UNPKG

25.3 kBJavaScriptView Raw
1//import * as createSVGPathCalculator from "point-at-length";
2export const createSVGPathCalculator = require("point-at-length");
3import { toPoints } from "svg-points";
4export class SVGPointElement {
5 constructor(x, y) {
6 this.x = x;
7 this.y = y;
8 }
9}
10export class SVGPathSegment {
11 constructor(type, values) {
12 this.type = type;
13 this.values = values;
14 }
15}
16export class SVGPath {
17 constructor(points, getPathDataFromPoints) {
18 this.getPathStringFromPathData = (pathData) => {
19 return pathData
20 .map(function (pathSegment) {
21 return pathSegment.type + pathSegment.values.join(",");
22 })
23 .join("");
24 };
25 this.getPointAtLength = (length) => {
26 const [x, y] = this.pathCalculator.at(length);
27 return new SVGPointElement(x, y);
28 };
29 this.getTotalLength = () => {
30 return this.pathCalculator.length();
31 };
32 this.getPathData = (settings) => {
33 return this.pathData;
34 };
35 this.setPathData = (pathData) => {
36 this.pathData = pathData;
37 this.d = this.getPathStringFromPathData(this.pathData);
38 this.pathCalculator = createSVGPathCalculator(this.d);
39 };
40 this.getPointAtPosition = (position) => {
41 const totalLength = this.getTotalLength();
42 return this.getPointAtLength(position * totalLength);
43 };
44 this.getPathDataFromPoints = getPathDataFromPoints;
45 this.pathData = getPathDataFromPoints(points);
46 this.d = this.getPathStringFromPathData(this.pathData);
47 this.points = toPoints({
48 type: "path",
49 d: this.d
50 });
51 this.pathCalculator = createSVGPathCalculator(this.d);
52 }
53}
54export function changeDirection(currentDirection) {
55 var xDirection = Math.abs(Math.abs(currentDirection[0]) - 1);
56 var yDirection = Math.abs(Math.abs(currentDirection[1]) - 1);
57 return [xDirection, yDirection];
58}
59export class StraightLine extends SVGPath {
60 constructor(points) {
61 super(points, function getPathDataFromPoints(points) {
62 const { x: x0, y: y0 } = points[0];
63 const { x: x1, y: y1 } = points[points.length - 1];
64 return [
65 new SVGPathSegment("M", [x0, y0]),
66 new SVGPathSegment("L", [x1, y1])
67 ];
68 });
69 }
70}
71export class ElbowLine extends SVGPath {
72 constructor(points) {
73 super(points, function getPathDataFromPoints(points) {
74 var pointCount = points.length;
75 var firstPoint = points[0], lastPoint = points[pointCount - 1];
76 var pathData = [new SVGPathSegment("M", [firstPoint.x, firstPoint.y])];
77 var direction = [];
78 if (firstPoint.orientation) {
79 direction.push(firstPoint.orientation[0]);
80 direction.push(firstPoint.orientation[1]);
81 }
82 else {
83 console.error("points");
84 console.error(points);
85 throw new Error("No orientation specified for elbowline edge w/ points logged above");
86 }
87 points.forEach(function (point, index) {
88 if (index > 0 && index < pointCount) {
89 var x0 = Math.abs(direction[0]) * (points[index].x - points[index - 1].x) +
90 points[index - 1].x, y0 = Math.abs(direction[1]) * (points[index].y - points[index - 1].y) +
91 points[index - 1].y;
92 pathData.push(new SVGPathSegment("L", [x0, y0]));
93 direction = changeDirection(direction);
94 }
95 });
96 pathData.push(new SVGPathSegment("L", [lastPoint.x, lastPoint.y]));
97 return pathData;
98 });
99 }
100}
101export class SegmentedLine extends SVGPath {
102 constructor(points) {
103 super(points, function getPathDataFromPoints(points) {
104 var firstPoint = points[0];
105 var pathData = [new SVGPathSegment("M", [firstPoint.x, firstPoint.y])];
106 points.forEach(function (point, index) {
107 if (index > 0) {
108 pathData.push(new SVGPathSegment("L", [point.x, point.y]));
109 }
110 });
111 return pathData;
112 });
113 }
114}
115// Returns the dot product of the given four-element vectors.
116function d3_svg_lineDot4(a, b) {
117 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
118}
119// Matrix to transform basis (b-spline) control points to bezier
120// control points. Derived from FvD 11.2.8.
121const d3_svg_lineBasisBezier1 = [0, 2 / 3, 1 / 3, 0];
122const d3_svg_lineBasisBezier2 = [0, 1 / 3, 2 / 3, 0];
123const d3_svg_lineBasisBezier3 = [0, 1 / 6, 2 / 3, 1 / 6];
124// Pushes a "C" Bézier curve onto the specified path array, given the
125// two specified four-element arrays which define the control points.
126function lineBasisBezier(pathData, x, y) {
127 var pointsForBezier = [];
128 pointsForBezier.push([
129 d3_svg_lineDot4(d3_svg_lineBasisBezier1, x),
130 d3_svg_lineDot4(d3_svg_lineBasisBezier1, y)
131 ]);
132 pointsForBezier.push([
133 d3_svg_lineDot4(d3_svg_lineBasisBezier2, x),
134 d3_svg_lineDot4(d3_svg_lineBasisBezier2, y)
135 ]);
136 pointsForBezier.push([
137 d3_svg_lineDot4(d3_svg_lineBasisBezier3, x),
138 d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)
139 ]);
140 pathData.push(new SVGPathSegment("C", pointsForBezier));
141}
142export class CurvedLine extends SVGPath {
143 constructor(points, markerStart, markerEnd) {
144 super(points, function getPathDataFromPoints(elbowPoints, markerStart, markerEnd) {
145 // modified from d3js: https://github.com/mbostock/d3/blob/ed54503fc7781d8bfe9e9fe125b76b9bbb5ac05c/src/svg/line.js
146 // TODO this code is kind of hacky. it seems to work OK, but it's probably confusing and should be refactored for readability/maintainability.
147 var elbowPointCount = elbowPoints.length;
148 var firstPoint = elbowPoints[0];
149 var lastPoint = elbowPoints[elbowPointCount - 1];
150 var points = [];
151 points.push(firstPoint);
152 var lastSegment = [];
153 var pathData = [new SVGPathSegment("M", [firstPoint.x, firstPoint.y])];
154 var direction = [];
155 if (firstPoint.orientation) {
156 const orientation = firstPoint.orientation;
157 direction.push(orientation[0]);
158 direction.push(orientation[1]);
159 }
160 else {
161 console.error("points");
162 console.error(points);
163 throw new Error("No orientation specified for curvedline edge w/ points logged above");
164 }
165 // for curves, I'm calculating and using the points representing the elbow vertices, from the given points (which represent the first point, any elbow segment mid-points and the last point).
166 // I'm making sure the curve passes through the midpoint of the marker side that is furthest away from the node it is attached to
167 // TODO this code might be confusing, because it involves redefining the points. Look at refactoring it for readability.
168 var markerHeightFactor = 0.75;
169 if (!!markerStart &&
170 firstPoint.orientation &&
171 typeof firstPoint.orientation[0] !== "undefined" &&
172 typeof firstPoint.orientation[1] !== "undefined") {
173 var firstPointWithOffset = {};
174 var firstOffset;
175 var firstMarkerData = { x: 0, y: 0, markerWidth: 12, markerHeight: 12 };
176 if (!!firstMarkerData) {
177 firstOffset = markerHeightFactor * firstMarkerData.markerHeight;
178 }
179 else {
180 firstOffset = 12;
181 }
182 firstPointWithOffset.x =
183 firstPoint.orientation[0] * firstOffset + firstPoint.x;
184 firstPointWithOffset.y =
185 firstPoint.orientation[1] * firstOffset + firstPoint.y;
186 pathData.push(new SVGPathSegment("L", [
187 firstPointWithOffset.x,
188 firstPointWithOffset.y
189 ]));
190 points[0] = firstPointWithOffset;
191 }
192 if (!!markerEnd &&
193 lastPoint.orientation &&
194 typeof lastPoint.orientation[0] !== "undefined" &&
195 typeof lastPoint.orientation[1] !== "undefined") {
196 lastSegment.push(new SVGPathSegment("L", [lastPoint.x, lastPoint.y]));
197 var lastPointWithOffset = {};
198 var lastOffset;
199 var lastMarkerData = { x: 0, y: 0, markerWidth: 12, markerHeight: 12 };
200 if (!!lastMarkerData) {
201 lastOffset = markerHeightFactor * lastMarkerData.markerHeight;
202 }
203 else {
204 lastOffset = 12;
205 }
206 lastPointWithOffset.x =
207 lastPoint.orientation[0] * lastOffset + lastPoint.x;
208 lastPointWithOffset.y =
209 lastPoint.orientation[1] * lastOffset + lastPoint.y;
210 elbowPoints[elbowPointCount - 1] = lastPoint = lastPointWithOffset;
211 }
212 elbowPoints.forEach(function (elbowPoint, index) {
213 var x0, y0, x1, y1;
214 if (index > 0 && index < elbowPointCount) {
215 x0 =
216 Math.abs(direction[0]) *
217 (elbowPoints[index].x - elbowPoints[index - 1].x) +
218 elbowPoints[index - 1].x;
219 y0 =
220 Math.abs(direction[1]) *
221 (elbowPoints[index].y - elbowPoints[index - 1].y) +
222 elbowPoints[index - 1].y;
223 points.push({ x: x0, y: y0 });
224 direction = changeDirection(direction);
225 }
226 });
227 points.push(lastPoint);
228 var i = 1, n = points.length, pi = points[0], x0 = pi.x, y0 = pi.y, px = [x0, x0, x0, (pi = points[1]).x], py = [y0, y0, y0, pi.y];
229 pathData.push(new SVGPathSegment("L", [
230 d3_svg_lineDot4(d3_svg_lineBasisBezier3, px),
231 d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)
232 ]));
233 points.push(points[n - 1]);
234 while (++i <= n) {
235 pi = points[i];
236 px.shift();
237 px.push(pi.x);
238 py.shift();
239 py.push(pi.y);
240 lineBasisBezier(pathData, px, py);
241 }
242 points.pop();
243 pathData.push(new SVGPathSegment("L", [pi.x, pi.y]));
244 pathData = pathData.concat(lastSegment);
245 return pathData;
246 });
247 this.pathData = this.getPathDataFromPoints(points, markerStart, markerEnd);
248 this.d = this.getPathStringFromPathData(this.pathData);
249 }
250}
251//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRnZURyYXdlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZWRnZS9lZGdlRHJhd2Vycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSw2REFBNkQ7QUFDN0QsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUM7QUFDbEUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFlBQVksQ0FBQztBQVd0QyxNQUFNO0lBTUosWUFBWSxDQUFTLEVBQUUsQ0FBUztRQUM5QixJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNYLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2IsQ0FBQztDQUNGO0FBMEJELE1BQU07SUFHSixZQUFZLElBQXFCLEVBQUUsTUFBZ0I7UUFDakQsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7SUFDdkIsQ0FBQztDQUNGO0FBUUQsTUFBTTtJQWFKLFlBQVksTUFBeUIsRUFBRSxxQkFBcUI7UUFVNUQsOEJBQXlCLEdBQUcsQ0FBQyxRQUEwQixFQUFVLEVBQUU7WUFDakUsTUFBTSxDQUFDLFFBQVE7aUJBQ1osR0FBRyxDQUFDLFVBQVMsV0FBVztnQkFDdkIsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDekQsQ0FBQyxDQUFDO2lCQUNELElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNkLENBQUMsQ0FBQztRQUNGLHFCQUFnQixHQUFHLENBQUMsTUFBYyxFQUFtQixFQUFFO1lBQ3JELE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDOUMsTUFBTSxDQUFDLElBQUksZUFBZSxD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
\No newline at end of file