1 | <!DOCTYPE html>
|
2 | <html lang="en">
|
3 | <head>
|
4 | <meta charset="utf-8"/>
|
5 | <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"/>
|
6 |
|
7 | <link rel="stylesheet" href="../assets/css/style.css"/>
|
8 | <title> GoJS Geometry Path Strings -- Northwoods Software </title>
|
9 | <link rel="stylesheet" href="../assets/css/prism.css" />
|
10 | </head>
|
11 | <script>
|
12 |
|
13 | window.diagrams = [];
|
14 | window.goCode = function(pre, w, h, parentid, animation) {
|
15 | window.diagrams.push([pre, w, h, parentid, animation]);
|
16 | }
|
17 | </script>
|
18 | <body>
|
19 | <nav id="navTop" class="w-full z-30 top-0 text-white bg-nwoods-primary">
|
20 | <div class="w-full container max-w-screen-lg mx-auto flex flex-wrap sm:flex-nowrap items-center justify-between mt-0 py-2">
|
21 | <div class="md:pl-4">
|
22 | <a class="text-white hover:text-white no-underline hover:no-underline
|
23 | font-bold text-2xl lg:text-4xl rounded-lg hover:bg-nwoods-secondary " href="../">
|
24 | <h1 class="mb-0 p-1 ">GoJS</h1>
|
25 | </a>
|
26 | </div>
|
27 | <button id="topnavButton" class="rounded-lg sm:hidden focus:outline-none focus:ring" aria-label="Navigation">
|
28 | <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
|
29 | <path id="topnavOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
|
30 | <path id="topnavClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
|
31 | </svg>
|
32 | </button>
|
33 | <div id="topnavList" class="hidden sm:block items-center w-auto mt-0 text-white p-0 z-20">
|
34 | <ul class="list-reset list-none font-semibold flex justify-end flex-wrap sm:flex-nowrap items-center px-0 pb-0">
|
35 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../learn/">Learn</a></li>
|
36 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../samples/">Samples</a></li>
|
37 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../intro/">Intro</a></li>
|
38 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../api/">API</a></li>
|
39 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/products/register.html">Register</a></li>
|
40 | <li class="p-1 sm:p-0"><a class="topnav-link" href="../download.html">Download</a></li>
|
41 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://forum.nwoods.com/c/gojs/11">Forum</a></li>
|
42 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/contact.html"
|
43 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a></li>
|
44 | <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/sales/index.html"
|
45 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a></li>
|
46 | </ul>
|
47 | </div>
|
48 | </div>
|
49 | <hr class="border-b border-gray-600 opacity-50 my-0 py-0" />
|
50 | </nav>
|
51 |
|
52 | <div class="md:flex flex-col md:flex-row md:min-h-screen w-full max-w-screen-xl mx-auto">
|
53 |
|
54 | <div id="navSide" class="flex flex-col w-full md:w-40 lg:w-48 text-gray-700 bg-white flex-shrink-0">
|
55 | <div class="flex-shrink-0 px-8 py-4">
|
56 | <button id="navButton" class="rounded-lg md:hidden focus:outline-none focus:ring" aria-label="Navigation">
|
57 | <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
|
58 | <path id="navOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
|
59 | <path id="navClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
|
60 | </svg>
|
61 | </button>
|
62 | </div>
|
63 | <nav id="navList" class="min-h-screen hidden md:block sidebar-nav flex-grow px-1 lg:px-4 pb-4 md:pb-0 md:overflow-y-auto break-words">
|
64 | <a href="index.html">Basics</a>
|
65 | <a href="buildingObjects.html">Building Parts</a>
|
66 | <a href="usingModels.html">Using Models</a>
|
67 | <a href="dataBinding.html">Data Binding</a>
|
68 | <a href="react.html">GoJS with React</a>
|
69 | <a href="angular.html">GoJS with Angular</a>
|
70 | <a href="textBlocks.html">TextBlocks</a>
|
71 | <a href="shapes.html">Shapes</a>
|
72 | <a href="pictures.html">Pictures</a>
|
73 | <a href="panels.html">Panels</a>
|
74 | <a href="tablePanels.html">Table Panels</a>
|
75 | <a href="brush.html">Brushes</a>
|
76 | <a href="sizing.html">Sizing Objects</a>
|
77 | <a href="itemArrays.html">Item Arrays</a>
|
78 | <a href="changedEvents.html">Changed Events</a>
|
79 | <a href="transactions.html">Transactions</a>
|
80 | <a href="viewport.html">Coordinates</a>
|
81 | <a href="initialView.html">Initial View</a>
|
82 | <a href="collections.html">Collections</a>
|
83 | <a href="links.html">Links</a>
|
84 | <a href="linkLabels.html">Link Labels</a>
|
85 | <a href="connectionPoints.html">Link Points</a>
|
86 | <a href="ports.html">Ports</a>
|
87 | <a href="nodes.html">Nodes</a>
|
88 | <a href="debugging.html">Debugging</a>
|
89 | <a href="layouts.html">Layouts</a>
|
90 | <a href="trees.html">Trees</a>
|
91 | <a href="subtrees.html">SubTrees</a>
|
92 | <a href="groups.html">Groups</a>
|
93 | <a href="subgraphs.html">SubGraphs</a>
|
94 | <a href="sizedGroups.html">Sized Groups</a>
|
95 | <a href="selection.html">Selection</a>
|
96 | <a href="highlighting.html">Highlighting</a>
|
97 | <a href="animation.html">Animation</a>
|
98 | <a href="toolTips.html">ToolTips</a>
|
99 | <a href="contextmenus.html">Context Menus</a>
|
100 | <a href="events.html">Diagram Events</a>
|
101 | <a href="tools.html">Tools</a>
|
102 | <a href="commands.html">Commands</a>
|
103 | <a href="permissions.html">Permissions</a>
|
104 | <a href="validation.html">Validation</a>
|
105 | <a href="HTMLInteraction.html">HTML Interaction</a>
|
106 | <a href="layers.html">Layers & Z-ordering</a>
|
107 | <a href="palette.html">Palette</a>
|
108 | <a href="overview.html">Overview</a>
|
109 | <a href="resizing.html">Resizing Diagrams</a>
|
110 | <a href="replacingDeleting.html">Replacing and Deleting</a>
|
111 | <a href="buttons.html">Buttons</a>
|
112 | <a href="templateMaps.html">Template Maps</a>
|
113 | <a href="legends.html">Legends and Titles</a>
|
114 | <a href="extensions.html">Extensions</a>
|
115 | <a href="geometry.html">Geometry Strings</a>
|
116 | <a href="grids.html">Grid Patterns</a>
|
117 | <a href="graduatedPanels.html">Graduated Panels</a>
|
118 | <a href="makingImages.html">Diagram Images</a>
|
119 | <a href="makingSVG.html">Diagram SVG</a>
|
120 | <a href="printing.html">Printing</a>
|
121 | <a href="serverSideImages.html">Server-side Images</a>
|
122 | <a href="nodeScript.html">GoJS in Node.js</a>
|
123 | <a href="testing.html">Testing</a>
|
124 | <a href="storage.html">Storage</a>
|
125 | <a href="performance.html">Performance</a>
|
126 | <a href="source.html">Building from Source</a>
|
127 | <a href="platforms.html">Platforms</a>
|
128 | <a href="deployment.html">Deployment</a>
|
129 | </nav>
|
130 | </div>
|
131 | <div class="pt-4 px-2 md:px-0 lg:px-4 pb-16 w-full overflow-hidden">
|
132 |
|
133 |
|
134 |
|
135 |
|
136 | <h1>Geometry Path Strings</h1>
|
137 | <p>
|
138 | The <b>GoJS</b> <a>Geometry</a> class controls the "shape" of a <a>Shape</a>,
|
139 | whereas the <a>Shape.fill</a> and <a>Shape.stroke</a> and other shape properties control the colors and appearance of the shape.
|
140 | For common shape figures, there are predefined geometries that can be used by setting <a>Shape.figure</a>.
|
141 | However one can also define custom geometries.
|
142 | </p>
|
143 | <p>
|
144 | One can construct any Geometry by allocating and initializing a <a>Geometry</a> of at least one <a>PathFigure</a> holding some <a>PathSegment</a>s.
|
145 | But you may find that using the string representation of a Geometry is easier to write and save in a database.
|
146 | Use the static method <a>Geometry,parse</a> or the <a>Shape.geometryString</a> property to transform a geometry path string into a <a>Geometry</a> object.
|
147 | </p>
|
148 | <p>
|
149 | See samples that make use of Geometries in the <a href="../samples/index.html#geometries">samples index</a>.
|
150 | </p>
|
151 |
|
152 | <h2 id="GeometryPathStringSyntax">Geometry Path String Syntax</h2>
|
153 | <p>
|
154 | The syntax for a geometry path string is an extension of the SVG path string syntax.
|
155 | The string consists of a number of commands, each a single letter followed by some command-specific numeric parameters.
|
156 | </p>
|
157 | <p>
|
158 | Below are the possible commands along with the parameters they take.
|
159 | The parameter notation <code>(x y)+</code> means that the command requires exactly two parameters,
|
160 | but there can be 1 or more sets of parameters for each command.
|
161 | For instance, the <code>L (x y)+</code> command can be written as <code>L 10 10 20 20</code> to denote two straight line segments.
|
162 | </p>
|
163 | <p>
|
164 | Commands written with an uppercase letter indicate absolute coordinates;
|
165 | lowercase commands specify coordinates relative to the last command.
|
166 | Some commands do not care about case because they do not take coordinates as arguments.
|
167 | </p>
|
168 |
|
169 | <ul style="padding-left: 0px; list-style: none;">
|
170 | <li><pre class="lang-js"><code>M (x y)+</code></pre> Move commands begin a new subpath in a <a>PathFigure</a>.
|
171 | One is essential to begin a PathFigure and therefore must be the first segment type in the path string,
|
172 | with the exception of a Fill command (<code>F</code>) that can precede it.
|
173 | <p>Additional sets of parameters for a move command are automatically considered Line commands,
|
174 | so <code>M 10 10 20 20</code> is identical to <code>M 10 10 L 20 20</code>.</li>
|
175 |
|
176 | <li><pre class="lang-js"><code>L (x y)+</code></pre> Line command adds a straight line segment from the previous point to the new point.</li>
|
177 | <li><pre class="lang-js"><code>H (x)+</code></pre> Horizontal line command specifies only an x value for a straight horizontal line.</li>
|
178 | <li><pre class="lang-js"><code>V (y)+</code></pre> Vertical line command specifies only a y value for a straight vertical line.</li>
|
179 |
|
180 | <li><pre class="lang-js"><code>Q (x1 y1 x y)+</code></pre> Quadratic Bezier Curves.
|
181 | <code>x1</code>, <code>y1</code> is the control point.
|
182 | See <a href="https://www.w3.org/TR/SVG/paths.html#PathDataQuadraticBezierCommands">SVG Quadratic Bezier command</a> for more details.</li>
|
183 | <li><pre class="lang-js"><code>T (x y)+</code></pre> Short-hand Quadratic Bezier Curves.
|
184 | The control point is calculated based on <a href="https://www.w3.org/TR/SVG/paths.html#PathDataQuadraticBezierCommands">SVG's path rules.</a></li>
|
185 |
|
186 | <li><pre class="lang-js"><code>C (x1 y1 x2 y2 x y)+</code></pre> Cubic Bezier Curves.
|
187 | <code>x1</code>, <code>y1</code> and <code>x2</code>, <code>y2</code> are the control points.
|
188 | See <a href="https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands">SVG Cubic Bezier command</a> for more details.</li>
|
189 | <li><pre class="lang-js"><code>S (x2 y2 x y)+</code></pre> Short-hand Cubic Bezier Curves.
|
190 | The two control points are calculated based on <a href="https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands">SVG's path rules.</a></li>
|
191 |
|
192 | <li><pre class="lang-js"><code>A (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+</code></pre> Elliptical Arcs.
|
193 | These follow the <a href="https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands">SVG arc conventions</a>.</li>
|
194 |
|
195 | <li><pre class="lang-js"><code>Z</code></pre> <code>Z</code> denotes that the current segment is closed.
|
196 | This is placed after the last segment of a subpath.
|
197 | There are no parameters, and case does not matter with this command.</li>
|
198 | </ul>
|
199 | <hr />
|
200 | <p>
|
201 | For detailed information on the SVG path strings, see the <a href="https://www.w3.org/TR/SVG/paths.html">W3C's page on SVG Paths</a>.
|
202 | <hr />
|
203 |
|
204 | <p>
|
205 | Additionally there are some tokens specific to <b>GoJS</b>:
|
206 | <ul style="padding-left: 0px; list-style: none;">
|
207 | <li><pre class="lang-js"><code>B (startAngle, sweepAngle, centerX, centerY, radiusX, radiusY) </code></pre> Arcs following <b>GoJS</b> canvas arc convention.
|
208 | These arcs create a new line from the last point in the subpath to the first point of an arc defined by the five arguments.
|
209 | Unlike all other commands with parameters, multiple sets of parameters are not allowed for B-arcs.
|
210 |
|
211 | <li><pre class="lang-js"><code>X</code></pre> Used before <code>M</code> commands to denote separate PathFigures instead of a subpath.
|
212 | There are no parameters, and case does not matter with this command.
|
213 | Separate PathFigures are important when different fills are desired per figure component.</li>
|
214 |
|
215 | <li><pre class="lang-js"><code>F</code></pre> The existence of this command specifies whether the current PathFigure is filled (true if <code>F</code> is present).
|
216 | This is placed at the beginning of a figure.
|
217 | There is an optional parameter that is currently ignored.
|
218 | Case does not matter with this command.</li>
|
219 |
|
220 | <li><pre class="lang-js"><code>U</code></pre> The existence of this command specifies whether the current PathFigure is shadowed (<strong>false</strong> if <code>U</code> is present.
|
221 | A shadowed PathFigure is the default).
|
222 | Shadows on shapes (and therefore PathFigures) only exist if <a>Part.isShadowed</a> is set to true on the containing part.
|
223 | This is placed at the beginning of a figure.
|
224 | Case does not matter with this command.</li>
|
225 | </ul>
|
226 |
|
227 | <h2 id="GeometryPathStringExamples">Geometry Path String Examples</h2>
|
228 | <p>
|
229 | Here is a simple usage of a geometry path string when initializing a <a>Shape</a> without setting <a>Shape.figure</a>:
|
230 | </p>
|
231 | <pre class="lang-js" id="s1"><code>
|
232 | diagram.add(
|
233 | $(go.Node,
|
234 | $(go.Shape,
|
235 | { geometryString: "F M120 0 L80 80 0 50z",
|
236 | fill: "lightgreen" })));
|
237 | </code></pre>
|
238 | <script> goCode("s1", 600, 140)</script>
|
239 | <p>
|
240 | Here is a geometry path string that uses quadratic Bezier curves:
|
241 | </p>
|
242 | <pre class="lang-js" id="s2"><code>
|
243 | diagram.add(
|
244 | $(go.Node,
|
245 | $(go.Shape,
|
246 | { geometryString: "F M0 0 L100 0 Q150 50 100 100 L0 100 Q50 50 0 0z",
|
247 | fill: "lightgreen" })));
|
248 | </code></pre>
|
249 | <script> goCode("s2", 600, 140)</script>
|
250 | <p>
|
251 | This geometry uses <b>GoJS</b> arcs:
|
252 | </p>
|
253 | <pre class="lang-js" id="s3"><code>
|
254 | diagram.add(
|
255 | $(go.Node, "Spot",
|
256 | $(go.Shape,
|
257 | { geometryString: "F M0 0 L80 0 B-90 90 80 20 20 20 L100 100 20 100 B90 90 20 80 20 20z",
|
258 | fill: "lightgreen" }),
|
259 | $(go.TextBlock, "custom shape")
|
260 | ));
|
261 | </code></pre>
|
262 | <script> goCode("s3", 600, 140)</script>
|
263 | <p>
|
264 | The following geometry uses <b>GoJS</b> arcs. Because the <a>Shape</a> is stretched to fit around the <a>TextBlock</a>,
|
265 | and because the default value of <a>Shape.geometryStretch</a> causes the <a>Geometry</a> to be stretched too,
|
266 | the custom geometry is also stretched to fit around the text.
|
267 | </p>
|
268 | <pre class="lang-js" id="s4"><code>
|
269 | diagram.add(
|
270 | $(go.Node, "Auto",
|
271 | $(go.Shape,
|
272 | { geometryString: "F M0 0 L.8 0 B-90 90 .8 .2 .2 .2 L1 1 .2 1 B90 90 .2 .8 .2 .2z",
|
273 | fill: "lightgreen" }),
|
274 | $(go.TextBlock, "custom shape",
|
275 | { margin: 4 })
|
276 | ));
|
277 | </code></pre>
|
278 | <script>goCode("s4", 600, 140)</script>
|
279 | <p>
|
280 | In the following Diagram we use a path string that contains three PathFigures.
|
281 | Note the <code>X</code> commands separating the figures and the <code>F</code> commands denoting fill.
|
282 | </p>
|
283 | <pre class="lang-js" id="a"><code>
|
284 | diagram.add(
|
285 | $(go.Part,
|
286 | $(go.Shape,
|
287 | { geometryString:
|
288 | "F M 0 0 l 30,30 10,10 35,0 0,-35 x m 50 0 l 0,-50 10,0 35,35 x" +
|
289 | "f m 50 0 l 0,-50 10,0 35,35z",
|
290 | strokeWidth: 10, stroke: "lightblue", fill: "gray" })
|
291 | ));
|
292 | </code></pre>
|
293 | <script>goCode("a", 600, 140)</script>
|
294 | The first two PathFigures are open; the first and third figures are filled.
|
295 | The <code>Z</code> command only closes the PathFigure that it ends.
|
296 |
|
297 | <p>
|
298 | In the following Diagram we use a path string that contains four PathFigures, two of which have a shadow.
|
299 | Note that figures are shadowed by default if the containing Part has <a>Part.isShadowed</a> set to true.
|
300 | To un-shadow specific path figures we use the <code>U</code> command.
|
301 | </p>
|
302 | <pre class="lang-js" id="a2"><code>
|
303 | diagram.add(
|
304 | $(go.Part,
|
305 | { isShadowed: true, shadowOffset: new go.Point(10, 10) },
|
306 | $(go.Shape,
|
307 | { geometryString:
|
308 | "F M 0 0 l 30,30 10,10 35,0 0,-35 x u m 50 0 l 0,-50 10,0 35,35 x" +
|
309 | "u f m 50 0 l 0,-50 10,0 35,35z x m 70 0 l 0,30 30,0 5,-35z",
|
310 | strokeWidth: 8, stroke: "lightblue", fill: "lightcoral" })
|
311 | ));
|
312 | </code></pre>
|
313 | <script>goCode("a2", 600, 140)</script>
|
314 | The first and last PathFigures are shadowed; the second and third are unshadowed.
|
315 |
|
316 | <h3 id="GeometryParse">Geometry.parse</h3>
|
317 | <p>
|
318 | Use the static method <a>Geometry,parse</a> to convert a <b>GoJS</b> syntax path string into a <a>Geometry</a>.
|
319 | </p>
|
320 | <pre class="lang-js" id="s11"><code>
|
321 | diagram.add(
|
322 | $(go.Node, "Horizontal",
|
323 | $(go.TextBlock, "Custom Triangle:"),
|
324 | $(go.Shape,
|
325 | { geometry: go.Geometry.parse("M120 0 L80 80 0 50z"), // Geometry is not filled
|
326 | fill: "green", background: "whitesmoke",
|
327 | stroke: "orange", strokeWidth: 2 })
|
328 | ));
|
329 | </code></pre>
|
330 | <script>goCode("s11", 600, 140)</script>
|
331 | <p>
|
332 | Note that even though a <a>Shape.fill</a> is specified, the shape does not appear filled.
|
333 | This is because the geometry's one <a>PathFigure</a> is not declared to be filled -- there is no <code>F</code> command.
|
334 | Importing SVG path strings that are filled also requires declaring that the geometry is filled.
|
335 | There are several ways to do that:
|
336 | </p>
|
337 | <ul>
|
338 | <li>
|
339 | Call <a>Geometry,fillPath</a> for converting the SVG path string to <b>GoJS</b> syntax before calling <a>Geometry,parse</a>.
|
340 | For literal SVG path strings it is often easiest just to prefix it with "F ".
|
341 | </li>
|
342 | <li>Call <a>Geometry,parse</a> with a second argument that is true.</li>
|
343 | <li>Modify the <a>Geometry</a> returned by <a>Geometry,parse</a>, by setting <a>PathFigure.isFilled</a> to true on the desired PathFigures.</li>
|
344 | </ul>
|
345 | <p>
|
346 | Here is the same example, but using a filled geometry path string.
|
347 | </p>
|
348 | <pre class="lang-js" id="s11a"><code>
|
349 | diagram.add(
|
350 | $(go.Node, "Horizontal",
|
351 | $(go.TextBlock, "Custom Triangle:"),
|
352 | $(go.Shape,
|
353 | { geometry: go.Geometry.parse("F M120 0 L80 80 0 50z"), // Geometry is filled
|
354 | fill: "green", background: "whitesmoke",
|
355 | stroke: "orange", strokeWidth: 2 })
|
356 | ));
|
357 | </code></pre>
|
358 | <script>goCode("s11a", 600, 140)</script>
|
359 |
|
360 | <p>
|
361 | All Geometry objects have bounds that contain the origin,
|
362 | so a geometry created with no points at x==0 or y==0 will have extra space to the left of it or above it.
|
363 | Note how there is extra space in the following node, causing the shape to appear farther away from the text and shifted down:
|
364 | </p>
|
365 | <pre class="lang-js" id="s12"><code>
|
366 | diagram.add(
|
367 | $(go.Node, "Horizontal",
|
368 | $(go.TextBlock, "Custom Triangle:"),
|
369 | $(go.Shape,
|
370 | { geometry: go.Geometry.parse("M120 50 L80 80 50 50z", true), // Geometry is filled
|
371 | fill: "green", background: "whitesmoke",
|
372 | stroke: "orange", strokeWidth: 2 })
|
373 | ));
|
374 | </code></pre>
|
375 | <script>goCode("s12", 600, 140)</script>
|
376 | <p>
|
377 | Often when importing SVG shapes created by drawing applications into <b>GoJS</b> we do not want any extra space above or to the left, so we need to normalize the geometry.
|
378 | There is a function for this, <a>Geometry.normalize</a>, which modifies the Geometry's points in-place and returns a Point describing the amount they were offset.
|
379 | </p>
|
380 | <pre class="lang-js" id="s12a"><code>
|
381 | var geo = go.Geometry.parse("M120 50 L80 80 50 50z", true);
|
382 | geo.normalize();
|
383 |
|
384 | diagram.add(
|
385 | $(go.Node, "Horizontal",
|
386 | $(go.TextBlock, "Custom Triangle:"),
|
387 | $(go.Shape,
|
388 | { geometry: geo, // normalized above
|
389 | fill: "green", background: "whitesmoke",
|
390 | stroke: "orange", strokeWidth: 2 })
|
391 | ));
|
392 | </code></pre>
|
393 | <script>goCode("s12a", 600, 140)</script>
|
394 |
|
395 | <h3 id="ShapeGeometryString">Shape.geometryString</h3>
|
396 | <p>
|
397 | The <a>Shape.geometryString</a> property setter parses a given <b>GoJS</b> path string as a Geometry, normalizes it,
|
398 | sets the <a>Shape.geometry</a> to this new Geometry, and offsets the Shape's position by the amount it was shifted in normalization.
|
399 | The positioning is useful when the shape is inside a <a>Panel,Position</a> panel.
|
400 | But when the shape is used in any other kind of panel (thus ignoring the <a>GraphObject.position</a>),
|
401 | it is still useful to remove the extra space so that the shape fits in well with the other objects in the panel.
|
402 | </p>
|
403 | <p>
|
404 | The example below adds three Parts with Shapes to the diagram.
|
405 | The first shape uses <a>Geometry,parse</a> to set the Shape's Geometry, the second one uses <a>Geometry,parse</a> and <a>Geometry.normalize</a>.
|
406 | The third uses <a>Shape.geometryString</a>.
|
407 | Note the difference in size between the first Part and the other two.
|
408 | </p>
|
409 | <pre class="lang-js" id="b"><code>
|
410 | var pathstring = "M30 100 C 50 50, 70 20, 100 100, 110, 130, 45, 150, 65, 100";
|
411 |
|
412 | // Just parsing the geometry
|
413 | diagram.add(
|
414 | $(go.Part, "Vertical",
|
415 | $(go.Shape,
|
416 | { geometry: go.Geometry.parse(pathstring),
|
417 | strokeWidth: 10, stroke: "lightcoral",
|
418 | background: "whitesmoke" }),
|
419 | $(go.TextBlock, "parse")
|
420 | ));
|
421 |
|
422 | // Parsing the geometry and normalizing it
|
423 | var geo = go.Geometry.parse(pathstring);
|
424 | geo.normalize();
|
425 | diagram.add(
|
426 | $(go.Part, "Vertical",
|
427 | $(go.Shape,
|
428 | { geometry: geo,
|
429 | strokeWidth: 10, stroke: "lightgreen",
|
430 | background: "whitesmoke" }),
|
431 | $(go.TextBlock, "parse/normalize")
|
432 | ));
|
433 |
|
434 | // Using geometryString to parse and normalize the geometry
|
435 | diagram.add(
|
436 | $(go.Part, "Vertical",
|
437 | $(go.Shape,
|
438 | { geometryString: pathstring,
|
439 | strokeWidth: 10, stroke: "lightblue",
|
440 | background: "whitesmoke" }),
|
441 | $(go.TextBlock, "geometryString")
|
442 | ));
|
443 |
|
444 | diagram.layout = $(go.GridLayout);
|
445 |
|
446 | // Select them all to more easily see their sizes
|
447 | diagram.commandHandler.selectAll();
|
448 | </code></pre>
|
449 | <script>goCode("b", 600, 180)</script>
|
450 |
|
451 |
|
452 | <h2 id="FlippingGeometriesHorizontallyAndVertically">Flipping Geometries Horizontally and Vertically</h2>
|
453 | <p>
|
454 | GoJS Geometries have several methods for modifying the geometry's points by a transformation matrix.
|
455 | We can use these methods to flip or mirror the geometries if needed.
|
456 | </p>
|
457 | <p>
|
458 | <code>geometry.scale(-1, 1)</code> will flip a geometry horizontally.
|
459 | <code>geometry.scale(1, -1)</code> will flip a geometry vertically.
|
460 | </p>
|
461 |
|
462 | <pre class="lang-js" id="b2"><code>
|
463 | var pathstring = "M30 100 C 50 50, 70 20, 100 100, 110, 130, 45, 150, 65, 100";
|
464 | var geo = go.Geometry.parse(pathstring);
|
465 | geo.normalize();
|
466 |
|
467 | diagram.add(
|
468 | $(go.Part, "Vertical",
|
469 | $(go.Shape,
|
470 | { geometry: geo,
|
471 | strokeWidth: 10, stroke: "lightgreen",
|
472 | background: "whitesmoke" }),
|
473 | $(go.TextBlock, "geometry from string\n(normalized)")
|
474 | ));
|
475 |
|
476 | var geo2 = geo.copy();
|
477 | geo2.scale(-1, 1); // flips a geometry horizontally
|
478 | diagram.add(
|
479 | $(go.Part, "Vertical",
|
480 | $(go.Shape,
|
481 | { geometry: geo2,
|
482 | strokeWidth: 10, stroke: "lightgreen",
|
483 | background: "whitesmoke" }),
|
484 | $(go.TextBlock, "flipped horizontally")
|
485 | ));
|
486 |
|
487 | var geo3 = geo.copy();
|
488 | geo3.scale(1, -1); // flips a geometry vertically
|
489 | diagram.add(
|
490 | $(go.Part, "Vertical",
|
491 | $(go.Shape,
|
492 | { geometry: geo3,
|
493 | strokeWidth: 10, stroke: "lightgreen",
|
494 | background: "whitesmoke" }),
|
495 | $(go.TextBlock, "flipped vertically")
|
496 | ));
|
497 |
|
498 | diagram.layout = $(go.GridLayout);
|
499 | </code></pre>
|
500 | <script>goCode("b2", 600, 180)</script>
|
501 |
|
502 | <h2 id="ConvertingPathStrings">Converting Path Strings</h2>
|
503 | <p>
|
504 | The static method <a>Geometry,stringify</a> can be used to output a Geometry as a string.
|
505 | This string will have the <b>GoJS</b> path string syntax.
|
506 | You can use Geometry.stringify and Geometry.parse to data bind custom shape geometries.
|
507 | <p>
|
508 | <code>Geometry.parse(Geometry.stringify(myGeometry))</code> will return a geometry equal to <code>myGeometry</code>,
|
509 | though if myGeometry was created from a string, the string itself is not guaranteed to be the same.
|
510 | If you merely want to copy a Geometry you should use <a>Geometry.copy</a>.
|
511 | <p>
|
512 | <pre class="lang-js"><code>
|
513 | // These path strings represent identical geometries:
|
514 | var a = "m0 0 t 50 50, q 40 20, 50 10 h 10 v -23 l 45, 5, 65, 100"
|
515 | var b = "M0 0 Q0 0 50 50 Q90 70 100 60 L110 60 L110 37 L155 42 L220 142"
|
516 | go.Geometry.stringify(Geometry.parse(a)); // returns the string in b
|
517 | go.Geometry.stringify(Geometry.parse(b)); // returns the string in b
|
518 | </code></pre>
|
519 |
|
520 | <p>
|
521 | Because of the additional non-SVG commands, a string generated from <a>Geometry,stringify</a> will not necessarily be a valid SVG path.
|
522 | </p>
|
523 | <p>
|
524 | The static method <a>Geometry,fillPath</a> takes a path string of either syntax and adds <code>F</code> tokens before each PathFigure that does not have them.
|
525 | Because SVG path strings are not considered to be "filled" by themselves,
|
526 | if you are converting an SVG Path shape to <b>GoJS</b> you will want to call <a>Geometry,fillPath</a> on the SVG string.
|
527 | </p>
|
528 | <pre class="lang-js"><code>
|
529 | go.Geometry.fillPath("M0 0 L20 20 L20 0");
|
530 | // returns "F M0 0 L20 20 L20 0"
|
531 | </code></pre>
|
532 | The result can then be passed to <a>Geometry,parse</a> or <a>Shape.geometryString</a>.
|
533 |
|
534 | <h2 id="ParameterizedGeometries">Parameterized Geometries</h2>
|
535 | <p>
|
536 | Although individual <a>Geometry</a> objects cannot be dynamically parameterized based on the intended size or other properties,
|
537 | the <a>Shape</a> class does support such parameterization via <a>Shape,defineFigureGenerator</a>.
|
538 | When you set or bind the <a>Shape.figure</a> property, the shape will call the named figure generator
|
539 | to generate a Geometry appropriate for the desired width and height and other Shape properties.
|
540 | </p>
|
541 | <p>
|
542 | You can see the definitions of all of the predefined figures in the extensions file:
|
543 | <a href="../extensions/Figures.js" target="_blank">Figures.js</a>.
|
544 | </p>
|
545 | </div>
|
546 | </div>
|
547 |
|
548 | <div class="bg-nwoods-primary">
|
549 | <section class="max-w-screen-lg text-white container mx-auto py-2 px-12">
|
550 | <p id="version" class="leading-none mb-2 my-4">GoJS</p>
|
551 | </section>
|
552 | </div><footer class="bg-nwoods-primary text-white">
|
553 | <div class="container max-w-screen-lg mx-auto px-8">
|
554 | <div class="w-full py-6">
|
555 |
|
556 | <div class="max-w-screen-lg xl:max-w-screen-xl mx-auto px-4 sm:px-6 md:px-8">
|
557 | <ul class="text-sm font-medium pb-14 sm:pb-20 grid grid-cols-1 sm:grid-cols-3 gap-y-10">
|
558 | <li class="list-none row-span-2">
|
559 | <h2 class="text-base font-semibold tracking-wide">GoJS</h2>
|
560 | <ul class="list-none space-y-4 md:space-y-1 px-0">
|
561 | <li>
|
562 | <a href="../samples/index.html">Samples</a>
|
563 | </li>
|
564 | <li>
|
565 | <a href="../learn/index.html">Learn</a>
|
566 | </li>
|
567 | <li>
|
568 | <a href="../intro/index.html">Intro</a>
|
569 | </li>
|
570 | <li>
|
571 | <a href="../api/index.html">API</a>
|
572 | </li>
|
573 | <li>
|
574 | <a href="../changelog.html">Changelog</a>
|
575 | </li>
|
576 | <li>
|
577 | <a href="https://github.com/NorthwoodsSoftware/GoJS">GitHub</a>
|
578 | </li>
|
579 | </ul>
|
580 | </li>
|
581 | <li class="list-none row-span-2">
|
582 | <h2 class="text-base font-semibold tracking-wide">Support</h2>
|
583 | <ul class="list-none space-y-4 md:space-y-1 px-0">
|
584 | <li>
|
585 | <a href="https://www.nwoods.com/contact.html"
|
586 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a>
|
587 | </li>
|
588 | <li>
|
589 | <a href="https://forum.nwoods.com/c/gojs">Forum</a>
|
590 | </li>
|
591 | <li>
|
592 | <a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a>
|
593 | </li>
|
594 | <li>
|
595 | <a href="https://www.nwoods.com/sales/index.html"
|
596 | target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a>
|
597 | </li>
|
598 | <li>
|
599 | <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">Videos</a>
|
600 | </li>
|
601 | </ul>
|
602 | </li>
|
603 | <li class="list-none row-span-2">
|
604 | <h2 class="text-base font-semibold tracking-wide">Company</h2>
|
605 | <ul class="list-none space-y-4 md:space-y-1 px-0">
|
606 | <li>
|
607 | <a href="https://www.nwoods.com">Northwoods</a>
|
608 | </li>
|
609 | <li>
|
610 | <a href="https://www.nwoods.com/about.html">About Us</a>
|
611 | </li>
|
612 | <li>
|
613 | <a href="https://www.nwoods.com/contact.html">Contact Us</a>
|
614 | </li>
|
615 | <li>
|
616 | <a href="https://twitter.com/northwoodsgo">Twitter</a>
|
617 | </li>
|
618 |
|
619 | </ul>
|
620 | </li>
|
621 | </ul>
|
622 |
|
623 |
|
624 | <p class="text-sm text-gray-100 md:mb-6">
|
625 | Copyright 1998-2021 <a class="text-white" href="https://www.nwoods.com">Northwoods Software</a>
|
626 | </p>
|
627 | </div>
|
628 | </div>
|
629 | </footer> </body>
|
630 |
|
631 | <script async src="https://www.googletagmanager.com/gtag/js?id=UA-1506307-5"></script>
|
632 | <script>
|
633 | window.dataLayer = window.dataLayer || [];
|
634 | function gtag(){dataLayer.push(arguments);}
|
635 | gtag('js', new Date()); gtag('config', 'UA-1506307-5');
|
636 | var getOutboundLink = function(url, label) {
|
637 | gtag('event', 'click', {
|
638 | 'event_category': 'outbound',
|
639 | 'event_label': label,
|
640 | 'transport_type': 'beacon'
|
641 | });
|
642 | }
|
643 |
|
644 |
|
645 | var topButton = document.getElementById("topnavButton");
|
646 | var topnavList = document.getElementById("topnavList");
|
647 | topButton.addEventListener("click", function() {
|
648 | this.classList.toggle("active");
|
649 | topnavList.classList.toggle("hidden");
|
650 | document.getElementById("topnavOpen").classList.toggle("hidden");
|
651 | document.getElementById("topnavClosed").classList.toggle("hidden");
|
652 | });
|
653 | </script>
|
654 | <script src="../assets/js/prism.js"></script>
|
655 | <script src="../release/go.js"></script>
|
656 | <script src="../assets/js/goDoc.js"></script>
|
657 | <script>
|
658 | document.addEventListener("DOMContentLoaded", function() {
|
659 | if (window.go) document.getElementById('version').textContent = "GoJS version " + go.version;
|
660 | if (window.goDoc) window.goDoc();
|
661 | var d = window.diagrams;
|
662 | for (var i = 0; i < d.length; i++) {
|
663 | var dargs = d[i];
|
664 | goCodeExecute(dargs[0], dargs[1], dargs[2], dargs[3], dargs[4]);
|
665 | }
|
666 | if (window.extra) window.extra();
|
667 | });
|
668 | </script>
|
669 | </html>
|