@nasser-sw/fabric 7.0.1-beta3 → 7.0.1-beta4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/0 +0 -0
- package/dist/index.js +323 -155
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.min.mjs +1 -1
- package/dist/index.min.mjs.map +1 -1
- package/dist/index.mjs +323 -155
- package/dist/index.mjs.map +1 -1
- package/dist/index.node.cjs +323 -155
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +323 -155
- package/dist/index.node.mjs.map +1 -1
- package/dist/package.json.min.mjs +1 -1
- package/dist/package.json.mjs +1 -1
- package/dist/src/shapes/Line.d.ts +31 -86
- package/dist/src/shapes/Line.d.ts.map +1 -1
- package/dist/src/shapes/Line.min.mjs +1 -1
- package/dist/src/shapes/Line.min.mjs.map +1 -1
- package/dist/src/shapes/Line.mjs +323 -154
- package/dist/src/shapes/Line.mjs.map +1 -1
- package/dist-extensions/src/shapes/CustomLine.d.ts +10 -0
- package/dist-extensions/src/shapes/CustomLine.d.ts.map +1 -0
- package/dist-extensions/src/shapes/Line.d.ts +31 -86
- package/dist-extensions/src/shapes/Line.d.ts.map +1 -1
- package/fabric-test-editor.html +157 -8
- package/fabric-test2.html +513 -0
- package/fabric.ts +182 -182
- package/package.json +1 -1
- package/src/shapes/Line.ts +372 -158
- package/debug/konva/CHANGELOG.md +0 -1474
- package/debug/konva/LICENSE +0 -22
- package/debug/konva/README.md +0 -205
- package/debug/konva/gulpfile.mjs +0 -110
- package/debug/konva/package.json +0 -139
- package/debug/konva/release.sh +0 -65
- package/debug/konva/resources/doc-includes/ContainerParams.txt +0 -6
- package/debug/konva/resources/doc-includes/NodeParams.txt +0 -20
- package/debug/konva/resources/doc-includes/ShapeParams.txt +0 -53
- package/debug/konva/resources/jsdoc.conf.json +0 -28
- package/debug/konva/rollup.config.mjs +0 -32
- package/debug/konva/src/Animation.ts +0 -237
- package/debug/konva/src/BezierFunctions.ts +0 -826
- package/debug/konva/src/Canvas.ts +0 -193
- package/debug/konva/src/Container.ts +0 -649
- package/debug/konva/src/Context.ts +0 -1017
- package/debug/konva/src/Core.ts +0 -5
- package/debug/konva/src/DragAndDrop.ts +0 -173
- package/debug/konva/src/Factory.ts +0 -246
- package/debug/konva/src/FastLayer.ts +0 -29
- package/debug/konva/src/Global.ts +0 -210
- package/debug/konva/src/Group.ts +0 -31
- package/debug/konva/src/Layer.ts +0 -546
- package/debug/konva/src/Node.ts +0 -3477
- package/debug/konva/src/PointerEvents.ts +0 -67
- package/debug/konva/src/Shape.ts +0 -2081
- package/debug/konva/src/Stage.ts +0 -1000
- package/debug/konva/src/Tween.ts +0 -811
- package/debug/konva/src/Util.ts +0 -1123
- package/debug/konva/src/Validators.ts +0 -210
- package/debug/konva/src/_CoreInternals.ts +0 -85
- package/debug/konva/src/_FullInternals.ts +0 -171
- package/debug/konva/src/canvas-backend.ts +0 -36
- package/debug/konva/src/filters/Blur.ts +0 -388
- package/debug/konva/src/filters/Brighten.ts +0 -48
- package/debug/konva/src/filters/Brightness.ts +0 -30
- package/debug/konva/src/filters/Contrast.ts +0 -75
- package/debug/konva/src/filters/Emboss.ts +0 -207
- package/debug/konva/src/filters/Enhance.ts +0 -154
- package/debug/konva/src/filters/Grayscale.ts +0 -25
- package/debug/konva/src/filters/HSL.ts +0 -108
- package/debug/konva/src/filters/HSV.ts +0 -106
- package/debug/konva/src/filters/Invert.ts +0 -23
- package/debug/konva/src/filters/Kaleidoscope.ts +0 -274
- package/debug/konva/src/filters/Mask.ts +0 -220
- package/debug/konva/src/filters/Noise.ts +0 -44
- package/debug/konva/src/filters/Pixelate.ts +0 -107
- package/debug/konva/src/filters/Posterize.ts +0 -46
- package/debug/konva/src/filters/RGB.ts +0 -82
- package/debug/konva/src/filters/RGBA.ts +0 -103
- package/debug/konva/src/filters/Sepia.ts +0 -27
- package/debug/konva/src/filters/Solarize.ts +0 -29
- package/debug/konva/src/filters/Threshold.ts +0 -44
- package/debug/konva/src/index.ts +0 -3
- package/debug/konva/src/shapes/Arc.ts +0 -176
- package/debug/konva/src/shapes/Arrow.ts +0 -231
- package/debug/konva/src/shapes/Circle.ts +0 -76
- package/debug/konva/src/shapes/Ellipse.ts +0 -121
- package/debug/konva/src/shapes/Image.ts +0 -319
- package/debug/konva/src/shapes/Label.ts +0 -386
- package/debug/konva/src/shapes/Line.ts +0 -364
- package/debug/konva/src/shapes/Path.ts +0 -1013
- package/debug/konva/src/shapes/Rect.ts +0 -79
- package/debug/konva/src/shapes/RegularPolygon.ts +0 -167
- package/debug/konva/src/shapes/Ring.ts +0 -94
- package/debug/konva/src/shapes/Sprite.ts +0 -370
- package/debug/konva/src/shapes/Star.ts +0 -125
- package/debug/konva/src/shapes/Text.ts +0 -1065
- package/debug/konva/src/shapes/TextPath.ts +0 -583
- package/debug/konva/src/shapes/Transformer.ts +0 -1889
- package/debug/konva/src/shapes/Wedge.ts +0 -129
- package/debug/konva/src/skia-backend.ts +0 -35
- package/debug/konva/src/types.ts +0 -84
- package/debug/konva/tsconfig.json +0 -31
- package/debug/konva/tsconfig.test.json +0 -7
package/dist/src/shapes/Line.mjs
CHANGED
|
@@ -14,35 +14,32 @@ import { makeBoundingBoxFromPoints } from '../util/misc/boundingBoxFromPoints.mj
|
|
|
14
14
|
import '../cache.mjs';
|
|
15
15
|
import '../parser/constants.mjs';
|
|
16
16
|
import '../util/animation/AnimationRegistry.mjs';
|
|
17
|
+
import { Control } from '../controls/Control.mjs';
|
|
17
18
|
import { cacheProperties } from './Object/defaultValues.mjs';
|
|
18
19
|
|
|
19
|
-
// @TODO this code is terrible and Line should be a special case of polyline.
|
|
20
|
-
|
|
21
20
|
const coordProps = ['x1', 'x2', 'y1', 'y2'];
|
|
22
|
-
/**
|
|
23
|
-
* A Class to draw a line
|
|
24
|
-
* A bunch of methods will be added to Polyline to handle the line case
|
|
25
|
-
* The line class is very strange to work with, is all special, it hardly aligns
|
|
26
|
-
* to what a developer want everytime there is an angle
|
|
27
|
-
* @deprecated
|
|
28
|
-
*/
|
|
29
21
|
class Line extends FabricObject {
|
|
30
|
-
/**
|
|
31
|
-
* Constructor
|
|
32
|
-
* @param {Array} [points] Array of points
|
|
33
|
-
* @param {Object} [options] Options object
|
|
34
|
-
* @return {Line} thisArg
|
|
35
|
-
*/
|
|
36
22
|
constructor() {
|
|
37
|
-
let [x1, y1, x2, y2] = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [0, 0,
|
|
23
|
+
let [x1, y1, x2, y2] = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [0, 0, 100, 0];
|
|
38
24
|
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
39
25
|
super();
|
|
40
|
-
|
|
26
|
+
_defineProperty(this, "hitStrokeWidth", 'auto');
|
|
27
|
+
_defineProperty(this, "_updatingEndpoints", false);
|
|
28
|
+
_defineProperty(this, "_useEndpointCoords", true);
|
|
41
29
|
this.setOptions(options);
|
|
42
30
|
this.x1 = x1;
|
|
43
31
|
this.x2 = x2;
|
|
44
32
|
this.y1 = y1;
|
|
45
33
|
this.y2 = y2;
|
|
34
|
+
if (options.hitStrokeWidth !== undefined) {
|
|
35
|
+
this.hitStrokeWidth = options.hitStrokeWidth;
|
|
36
|
+
}
|
|
37
|
+
this.hasBorders = false;
|
|
38
|
+
this.hasControls = true;
|
|
39
|
+
this.selectable = true;
|
|
40
|
+
this.hoverCursor = 'move';
|
|
41
|
+
this.perPixelTargetFind = false;
|
|
42
|
+
this.strokeLineCap = 'butt';
|
|
46
43
|
this._setWidthHeight();
|
|
47
44
|
const {
|
|
48
45
|
left,
|
|
@@ -50,96 +47,323 @@ class Line extends FabricObject {
|
|
|
50
47
|
} = options;
|
|
51
48
|
typeof left === 'number' && this.set(LEFT, left);
|
|
52
49
|
typeof top === 'number' && this.set(TOP, top);
|
|
50
|
+
this._setupLineControls();
|
|
51
|
+
}
|
|
52
|
+
_setupLineControls() {
|
|
53
|
+
this.controls = {
|
|
54
|
+
p1: new Control({
|
|
55
|
+
x: 0,
|
|
56
|
+
y: 0,
|
|
57
|
+
cursorStyle: 'move',
|
|
58
|
+
actionHandler: this._endpointActionHandler.bind(this),
|
|
59
|
+
positionHandler: this._p1PositionHandler.bind(this),
|
|
60
|
+
render: this._renderEndpointControl.bind(this),
|
|
61
|
+
sizeX: 12,
|
|
62
|
+
sizeY: 12
|
|
63
|
+
}),
|
|
64
|
+
p2: new Control({
|
|
65
|
+
x: 0,
|
|
66
|
+
y: 0,
|
|
67
|
+
cursorStyle: 'move',
|
|
68
|
+
actionHandler: this._endpointActionHandler.bind(this),
|
|
69
|
+
positionHandler: this._p2PositionHandler.bind(this),
|
|
70
|
+
render: this._renderEndpointControl.bind(this),
|
|
71
|
+
sizeX: 12,
|
|
72
|
+
sizeY: 12
|
|
73
|
+
})
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
_p1PositionHandler() {
|
|
77
|
+
var _this$canvas;
|
|
78
|
+
const vpt = ((_this$canvas = this.canvas) === null || _this$canvas === void 0 ? void 0 : _this$canvas.viewportTransform) || [1, 0, 0, 1, 0, 0];
|
|
79
|
+
return new Point(this.x1, this.y1).transform(vpt);
|
|
80
|
+
}
|
|
81
|
+
_p2PositionHandler() {
|
|
82
|
+
var _this$canvas2;
|
|
83
|
+
const vpt = ((_this$canvas2 = this.canvas) === null || _this$canvas2 === void 0 ? void 0 : _this$canvas2.viewportTransform) || [1, 0, 0, 1, 0, 0];
|
|
84
|
+
return new Point(this.x2, this.y2).transform(vpt);
|
|
85
|
+
}
|
|
86
|
+
_renderEndpointControl(ctx, left, top) {
|
|
87
|
+
const size = 12;
|
|
88
|
+
ctx.save();
|
|
89
|
+
ctx.fillStyle = '#007bff';
|
|
90
|
+
ctx.strokeStyle = '#ffffff';
|
|
91
|
+
ctx.lineWidth = 2;
|
|
92
|
+
ctx.beginPath();
|
|
93
|
+
ctx.arc(left, top, size / 2, 0, 2 * Math.PI);
|
|
94
|
+
ctx.fill();
|
|
95
|
+
ctx.stroke();
|
|
96
|
+
ctx.restore();
|
|
97
|
+
}
|
|
98
|
+
drawBorders(ctx) {
|
|
99
|
+
let styleOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
100
|
+
if (this._useEndpointCoords) {
|
|
101
|
+
this._drawLineBorders(ctx, styleOverride);
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
return super.drawBorders(ctx, styleOverride, {});
|
|
53
105
|
}
|
|
106
|
+
_drawLineBorders(ctx) {
|
|
107
|
+
var _this$canvas3;
|
|
108
|
+
let styleOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
109
|
+
const vpt = ((_this$canvas3 = this.canvas) === null || _this$canvas3 === void 0 ? void 0 : _this$canvas3.viewportTransform) || [1, 0, 0, 1, 0, 0];
|
|
110
|
+
ctx.save();
|
|
111
|
+
ctx.setTransform(vpt[0], vpt[1], vpt[2], vpt[3], vpt[4], vpt[5]);
|
|
112
|
+
ctx.strokeStyle = styleOverride.borderColor || this.borderColor || 'rgba(100, 200, 200, 0.5)';
|
|
113
|
+
ctx.lineWidth = (this.strokeWidth || 1) + 5;
|
|
114
|
+
ctx.lineCap = this.strokeLineCap || 'butt';
|
|
115
|
+
ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
|
|
116
|
+
ctx.beginPath();
|
|
117
|
+
ctx.moveTo(this.x1, this.y1);
|
|
118
|
+
ctx.lineTo(this.x2, this.y2);
|
|
119
|
+
ctx.stroke();
|
|
120
|
+
ctx.restore();
|
|
121
|
+
}
|
|
122
|
+
_renderControls(ctx) {
|
|
123
|
+
let styleOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
124
|
+
ctx.save();
|
|
125
|
+
ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
|
|
126
|
+
this.drawControls(ctx, styleOverride);
|
|
127
|
+
ctx.restore();
|
|
128
|
+
}
|
|
129
|
+
getBoundingRect() {
|
|
130
|
+
if (this._useEndpointCoords) {
|
|
131
|
+
const {
|
|
132
|
+
x1,
|
|
133
|
+
y1,
|
|
134
|
+
x2,
|
|
135
|
+
y2
|
|
136
|
+
} = this;
|
|
137
|
+
const effectiveStrokeWidth = this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth;
|
|
138
|
+
const padding = Math.max(effectiveStrokeWidth / 2 + 5, 10);
|
|
139
|
+
return {
|
|
140
|
+
left: Math.min(x1, x2) - padding,
|
|
141
|
+
top: Math.min(y1, y2) - padding,
|
|
142
|
+
width: Math.abs(x2 - x1) + padding * 2 || padding * 2,
|
|
143
|
+
height: Math.abs(y2 - y1) + padding * 2 || padding * 2
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return super.getBoundingRect();
|
|
147
|
+
}
|
|
148
|
+
setCoords() {
|
|
149
|
+
if (this._useEndpointCoords) {
|
|
150
|
+
const minX = Math.min(this.x1, this.x2);
|
|
151
|
+
const maxX = Math.max(this.x1, this.x2);
|
|
152
|
+
const minY = Math.min(this.y1, this.y2);
|
|
153
|
+
const maxY = Math.max(this.y1, this.y2);
|
|
154
|
+
const effectiveStrokeWidth = this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth;
|
|
155
|
+
const hitPadding = Math.max(effectiveStrokeWidth / 2 + 5, 10);
|
|
156
|
+
this.left = minX - hitPadding + (maxX - minX + hitPadding * 2) / 2;
|
|
157
|
+
this.top = minY - hitPadding + (maxY - minY + hitPadding * 2) / 2;
|
|
158
|
+
this.width = Math.abs(this.x2 - this.x1) + hitPadding * 2;
|
|
159
|
+
this.height = Math.abs(this.y2 - this.y1) + hitPadding * 2;
|
|
160
|
+
}
|
|
161
|
+
super.setCoords();
|
|
162
|
+
}
|
|
163
|
+
getCoords() {
|
|
164
|
+
if (this._useEndpointCoords) {
|
|
165
|
+
const deltaX = this.x2 - this.x1;
|
|
166
|
+
const deltaY = this.y2 - this.y1;
|
|
167
|
+
const length = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
168
|
+
if (length === 0) {
|
|
169
|
+
return super.getCoords();
|
|
170
|
+
}
|
|
171
|
+
const effectiveStrokeWidth = this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth;
|
|
172
|
+
const halfWidth = Math.max(effectiveStrokeWidth / 2 + 2, 5);
|
|
54
173
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}, {
|
|
77
|
-
x: x2,
|
|
78
|
-
y: y2
|
|
79
|
-
}]);
|
|
80
|
-
const position = new Point(left + width / 2, top + height / 2);
|
|
81
|
-
this.setPositionByOrigin(position, CENTER, CENTER);
|
|
174
|
+
// Unit vector perpendicular to line
|
|
175
|
+
const perpX = -deltaY / length;
|
|
176
|
+
const perpY = deltaX / length;
|
|
177
|
+
|
|
178
|
+
// Four corners of oriented rectangle
|
|
179
|
+
return [new Point(this.x1 + perpX * halfWidth, this.y1 + perpY * halfWidth), new Point(this.x2 + perpX * halfWidth, this.y2 + perpY * halfWidth), new Point(this.x2 - perpX * halfWidth, this.y2 - perpY * halfWidth), new Point(this.x1 - perpX * halfWidth, this.y1 - perpY * halfWidth)];
|
|
180
|
+
}
|
|
181
|
+
return super.getCoords();
|
|
182
|
+
}
|
|
183
|
+
containsPoint(point) {
|
|
184
|
+
if (this._useEndpointCoords) {
|
|
185
|
+
var _this$canvas4;
|
|
186
|
+
if (((_this$canvas4 = this.canvas) === null || _this$canvas4 === void 0 ? void 0 : _this$canvas4.getActiveObject()) === this) {
|
|
187
|
+
return super.containsPoint(point);
|
|
188
|
+
}
|
|
189
|
+
const distance = this._distanceToLineSegment(point.x, point.y);
|
|
190
|
+
const effectiveStrokeWidth = this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth || 1;
|
|
191
|
+
const tolerance = Math.max(effectiveStrokeWidth / 2 + 2, 5);
|
|
192
|
+
return distance <= tolerance;
|
|
193
|
+
}
|
|
194
|
+
return super.containsPoint(point);
|
|
82
195
|
}
|
|
196
|
+
_distanceToLineSegment(px, py) {
|
|
197
|
+
const x1 = this.x1,
|
|
198
|
+
y1 = this.y1,
|
|
199
|
+
x2 = this.x2,
|
|
200
|
+
y2 = this.y2;
|
|
201
|
+
const pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
|
|
202
|
+
if (pd2 === 0) {
|
|
203
|
+
return Math.sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));
|
|
204
|
+
}
|
|
205
|
+
const u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
|
|
206
|
+
let closestX, closestY;
|
|
207
|
+
if (u < 0) {
|
|
208
|
+
closestX = x1;
|
|
209
|
+
closestY = y1;
|
|
210
|
+
} else if (u > 1) {
|
|
211
|
+
closestX = x2;
|
|
212
|
+
closestY = y2;
|
|
213
|
+
} else {
|
|
214
|
+
closestX = x1 + u * (x2 - x1);
|
|
215
|
+
closestY = y1 + u * (y2 - y1);
|
|
216
|
+
}
|
|
217
|
+
return Math.sqrt((px - closestX) * (px - closestX) + (py - closestY) * (py - closestY));
|
|
218
|
+
}
|
|
219
|
+
_endpointActionHandler(eventData, transformData, x, y) {
|
|
220
|
+
var _this$canvas6;
|
|
221
|
+
const controlKey = transformData.corner;
|
|
222
|
+
const pointer = new Point(x, y);
|
|
223
|
+
let newX = pointer.x;
|
|
224
|
+
let newY = pointer.y;
|
|
225
|
+
if (eventData.shiftKey) {
|
|
226
|
+
const otherControl = controlKey === 'p1' ? 'p2' : 'p1';
|
|
227
|
+
const otherX = this[otherControl === 'p1' ? 'x1' : 'x2'];
|
|
228
|
+
const otherY = this[otherControl === 'p1' ? 'y1' : 'y2'];
|
|
229
|
+
const snapped = this._snapToAngle(otherX, otherY, newX, newY);
|
|
230
|
+
newX = snapped.x;
|
|
231
|
+
newY = snapped.y;
|
|
232
|
+
}
|
|
233
|
+
if (this._useEndpointCoords) {
|
|
234
|
+
var _this$canvas5;
|
|
235
|
+
if (controlKey === 'p1') {
|
|
236
|
+
this.x1 = newX;
|
|
237
|
+
this.y1 = newY;
|
|
238
|
+
} else if (controlKey === 'p2') {
|
|
239
|
+
this.x2 = newX;
|
|
240
|
+
this.y2 = newY;
|
|
241
|
+
}
|
|
242
|
+
this.dirty = true;
|
|
243
|
+
this.setCoords();
|
|
244
|
+
(_this$canvas5 = this.canvas) === null || _this$canvas5 === void 0 || _this$canvas5.requestRenderAll();
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
83
247
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
248
|
+
// Fallback for old system
|
|
249
|
+
this._updatingEndpoints = true;
|
|
250
|
+
if (controlKey === 'p1') {
|
|
251
|
+
this.x1 = newX;
|
|
252
|
+
this.y1 = newY;
|
|
253
|
+
} else if (controlKey === 'p2') {
|
|
254
|
+
this.x2 = newX;
|
|
255
|
+
this.y2 = newY;
|
|
256
|
+
}
|
|
257
|
+
this._setWidthHeight();
|
|
258
|
+
this.dirty = true;
|
|
259
|
+
this._updatingEndpoints = false;
|
|
260
|
+
(_this$canvas6 = this.canvas) === null || _this$canvas6 === void 0 || _this$canvas6.requestRenderAll();
|
|
261
|
+
this.fire('modified', {
|
|
262
|
+
transform: transformData,
|
|
263
|
+
target: this,
|
|
264
|
+
e: eventData
|
|
265
|
+
});
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
_snapToAngle(fromX, fromY, toX, toY) {
|
|
269
|
+
const deltaX = toX - fromX;
|
|
270
|
+
const deltaY = toY - fromY;
|
|
271
|
+
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
272
|
+
if (distance === 0) return {
|
|
273
|
+
x: toX,
|
|
274
|
+
y: toY
|
|
275
|
+
};
|
|
276
|
+
let angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
|
|
277
|
+
const snapIncrement = 15;
|
|
278
|
+
const snappedAngle = Math.round(angle / snapIncrement) * snapIncrement;
|
|
279
|
+
const snappedRadians = snappedAngle * (Math.PI / 180);
|
|
280
|
+
return {
|
|
281
|
+
x: fromX + Math.cos(snappedRadians) * distance,
|
|
282
|
+
y: fromY + Math.sin(snappedRadians) * distance
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
_setWidthHeight() {
|
|
286
|
+
let skipReposition = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
287
|
+
this.width = Math.abs(this.x2 - this.x1) || 1;
|
|
288
|
+
this.height = Math.abs(this.y2 - this.y1) || 1;
|
|
289
|
+
if (!skipReposition && !this._updatingEndpoints) {
|
|
290
|
+
const {
|
|
291
|
+
left,
|
|
292
|
+
top,
|
|
293
|
+
width,
|
|
294
|
+
height
|
|
295
|
+
} = makeBoundingBoxFromPoints([{
|
|
296
|
+
x: this.x1,
|
|
297
|
+
y: this.y1
|
|
298
|
+
}, {
|
|
299
|
+
x: this.x2,
|
|
300
|
+
y: this.y2
|
|
301
|
+
}]);
|
|
302
|
+
this.setPositionByOrigin(new Point(left + width / 2, top + height / 2), CENTER, CENTER);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
89
305
|
_set(key, value) {
|
|
306
|
+
const oldLeft = this.left;
|
|
307
|
+
const oldTop = this.top;
|
|
90
308
|
super._set(key, value);
|
|
91
309
|
if (coordProps.includes(key)) {
|
|
92
|
-
// this doesn't make sense very much, since setting x1 when top or left
|
|
93
|
-
// are already set, is just going to show a strange result since the
|
|
94
|
-
// line will move way more than the developer expect.
|
|
95
|
-
// in fabric5 it worked only when the line didn't have extra transformations,
|
|
96
|
-
// in fabric6 too. With extra transform they behave bad in different ways.
|
|
97
|
-
// This needs probably a good rework or a tutorial if you have to create a dynamic line
|
|
98
310
|
this._setWidthHeight();
|
|
311
|
+
this.dirty = true;
|
|
312
|
+
}
|
|
313
|
+
if ((key === 'left' || key === 'top') && this.canvas && !this._updatingEndpoints) {
|
|
314
|
+
const deltaX = this.left - oldLeft;
|
|
315
|
+
const deltaY = this.top - oldTop;
|
|
316
|
+
if (deltaX !== 0 || deltaY !== 0) {
|
|
317
|
+
this._updatingEndpoints = true;
|
|
318
|
+
this.x1 += deltaX;
|
|
319
|
+
this.y1 += deltaY;
|
|
320
|
+
this.x2 += deltaX;
|
|
321
|
+
this.y2 += deltaY;
|
|
322
|
+
this._updatingEndpoints = false;
|
|
323
|
+
}
|
|
99
324
|
}
|
|
100
325
|
return this;
|
|
101
326
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
327
|
+
render(ctx) {
|
|
328
|
+
if (this._useEndpointCoords) {
|
|
329
|
+
this._renderDirectly(ctx);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
super.render(ctx);
|
|
333
|
+
}
|
|
334
|
+
_renderDirectly(ctx) {
|
|
335
|
+
var _this$canvas7, _this$stroke;
|
|
336
|
+
if (!this.visible) return;
|
|
337
|
+
ctx.save();
|
|
338
|
+
const vpt = ((_this$canvas7 = this.canvas) === null || _this$canvas7 === void 0 ? void 0 : _this$canvas7.viewportTransform) || [1, 0, 0, 1, 0, 0];
|
|
339
|
+
ctx.transform(vpt[0], vpt[1], vpt[2], vpt[3], vpt[4], vpt[5]);
|
|
340
|
+
ctx.globalAlpha = this.opacity;
|
|
341
|
+
ctx.strokeStyle = ((_this$stroke = this.stroke) === null || _this$stroke === void 0 ? void 0 : _this$stroke.toString()) || '#000';
|
|
342
|
+
ctx.lineWidth = this.strokeWidth;
|
|
343
|
+
ctx.lineCap = this.strokeLineCap || 'butt';
|
|
344
|
+
ctx.beginPath();
|
|
345
|
+
ctx.moveTo(this.x1, this.y1);
|
|
346
|
+
ctx.lineTo(this.x2, this.y2);
|
|
347
|
+
ctx.stroke();
|
|
348
|
+
ctx.restore();
|
|
349
|
+
}
|
|
107
350
|
_render(ctx) {
|
|
351
|
+
if (this._useEndpointCoords) return;
|
|
108
352
|
ctx.beginPath();
|
|
109
353
|
const p = this.calcLinePoints();
|
|
110
354
|
ctx.moveTo(p.x1, p.y1);
|
|
111
355
|
ctx.lineTo(p.x2, p.y2);
|
|
112
356
|
ctx.lineWidth = this.strokeWidth;
|
|
113
|
-
|
|
114
|
-
// TODO: test this
|
|
115
|
-
// make sure setting "fill" changes color of a line
|
|
116
|
-
// (by copying fillStyle to strokeStyle, since line is stroked, not filled)
|
|
117
357
|
const origStrokeStyle = ctx.strokeStyle;
|
|
118
358
|
if (isFiller(this.stroke)) {
|
|
119
359
|
ctx.strokeStyle = this.stroke.toLive(ctx);
|
|
120
|
-
} else {
|
|
121
|
-
var _this$stroke;
|
|
122
|
-
ctx.strokeStyle = (_this$stroke = this.stroke) !== null && _this$stroke !== void 0 ? _this$stroke : ctx.fillStyle;
|
|
123
360
|
}
|
|
124
361
|
this.stroke && this._renderStroke(ctx);
|
|
125
362
|
ctx.strokeStyle = origStrokeStyle;
|
|
126
363
|
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* This function is an helper for svg import. it returns the center of the object in the svg
|
|
130
|
-
* untransformed coordinates
|
|
131
|
-
* @private
|
|
132
|
-
* @return {Point} center point from element coordinates
|
|
133
|
-
*/
|
|
134
364
|
_findCenterFromElement() {
|
|
135
365
|
return new Point((this.x1 + this.x2) / 2, (this.y1 + this.y2) / 2);
|
|
136
366
|
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Returns object representation of an instance
|
|
140
|
-
* @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
|
|
141
|
-
* @return {Object} object representation of an instance
|
|
142
|
-
*/
|
|
143
367
|
toObject() {
|
|
144
368
|
let propertiesToInclude = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
145
369
|
return {
|
|
@@ -147,32 +371,25 @@ class Line extends FabricObject {
|
|
|
147
371
|
...this.calcLinePoints()
|
|
148
372
|
};
|
|
149
373
|
}
|
|
150
|
-
|
|
151
|
-
/*
|
|
152
|
-
* Calculate object dimensions from its properties
|
|
153
|
-
* @private
|
|
154
|
-
*/
|
|
155
374
|
_getNonTransformedDimensions() {
|
|
156
375
|
const dim = super._getNonTransformedDimensions();
|
|
157
|
-
if (this.strokeLineCap === '
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
if (this.height === 0) {
|
|
162
|
-
dim.x -= this.strokeWidth;
|
|
163
|
-
}
|
|
376
|
+
if (this.strokeLineCap === 'round') {
|
|
377
|
+
dim.x += this.strokeWidth;
|
|
378
|
+
dim.y += this.strokeWidth;
|
|
164
379
|
}
|
|
165
380
|
return dim;
|
|
166
381
|
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Recalculates line points given width and height
|
|
170
|
-
* Those points are simply placed around the center,
|
|
171
|
-
* This is not useful outside internal render functions and svg output
|
|
172
|
-
* Is not meant to be for the developer.
|
|
173
|
-
* @private
|
|
174
|
-
*/
|
|
175
382
|
calcLinePoints() {
|
|
383
|
+
if (this._updatingEndpoints) {
|
|
384
|
+
const centerX = (this.x1 + this.x2) / 2;
|
|
385
|
+
const centerY = (this.y1 + this.y2) / 2;
|
|
386
|
+
return {
|
|
387
|
+
x1: this.x1 - centerX,
|
|
388
|
+
y1: this.y1 - centerY,
|
|
389
|
+
x2: this.x2 - centerX,
|
|
390
|
+
y2: this.y2 - centerY
|
|
391
|
+
};
|
|
392
|
+
}
|
|
176
393
|
const {
|
|
177
394
|
x1: _x1,
|
|
178
395
|
x2: _x2,
|
|
@@ -181,27 +398,15 @@ class Line extends FabricObject {
|
|
|
181
398
|
width,
|
|
182
399
|
height
|
|
183
400
|
} = this;
|
|
184
|
-
const xMult = _x1 <= _x2 ? -1 : 1
|
|
185
|
-
|
|
186
|
-
x1 = xMult * width / 2,
|
|
187
|
-
y1 = yMult * height / 2,
|
|
188
|
-
x2 = xMult * -width / 2,
|
|
189
|
-
y2 = yMult * -height / 2;
|
|
401
|
+
const xMult = _x1 <= _x2 ? -1 : 1;
|
|
402
|
+
const yMult = _y1 <= _y2 ? -1 : 1;
|
|
190
403
|
return {
|
|
191
|
-
x1,
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
y2
|
|
404
|
+
x1: xMult * width / 2,
|
|
405
|
+
y1: yMult * height / 2,
|
|
406
|
+
x2: xMult * -width / 2,
|
|
407
|
+
y2: yMult * -height / 2
|
|
195
408
|
};
|
|
196
409
|
}
|
|
197
|
-
|
|
198
|
-
/* _FROM_SVG_START_ */
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Returns svg representation of an instance
|
|
202
|
-
* @return {Array} an array of strings with the specific svg representation
|
|
203
|
-
* of the instance
|
|
204
|
-
*/
|
|
205
410
|
_toSVG() {
|
|
206
411
|
const {
|
|
207
412
|
x1,
|
|
@@ -211,18 +416,6 @@ class Line extends FabricObject {
|
|
|
211
416
|
} = this.calcLinePoints();
|
|
212
417
|
return ['<line ', 'COMMON_PARTS', `x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" />\n`];
|
|
213
418
|
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* List of attribute names to account for when parsing SVG element (used by {@link Line.fromElement})
|
|
217
|
-
* @see http://www.w3.org/TR/SVG/shapes.html#LineElement
|
|
218
|
-
*/
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Returns Line instance from an SVG element
|
|
222
|
-
* @param {HTMLElement} element Element to parse
|
|
223
|
-
* @param {Object} [options] Options object
|
|
224
|
-
* @param {Function} [callback] callback function invoked after parsing
|
|
225
|
-
*/
|
|
226
419
|
static async fromElement(element, options, cssRules) {
|
|
227
420
|
const {
|
|
228
421
|
x1 = 0,
|
|
@@ -233,14 +426,6 @@ class Line extends FabricObject {
|
|
|
233
426
|
} = parseAttributes(element, this.ATTRIBUTE_NAMES, cssRules);
|
|
234
427
|
return new this([x1, y1, x2, y2], parsedAttributes);
|
|
235
428
|
}
|
|
236
|
-
|
|
237
|
-
/* _FROM_SVG_END_ */
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Returns Line instance from an object representation
|
|
241
|
-
* @param {Object} object Object to create an instance from
|
|
242
|
-
* @returns {Promise<Line>}
|
|
243
|
-
*/
|
|
244
429
|
static fromObject(_ref) {
|
|
245
430
|
let {
|
|
246
431
|
x1,
|
|
@@ -257,22 +442,6 @@ class Line extends FabricObject {
|
|
|
257
442
|
});
|
|
258
443
|
}
|
|
259
444
|
}
|
|
260
|
-
/**
|
|
261
|
-
* x value or first line edge
|
|
262
|
-
* @type number
|
|
263
|
-
*/
|
|
264
|
-
/**
|
|
265
|
-
* y value or first line edge
|
|
266
|
-
* @type number
|
|
267
|
-
*/
|
|
268
|
-
/**
|
|
269
|
-
* x value or second line edge
|
|
270
|
-
* @type number
|
|
271
|
-
*/
|
|
272
|
-
/**
|
|
273
|
-
* y value or second line edge
|
|
274
|
-
* @type number
|
|
275
|
-
*/
|
|
276
445
|
_defineProperty(Line, "type", 'Line');
|
|
277
446
|
_defineProperty(Line, "cacheProperties", [...cacheProperties, ...coordProps]);
|
|
278
447
|
_defineProperty(Line, "ATTRIBUTE_NAMES", SHARED_ATTRIBUTES.concat(coordProps));
|