gojs
Version:
Interactive diagrams, charts, and graphs, such as trees, flowcharts, orgcharts, UML, BPMN, or business diagrams
316 lines (305 loc) • 15.6 kB
HTML
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GoJS Sizing of GraphObjects -- Northwoods Software</title>
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
<script src="../release/go.js"></script>
<script src="../extensions/Figures.js"></script>
<script src="goIntro.js"></script>
</head>
<body onload="goIntro()">
<div id="container" class="container-fluid">
<div id="content">
<h1>Sizing GraphObjects</h1>
<p>
The size of a <a>GraphObject</a> is determined by the values of the <a>GraphObject.desiredSize</a>,
<a>GraphObject.minSize</a>, <a>GraphObject.maxSize</a> and <a>GraphObject.stretch</a> properties.
The actual size of an object after its containing panel measures and arranges it is given by several
read-only properties: <a>GraphObject.naturalBounds</a>, <a>GraphObject.measuredBounds</a>, and <a>GraphObject.actualBounds</a>.
</p>
<p>
The <a>GraphObject.width</a> property is exactly the same as the <a>Size.width</a> component of the <a>GraphObject.desiredSize</a>.
Similarly, the <a>GraphObject.height</a> property corresponds to the desiredSize's height.
The default value of <a>GraphObject.desiredSize</a> is <code>(NaN, NaN)</code> -- meaning that the size must be computed.
One can set the width to a real number and leave the height to be <code>NaN</code>, or vice-versa.
</p>
<p>
Users can also change the size of an object within a Part via the <a>ResizingTool</a>: Introduction to the <a href="tools.html#ResizingTool">ResizingTool</a>.
</p>
<h3 id="DesiredSizeMinSizeAndMaxSize">DesiredSize, MinSize, and MaxSize</h3>
<p>
When the <a>GraphObject.desiredSize</a> property is set to real numbers it gets that as its natural size.
When the desiredSize property is not set but there is a <a>GraphObject.stretch</a> value,
it will get the size of the available space.
When desiredSize is not set and there is no stretch,
an object prefers being its natural size,
based on the type of object that it is and the other properties that it has.
</p>
<p>
But the effective width and effective height, whether given by desiredSize or computed,
are each constrained by the <a>GraphObject.maxSize</a> and by the <a>GraphObject.minSize</a>.
The minimum size takes precedence over the maximum size in case of conflict.
</p>
<p>
The size for a GraphObject in a Table <a>Panel</a> may also be constrained by the width
of the column and the height of the row that the object is in.
</p>
<pre class="lang-js" id="shapeSizes">
diagram.add(
$(go.Part,
$(go.Panel, "Table",
{ defaultAlignment: go.Spot.Left },
$(go.RowColumnDefinition, { column: 0, width: 200 }),
$(go.RowColumnDefinition, { column: 1, width: 15 }),
$(go.Shape, "Rectangle",
{ row: 0, column: 0, fill: "green",
width: 100, height: 20 }),
$(go.TextBlock, { row: 0, column: 2,
text: "desiredSize: 100x20, no minSize, no maxSize" }),
$(go.Shape, "Rectangle",
{ row: 1, column: 0, fill: "red",
width: 100, height: 20,
minSize: new go.Size(150, 10) }),
$(go.TextBlock, { row: 1, column: 2,
text: "desired: 100x20, min: 150x10" }),
$(go.Shape, "Rectangle",
{ row: 2, column: 0, fill: "yellow",
width: 100, height: 20,
maxSize: new go.Size(50, 300) }),
$(go.TextBlock, { row: 2, column: 2,
text: "desired: 100x20, max: 50x300" }),
$(go.Shape, "Rectangle",
{ row: 3, column: 0, fill: "red",
width: 100, height: 20,
minSize: new go.Size(150, 10), maxSize: new go.Size(50, 300) }),
$(go.TextBlock, { row: 3, column: 2,
text: "desired: 100x20, min: 150x10, max: 50x300" })
)
));
</pre>
<script>goCode("shapeSizes", 600, 120)</script>
<h3 id="MeasuredAndActualSizes">Measured and Actual Sizes</h3>
<p>
Every GraphObject also has a <a>GraphObject.measuredBounds</a>,
which describes how big the object seems to be, and a <a>GraphObject.actualBounds</a>,
which describes the position and size of an object.
These read-only properties take into account any non-zero <a>GraphObject.angle</a> or non-unitary <a>GraphObject.scale</a>.
These measurements are in the containing <a>Panel</a>'s coordinate system.
</p>
<pre class="lang-js" id="sizedShapes">
function getSizeString(s) {
return s.width.toFixed(2) + "x" + s.height.toFixed(2);
}
var table =
$(go.Part, "Table",
$(go.Shape, { name: "A", row: 0, column: 1,
figure: "Club", fill: "green", background: "lightgray",
width: 40, height: 40,
}), // default angle is zero; default scale is one
$(go.Shape, { name: "B", row: 0, column: 2,
figure: "Club", fill: "green", background: "lightgray",
width: 40, height: 40,
angle: 30 }),
$(go.Shape, { name: "C", row: 0, column: 3,
figure: "Club", fill: "green", background: "lightgray",
width: 40, height: 40,
scale: 1.5 }),
$(go.Shape, { name: "D", row: 0, column: 4,
figure: "Club", fill: "green", background: "lightgray",
width: 40, height: 40,
angle: 30, scale: 1.5 }),
$(go.TextBlock, { row: 1, column: 1, margin: 4 },
new go.Binding("text", "naturalBounds", getSizeString).ofObject("A")),
$(go.TextBlock, { row: 1, column: 2, margin: 4 },
new go.Binding("text", "naturalBounds", getSizeString).ofObject("B")),
$(go.TextBlock, { row: 1, column: 3, margin: 4 },
new go.Binding("text", "naturalBounds", getSizeString).ofObject("C")),
$(go.TextBlock, { row: 1, column: 4, margin: 4 },
new go.Binding("text", "naturalBounds", getSizeString).ofObject("D")),
$(go.TextBlock, { row: 2, column: 1, margin: 4 },
new go.Binding("text", "measuredBounds", getSizeString).ofObject("A")),
$(go.TextBlock, { row: 2, column: 2, margin: 4 },
new go.Binding("text", "measuredBounds", getSizeString).ofObject("B")),
$(go.TextBlock, { row: 2, column: 3, margin: 4 },
new go.Binding("text", "measuredBounds", getSizeString).ofObject("C")),
$(go.TextBlock, { row: 2, column: 4, margin: 4 },
new go.Binding("text", "measuredBounds", getSizeString).ofObject("D")),
$(go.TextBlock, { row: 3, column: 1, margin: 4 },
new go.Binding("text", "actualBounds", getSizeString).ofObject("A")),
$(go.TextBlock, { row: 3, column: 2, margin: 4 },
new go.Binding("text", "actualBounds", getSizeString).ofObject("B")),
$(go.TextBlock, { row: 3, column: 3, margin: 4 },
new go.Binding("text", "actualBounds", getSizeString).ofObject("C")),
$(go.TextBlock, { row: 3, column: 4, margin: 4 },
new go.Binding("text", "actualBounds", getSizeString).ofObject("D")),
$(go.TextBlock, "naturalBounds:", { row: 1, column: 0, alignment: go.Spot.Left }),
$(go.TextBlock, "measuredBounds:", { row: 2, column: 0, alignment: go.Spot.Left }),
$(go.TextBlock, "actualBounds:", { row: 3, column: 0, alignment: go.Spot.Left })
);
diagram.add(table);
setTimeout(function() {
table.data = {}; // cause bindings to be evaluated after Shapes are measured
}, 500);
</pre>
<script>goCode("sizedShapes", 600, 180)</script>
<p>
Note that the size of the regular 40x40 shape is 41x41.
The additional size is due to the thickness of the pen (<a>Shape.strokeWidth</a>) used to outline the shape.
Rotating or increasing the scale causes the 40x40 shape to actually take up significantly more space.
</p>
<p>
To summarize: the <a>GraphObject.desiredSize</a> (a.k.a. <a>GraphObject.width</a> and <a>GraphObject.height</a>)
and the <a>GraphObject.naturalBounds</a> are in the object's local coordinate system.
The <a>GraphObject.minSize</a>, <a>GraphObject.maxSize</a>, <a>GraphObject.margin</a>, <a>GraphObject.measuredBounds</a>, and
<a>GraphObject.actualBounds</a> are all in the containing <a>Panel</a>'s coordinate system, or in document
coordinates if there is no such panel because it is a <a>Part</a>.
</p>
<h3 id="StretchingOfGraphObjects">Stretching of GraphObjects</h3>
<p>
When you specify a <a>GraphObject.stretch</a> value other than <a>GraphObject,None</a>,
the object will stretch or contract to fill the available space.
However, the <a>GraphObject.maxSize</a> and <a>GraphObject.minSize</a> properties still limit the size.
</p>
<p>
But setting the <a>GraphObject.desiredSize</a> (or equivalently, the <a>GraphObject.width</a> and/or <a>GraphObject.height</a>)
will cause any stretch value to be ignored.
</p>
<p>
In the following examples the left column is constrained to have a width of 200.
</p>
<pre class="lang-js" id="stretchSizes">
diagram.add(
$(go.Part,
$(go.Panel, "Table",
{ defaultAlignment: go.Spot.Left },
$(go.RowColumnDefinition, { column: 0, width: 200 }),
$(go.RowColumnDefinition, { column: 1, width: 15 }),
$(go.Shape, "Rectangle",
{ row: 0, column: 0, fill: "green",
stretch: go.GraphObject.Fill }),
$(go.TextBlock, { row: 0, column: 2,
text: "stretch: Fill, no minSize, no maxSize" }),
$(go.Shape, "Rectangle",
{ row: 1, column: 0, fill: "red",
stretch: go.GraphObject.Fill,
minSize: new go.Size(150, 10) }),
$(go.TextBlock, { row: 1, column: 2,
text: "stretch: Fill, min: 150x10" }),
$(go.Shape, "Rectangle",
{ row: 2, column: 0, fill: "yellow",
stretch: go.GraphObject.Fill,
maxSize: new go.Size(50, 300) }),
$(go.TextBlock, { row: 2, column: 2,
text: "stretch: Fill, max: 50x300" }),
$(go.Shape, "Rectangle",
{ row: 3, column: 0, fill: "red",
stretch: go.GraphObject.Fill,
minSize: new go.Size(150, 10), maxSize: new go.Size(50, 300) }),
$(go.TextBlock, { row: 3, column: 2,
text: "stretch: Fill, min: 150x10, max: 50x300" }),
$(go.Shape, "Rectangle",
{ row: 4, column: 0, fill: "red",
width: 100, stretch: go.GraphObject.Fill }),
$(go.TextBlock, { row: 4, column: 2,
text: "desired width & stretch: ignore stretch" })
)
));
</pre>
<script>goCode("stretchSizes", 600, 120)</script>
<p>
To summarize, if <a>GraphObject.desiredSize</a> is set, any <a>GraphObject.stretch</a> is ignored.
If <a>GraphObject.maxSize</a> conflicts with that value, it takes precedence.
And if <a>GraphObject.minSize</a> conflicts with those values, it takes precedence.
The width values are constrained independently of the height values.
</p>
<h2 id="StretchAndAlignment">Stretch and Alignment</h2>
<p>
The size of a <a>GraphObject</a> in a <a>Panel</a> is determined by many factors.
The <a>GraphObject.stretch</a> property specifies whether the width and/or height should take up all
of the space given to it by the Panel.
When the width and/or height is not stretched to fill the given space,
the <a>GraphObject.alignment</a> property controls where the object is placed if it is smaller than available space.
One may also stretch the width while aligning vertically, just as one may also
stretch vertically while aligning along the X axis.
</p>
<p>
The alignment value for a GraphObject, if not given by the value of <a>GraphObject.alignment</a>, may be inherited.
If the object is in a Table Panel, the value may inherit from the RowColumnDefinitions of
the row and of the column that the object is in.
Finally the value may be inherited from the <a>Panel.defaultAlignment</a> property.
</p>
<p>
If you specify a fill stretch (horizontal or vertical or both) and an alignment, the alignment will be ignored.
Basically if an object is exactly the size that is available to it, there is only one position for it, so all alignments are the same.
</p>
<h3 id="AlignmentOfShapes">Alignment of Shapes</h3>
<pre class="lang-js" id="shapeAlignment">
diagram.add(
$(go.Part,
$(go.Panel, "Table",
{ defaultAlignment: go.Spot.Left },
$(go.RowColumnDefinition, { column: 0, width: 200 }),
$(go.RowColumnDefinition, { column: 1, width: 15 }),
$(go.Shape, "Rectangle",
{ row: 0, column: 0, fill: "lightblue",
width: 100, height: 20, alignment: go.Spot.Left }),
$(go.TextBlock, { row: 0, column: 2, text: "alignment: Left" }),
$(go.Shape, "Rectangle",
{ row: 1, column: 0, fill: "lightblue",
width: 100, height: 20, alignment: go.Spot.Center }),
$(go.TextBlock, { row: 1, column: 2, text: "alignment: Center" }),
$(go.Shape, "Rectangle",
{ row: 2, column: 0, fill: "lightblue",
width: 100, height: 20, alignment: go.Spot.Right }),
$(go.TextBlock, { row: 2, column: 2, text: "alignment: Right" }),
$(go.Shape, "Rectangle",
{ row: 3, column: 0, fill: "yellow",
height: 20, stretch: go.GraphObject.Horizontal }),
$(go.TextBlock, { row: 3, column: 2, text: "stretch: Horizontal" }),
$(go.Shape, "Rectangle",
{ row: 4, column: 0, fill: "yellow",
height: 20, stretch: go.GraphObject.Horizontal, alignment: go.Spot.Right }),
$(go.TextBlock, { row: 4, column: 2,
text: "stretch: Horizontal, ignore alignment" })
)
));
</pre>
<script>goCode("shapeAlignment", 600, 120)</script>
<p>
When the element is larger than the available space, the <a>GraphObject.alignment</a>
property still controls where the element is positioned.
However the element will be clipped to fit.
</p>
<p>
To make things clearer in the following examples we have made the shape stroke thicker
and added a margin to separate the shapes.
</p>
<pre class="lang-js" id="bigShapeAlignment">
diagram.add(
$(go.Part,
$(go.Panel, "Table",
{ defaultAlignment: go.Spot.Left },
$(go.RowColumnDefinition, { column: 0, width: 200 }),
$(go.RowColumnDefinition, { column: 1, width: 15 }),
$(go.Shape, "Rectangle",
{ row: 0, column: 0, fill: "lightblue", strokeWidth: 2,
width: 300, height: 20, margin: 2, alignment: go.Spot.Left }),
$(go.TextBlock, { row: 0, column: 2, text: "big obj alignment: Left" }),
$(go.Shape, "Rectangle",
{ row: 1, column: 0, fill: "lightblue", strokeWidth: 2,
width: 300, height: 20, margin: 2, alignment: go.Spot.Center }),
$(go.TextBlock, { row: 1, column: 2, text: "big obj alignment: Center" }),
$(go.Shape, "Rectangle",
{ row: 2, column: 0, fill: "lightblue", strokeWidth: 2,
width: 300, height: 20, margin: 2, alignment: go.Spot.Right }),
$(go.TextBlock, { row: 2, column: 2, text: "big obj alignment: Right" })
)
));
</pre>
<script>goCode("bigShapeAlignment", 600, 100)</script>
</div>
</div>
</body>
</html>