@nasser-sw/fabric 7.0.0-beta1 → 7.0.1-beta10
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/debug/{konva → konva-master}/CHANGELOG.md +2 -1
- package/debug/{konva → konva-master}/README.md +7 -3
- package/debug/{konva → konva-master}/package.json +1 -1
- package/debug/{konva → konva-master}/release.sh +1 -4
- package/debug/{konva → konva-master}/src/Canvas.ts +37 -0
- package/debug/{konva → konva-master}/src/shapes/Text.ts +2 -2
- package/dist/index.js +2198 -272
- 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 +2198 -272
- package/dist/index.mjs.map +1 -1
- package/dist/index.node.cjs +2198 -272
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +2198 -272
- 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 +33 -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 +405 -159
- package/dist/src/shapes/Line.mjs.map +1 -1
- package/dist/src/shapes/Polyline.d.ts +7 -0
- package/dist/src/shapes/Polyline.d.ts.map +1 -1
- package/dist/src/shapes/Polyline.min.mjs +1 -1
- package/dist/src/shapes/Polyline.min.mjs.map +1 -1
- package/dist/src/shapes/Polyline.mjs +48 -16
- package/dist/src/shapes/Polyline.mjs.map +1 -1
- package/dist/src/shapes/Text/Text.d.ts +19 -0
- package/dist/src/shapes/Text/Text.d.ts.map +1 -1
- package/dist/src/shapes/Text/Text.min.mjs +1 -1
- package/dist/src/shapes/Text/Text.min.mjs.map +1 -1
- package/dist/src/shapes/Text/Text.mjs +302 -16
- package/dist/src/shapes/Text/Text.mjs.map +1 -1
- package/dist/src/shapes/Textbox.d.ts +56 -1
- package/dist/src/shapes/Textbox.d.ts.map +1 -1
- package/dist/src/shapes/Textbox.min.mjs +1 -1
- package/dist/src/shapes/Textbox.min.mjs.map +1 -1
- package/dist/src/shapes/Textbox.mjs +633 -11
- package/dist/src/shapes/Textbox.mjs.map +1 -1
- package/dist/src/shapes/Triangle.d.ts +27 -2
- package/dist/src/shapes/Triangle.d.ts.map +1 -1
- package/dist/src/shapes/Triangle.min.mjs +1 -1
- package/dist/src/shapes/Triangle.min.mjs.map +1 -1
- package/dist/src/shapes/Triangle.mjs +72 -12
- package/dist/src/shapes/Triangle.mjs.map +1 -1
- package/dist/src/text/examples/arabicTextExample.d.ts +60 -0
- package/dist/src/text/examples/arabicTextExample.d.ts.map +1 -0
- package/dist/src/text/measure.d.ts +9 -0
- package/dist/src/text/measure.d.ts.map +1 -1
- package/dist/src/text/measure.min.mjs +1 -1
- package/dist/src/text/measure.min.mjs.map +1 -1
- package/dist/src/text/measure.mjs +175 -4
- package/dist/src/text/measure.mjs.map +1 -1
- package/dist/src/text/overlayEditor.d.ts +8 -0
- package/dist/src/text/overlayEditor.d.ts.map +1 -1
- package/dist/src/text/overlayEditor.min.mjs +1 -1
- package/dist/src/text/overlayEditor.min.mjs.map +1 -1
- package/dist/src/text/overlayEditor.mjs +395 -56
- package/dist/src/text/overlayEditor.mjs.map +1 -1
- package/dist/src/text/scriptUtils.d.ts +142 -0
- package/dist/src/text/scriptUtils.d.ts.map +1 -0
- package/dist/src/text/scriptUtils.min.mjs +2 -0
- package/dist/src/text/scriptUtils.min.mjs.map +1 -0
- package/dist/src/text/scriptUtils.mjs +212 -0
- package/dist/src/text/scriptUtils.mjs.map +1 -0
- package/dist/src/util/misc/cornerRadius.d.ts +70 -0
- package/dist/src/util/misc/cornerRadius.d.ts.map +1 -0
- package/dist/src/util/misc/cornerRadius.min.mjs +2 -0
- package/dist/src/util/misc/cornerRadius.min.mjs.map +1 -0
- package/dist/src/util/misc/cornerRadius.mjs +181 -0
- package/dist/src/util/misc/cornerRadius.mjs.map +1 -0
- 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 +33 -86
- package/dist-extensions/src/shapes/Line.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Polyline.d.ts +7 -0
- package/dist-extensions/src/shapes/Polyline.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Text/Text.d.ts +19 -0
- package/dist-extensions/src/shapes/Text/Text.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Textbox.d.ts +56 -1
- package/dist-extensions/src/shapes/Textbox.d.ts.map +1 -1
- package/dist-extensions/src/shapes/Triangle.d.ts +27 -2
- package/dist-extensions/src/shapes/Triangle.d.ts.map +1 -1
- package/dist-extensions/src/text/measure.d.ts +9 -0
- package/dist-extensions/src/text/measure.d.ts.map +1 -1
- package/dist-extensions/src/text/overlayEditor.d.ts +8 -0
- package/dist-extensions/src/text/overlayEditor.d.ts.map +1 -1
- package/dist-extensions/src/text/scriptUtils.d.ts +142 -0
- package/dist-extensions/src/text/scriptUtils.d.ts.map +1 -0
- package/dist-extensions/src/util/misc/cornerRadius.d.ts +70 -0
- package/dist-extensions/src/util/misc/cornerRadius.d.ts.map +1 -0
- package/fabric-test-editor.html +3552 -0
- package/fabric-test2.html +647 -0
- package/fabric.ts +182 -182
- package/fonts/STV Bold.ttf +0 -0
- package/fonts/STV Light.ttf +0 -0
- package/fonts/STV Regular.ttf +0 -0
- package/package.json +164 -164
- package/src/shapes/Line.ts +484 -157
- package/src/shapes/Polyline.ts +70 -29
- package/src/shapes/Text/Text.ts +317 -19
- package/src/shapes/Textbox.ts +663 -12
- package/src/shapes/Triangle.spec.ts +76 -0
- package/src/shapes/Triangle.ts +85 -15
- package/src/text/measure.ts +200 -50
- package/src/text/overlayEditor.ts +504 -94
- package/src/util/misc/cornerRadius.spec.ts +141 -0
- package/src/util/misc/cornerRadius.ts +269 -0
- /package/debug/{konva → konva-master}/LICENSE +0 -0
- /package/debug/{konva → konva-master}/gulpfile.mjs +0 -0
- /package/debug/{konva → konva-master}/resources/doc-includes/ContainerParams.txt +0 -0
- /package/debug/{konva → konva-master}/resources/doc-includes/NodeParams.txt +0 -0
- /package/debug/{konva → konva-master}/resources/doc-includes/ShapeParams.txt +0 -0
- /package/debug/{konva → konva-master}/resources/jsdoc.conf.json +0 -0
- /package/debug/{konva → konva-master}/rollup.config.mjs +0 -0
- /package/debug/{konva → konva-master}/src/Animation.ts +0 -0
- /package/debug/{konva → konva-master}/src/BezierFunctions.ts +0 -0
- /package/debug/{konva → konva-master}/src/Container.ts +0 -0
- /package/debug/{konva → konva-master}/src/Context.ts +0 -0
- /package/debug/{konva → konva-master}/src/Core.ts +0 -0
- /package/debug/{konva → konva-master}/src/DragAndDrop.ts +0 -0
- /package/debug/{konva → konva-master}/src/Factory.ts +0 -0
- /package/debug/{konva → konva-master}/src/FastLayer.ts +0 -0
- /package/debug/{konva → konva-master}/src/Global.ts +0 -0
- /package/debug/{konva → konva-master}/src/Group.ts +0 -0
- /package/debug/{konva → konva-master}/src/Layer.ts +0 -0
- /package/debug/{konva → konva-master}/src/Node.ts +0 -0
- /package/debug/{konva → konva-master}/src/PointerEvents.ts +0 -0
- /package/debug/{konva → konva-master}/src/Shape.ts +0 -0
- /package/debug/{konva → konva-master}/src/Stage.ts +0 -0
- /package/debug/{konva → konva-master}/src/Tween.ts +0 -0
- /package/debug/{konva → konva-master}/src/Util.ts +0 -0
- /package/debug/{konva → konva-master}/src/Validators.ts +0 -0
- /package/debug/{konva → konva-master}/src/_CoreInternals.ts +0 -0
- /package/debug/{konva → konva-master}/src/_FullInternals.ts +0 -0
- /package/debug/{konva → konva-master}/src/canvas-backend.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Blur.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Brighten.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Brightness.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Contrast.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Emboss.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Enhance.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Grayscale.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/HSL.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/HSV.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Invert.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Kaleidoscope.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Mask.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Noise.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Pixelate.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Posterize.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/RGB.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/RGBA.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Sepia.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Solarize.ts +0 -0
- /package/debug/{konva → konva-master}/src/filters/Threshold.ts +0 -0
- /package/debug/{konva → konva-master}/src/index.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Arc.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Arrow.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Circle.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Ellipse.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Image.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Label.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Line.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Path.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Rect.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/RegularPolygon.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Ring.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Sprite.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Star.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/TextPath.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Transformer.ts +0 -0
- /package/debug/{konva → konva-master}/src/shapes/Wedge.ts +0 -0
- /package/debug/{konva → konva-master}/src/skia-backend.ts +0 -0
- /package/debug/{konva → konva-master}/src/types.ts +0 -0
- /package/debug/{konva → konva-master}/tsconfig.json +0 -0
- /package/debug/{konva → konva-master}/tsconfig.test.json +0 -0
package/src/shapes/Line.ts
CHANGED
|
@@ -10,12 +10,13 @@ import type { ObjectEvents } from '../EventTypeDefs';
|
|
|
10
10
|
import { makeBoundingBoxFromPoints } from '../util';
|
|
11
11
|
import { CENTER, LEFT, TOP } from '../constants';
|
|
12
12
|
import type { CSSRules } from '../parser/typedefs';
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
import { Control } from '../controls/Control';
|
|
14
|
+
import type { TPointerEvent, Transform } from '../EventTypeDefs';
|
|
15
|
+
import { Gradient } from '../gradient/Gradient';
|
|
15
16
|
|
|
16
17
|
const coordProps = ['x1', 'x2', 'y1', 'y2'] as const;
|
|
17
18
|
|
|
18
|
-
interface
|
|
19
|
+
interface UniqueLineCoords {
|
|
19
20
|
x1: number;
|
|
20
21
|
x2: number;
|
|
21
22
|
y1: number;
|
|
@@ -24,225 +25,563 @@ interface UniqueLineProps {
|
|
|
24
25
|
|
|
25
26
|
export interface SerializedLineProps
|
|
26
27
|
extends SerializedObjectProps,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* A Class to draw a line
|
|
31
|
-
* A bunch of methods will be added to Polyline to handle the line case
|
|
32
|
-
* The line class is very strange to work with, is all special, it hardly aligns
|
|
33
|
-
* to what a developer want everytime there is an angle
|
|
34
|
-
* @deprecated
|
|
35
|
-
*/
|
|
28
|
+
UniqueLineCoords {}
|
|
29
|
+
|
|
36
30
|
export class Line<
|
|
37
31
|
Props extends TOptions<FabricObjectProps> = Partial<FabricObjectProps>,
|
|
38
32
|
SProps extends SerializedLineProps = SerializedLineProps,
|
|
39
33
|
EventSpec extends ObjectEvents = ObjectEvents,
|
|
40
34
|
>
|
|
41
35
|
extends FabricObject<Props, SProps, EventSpec>
|
|
42
|
-
implements
|
|
36
|
+
implements UniqueLineCoords
|
|
43
37
|
{
|
|
44
|
-
/**
|
|
45
|
-
* x value or first line edge
|
|
46
|
-
* @type number
|
|
47
|
-
*/
|
|
48
38
|
declare x1: number;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* y value or first line edge
|
|
52
|
-
* @type number
|
|
53
|
-
*/
|
|
54
39
|
declare y1: number;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* x value or second line edge
|
|
58
|
-
* @type number
|
|
59
|
-
*/
|
|
60
40
|
declare x2: number;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* y value or second line edge
|
|
64
|
-
* @type number
|
|
65
|
-
*/
|
|
66
41
|
declare y2: number;
|
|
67
42
|
|
|
68
|
-
|
|
43
|
+
hitStrokeWidth: number | 'auto' = 'auto';
|
|
69
44
|
|
|
45
|
+
private _updatingEndpoints = false;
|
|
46
|
+
private _useEndpointCoords = true;
|
|
47
|
+
private _exportingSVG = false;
|
|
48
|
+
|
|
49
|
+
static type = 'Line';
|
|
70
50
|
static cacheProperties = [...cacheProperties, ...coordProps];
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
*/
|
|
77
|
-
constructor([x1, y1, x2, y2] = [0, 0, 0, 0], options: Partial<Props> = {}) {
|
|
51
|
+
|
|
52
|
+
constructor(
|
|
53
|
+
[x1, y1, x2, y2] = [0, 0, 100, 0],
|
|
54
|
+
options: Partial<Props & { hitStrokeWidth?: number | 'auto' }> = {},
|
|
55
|
+
) {
|
|
78
56
|
super();
|
|
79
|
-
Object.assign(this, Line.ownDefaults);
|
|
80
57
|
this.setOptions(options);
|
|
81
58
|
this.x1 = x1;
|
|
82
59
|
this.x2 = x2;
|
|
83
60
|
this.y1 = y1;
|
|
84
61
|
this.y2 = y2;
|
|
62
|
+
|
|
63
|
+
if (options.hitStrokeWidth !== undefined) {
|
|
64
|
+
this.hitStrokeWidth = options.hitStrokeWidth;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this.hasBorders = false;
|
|
68
|
+
this.hasControls = true;
|
|
69
|
+
this.selectable = true;
|
|
70
|
+
this.hoverCursor = 'move';
|
|
71
|
+
this.perPixelTargetFind = false;
|
|
72
|
+
this.strokeLineCap = 'butt';
|
|
73
|
+
|
|
85
74
|
this._setWidthHeight();
|
|
86
75
|
const { left, top } = options;
|
|
87
76
|
typeof left === 'number' && this.set(LEFT, left);
|
|
88
77
|
typeof top === 'number' && this.set(TOP, top);
|
|
78
|
+
this._setupLineControls();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
_setupLineControls() {
|
|
82
|
+
this.controls = {
|
|
83
|
+
p1: new Control({
|
|
84
|
+
x: 0,
|
|
85
|
+
y: 0,
|
|
86
|
+
cursorStyle: 'move',
|
|
87
|
+
actionHandler: this._endpointActionHandler.bind(this),
|
|
88
|
+
positionHandler: this._p1PositionHandler.bind(this),
|
|
89
|
+
render: this._renderEndpointControl.bind(this),
|
|
90
|
+
sizeX: 12,
|
|
91
|
+
sizeY: 12,
|
|
92
|
+
}),
|
|
93
|
+
p2: new Control({
|
|
94
|
+
x: 0,
|
|
95
|
+
y: 0,
|
|
96
|
+
cursorStyle: 'move',
|
|
97
|
+
actionHandler: this._endpointActionHandler.bind(this),
|
|
98
|
+
positionHandler: this._p2PositionHandler.bind(this),
|
|
99
|
+
render: this._renderEndpointControl.bind(this),
|
|
100
|
+
sizeX: 12,
|
|
101
|
+
sizeY: 12,
|
|
102
|
+
}),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
_p1PositionHandler() {
|
|
107
|
+
return new Point(this.x1, this.y1).transform(this.getViewportTransform());
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
_p2PositionHandler() {
|
|
111
|
+
return new Point(this.x2, this.y2).transform(this.getViewportTransform());
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
_renderEndpointControl(
|
|
115
|
+
ctx: CanvasRenderingContext2D,
|
|
116
|
+
left: number,
|
|
117
|
+
top: number,
|
|
118
|
+
) {
|
|
119
|
+
const size = 12;
|
|
120
|
+
ctx.save();
|
|
121
|
+
ctx.fillStyle = '#007bff';
|
|
122
|
+
ctx.strokeStyle = '#ffffff';
|
|
123
|
+
ctx.lineWidth = 2;
|
|
124
|
+
ctx.beginPath();
|
|
125
|
+
ctx.arc(left, top, size / 2, 0, 2 * Math.PI);
|
|
126
|
+
ctx.fill();
|
|
127
|
+
ctx.stroke();
|
|
128
|
+
ctx.restore();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
drawBorders(ctx: CanvasRenderingContext2D, styleOverride: any = {}) {
|
|
132
|
+
if (this._useEndpointCoords) {
|
|
133
|
+
this._drawLineBorders(ctx, styleOverride);
|
|
134
|
+
return this;
|
|
135
|
+
}
|
|
136
|
+
return super.drawBorders(ctx, styleOverride, {});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
_drawLineBorders(ctx: CanvasRenderingContext2D, styleOverride: any = {}) {
|
|
140
|
+
const vpt = this.canvas?.viewportTransform || [1, 0, 0, 1, 0, 0];
|
|
141
|
+
ctx.save();
|
|
142
|
+
ctx.setTransform(vpt[0], vpt[1], vpt[2], vpt[3], vpt[4], vpt[5]);
|
|
143
|
+
ctx.strokeStyle =
|
|
144
|
+
styleOverride.borderColor ||
|
|
145
|
+
this.borderColor ||
|
|
146
|
+
'rgba(100, 200, 200, 0.5)';
|
|
147
|
+
ctx.lineWidth = (this.strokeWidth || 1) + 5;
|
|
148
|
+
ctx.lineCap = this.strokeLineCap || 'butt';
|
|
149
|
+
ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
|
|
150
|
+
ctx.beginPath();
|
|
151
|
+
ctx.moveTo(this.x1, this.y1);
|
|
152
|
+
ctx.lineTo(this.x2, this.y2);
|
|
153
|
+
ctx.stroke();
|
|
154
|
+
ctx.restore();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
_renderControls(ctx: CanvasRenderingContext2D, styleOverride: any = {}) {
|
|
158
|
+
ctx.save();
|
|
159
|
+
ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
|
|
160
|
+
this.drawControls(ctx, styleOverride);
|
|
161
|
+
ctx.restore();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
getBoundingRect() {
|
|
165
|
+
if (this._useEndpointCoords) {
|
|
166
|
+
const { x1, y1, x2, y2 } = this;
|
|
167
|
+
const effectiveStrokeWidth =
|
|
168
|
+
this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth;
|
|
169
|
+
const padding = Math.max(effectiveStrokeWidth / 2 + 5, 10);
|
|
170
|
+
return {
|
|
171
|
+
left: Math.min(x1, x2) - padding,
|
|
172
|
+
top: Math.min(y1, y2) - padding,
|
|
173
|
+
width: Math.abs(x2 - x1) + padding * 2 || padding * 2,
|
|
174
|
+
height: Math.abs(y2 - y1) + padding * 2 || padding * 2,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
return super.getBoundingRect();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
setCoords() {
|
|
181
|
+
if (this._useEndpointCoords) {
|
|
182
|
+
// Set width and height for hit detection and bounding box
|
|
183
|
+
const effectiveStrokeWidth =
|
|
184
|
+
this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth;
|
|
185
|
+
const hitPadding = Math.max(effectiveStrokeWidth / 2 + 5, 10);
|
|
186
|
+
this.width = Math.abs(this.x2 - this.x1) + hitPadding * 2;
|
|
187
|
+
this.height = Math.abs(this.y2 - this.y1) + hitPadding * 2;
|
|
188
|
+
|
|
189
|
+
// Only update left/top if they haven't been explicitly set (e.g., during loading)
|
|
190
|
+
if (this.left === 0 && this.top === 0) {
|
|
191
|
+
const center = this._findCenterFromElement();
|
|
192
|
+
this.left = center.x;
|
|
193
|
+
this.top = center.y;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
super.setCoords();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
getCoords(): [Point, Point, Point, Point] {
|
|
200
|
+
if (this._useEndpointCoords) {
|
|
201
|
+
const deltaX = this.x2 - this.x1;
|
|
202
|
+
const deltaY = this.y2 - this.y1;
|
|
203
|
+
const length = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
204
|
+
|
|
205
|
+
if (length === 0) {
|
|
206
|
+
return super.getCoords() as [Point, Point, Point, Point];
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const effectiveStrokeWidth =
|
|
210
|
+
this.hitStrokeWidth === 'auto' ? this.strokeWidth : this.hitStrokeWidth;
|
|
211
|
+
const halfWidth = Math.max(effectiveStrokeWidth / 2 + 2, 5);
|
|
212
|
+
|
|
213
|
+
// Unit vector perpendicular to line
|
|
214
|
+
const perpX = -deltaY / length;
|
|
215
|
+
const perpY = deltaX / length;
|
|
216
|
+
|
|
217
|
+
// Four corners of oriented rectangle
|
|
218
|
+
return [
|
|
219
|
+
new Point(this.x1 + perpX * halfWidth, this.y1 + perpY * halfWidth),
|
|
220
|
+
new Point(this.x2 + perpX * halfWidth, this.y2 + perpY * halfWidth),
|
|
221
|
+
new Point(this.x2 - perpX * halfWidth, this.y2 - perpY * halfWidth),
|
|
222
|
+
new Point(this.x1 - perpX * halfWidth, this.y1 - perpY * halfWidth),
|
|
223
|
+
];
|
|
224
|
+
}
|
|
225
|
+
return super.getCoords() as [Point, Point, Point, Point];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
containsPoint(point: Point): boolean {
|
|
229
|
+
if (this._useEndpointCoords) {
|
|
230
|
+
if (this.canvas?.getActiveObject() === this) {
|
|
231
|
+
return super.containsPoint(point);
|
|
232
|
+
}
|
|
233
|
+
const distance = this._distanceToLineSegment(point.x, point.y);
|
|
234
|
+
const effectiveStrokeWidth =
|
|
235
|
+
this.hitStrokeWidth === 'auto'
|
|
236
|
+
? this.strokeWidth
|
|
237
|
+
: this.hitStrokeWidth || 1;
|
|
238
|
+
|
|
239
|
+
const tolerance = Math.max(effectiveStrokeWidth / 2 + 2, 5);
|
|
240
|
+
return distance <= tolerance;
|
|
241
|
+
}
|
|
242
|
+
return super.containsPoint(point);
|
|
89
243
|
}
|
|
90
244
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
245
|
+
_distanceToLineSegment(px: number, py: number): number {
|
|
246
|
+
const x1 = this.x1,
|
|
247
|
+
y1 = this.y1,
|
|
248
|
+
x2 = this.x2,
|
|
249
|
+
y2 = this.y2;
|
|
250
|
+
|
|
251
|
+
const pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
|
|
252
|
+
if (pd2 === 0) {
|
|
253
|
+
return Math.sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
|
|
257
|
+
|
|
258
|
+
let closestX: number, closestY: number;
|
|
259
|
+
if (u < 0) {
|
|
260
|
+
closestX = x1;
|
|
261
|
+
closestY = y1;
|
|
262
|
+
} else if (u > 1) {
|
|
263
|
+
closestX = x2;
|
|
264
|
+
closestY = y2;
|
|
265
|
+
} else {
|
|
266
|
+
closestX = x1 + u * (x2 - x1);
|
|
267
|
+
closestY = y1 + u * (y2 - y1);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return Math.sqrt(
|
|
271
|
+
(px - closestX) * (px - closestX) + (py - closestY) * (py - closestY),
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
_endpointActionHandler(
|
|
276
|
+
eventData: TPointerEvent,
|
|
277
|
+
transformData: Transform,
|
|
278
|
+
x: number,
|
|
279
|
+
y: number,
|
|
280
|
+
) {
|
|
281
|
+
const controlKey = transformData.corner;
|
|
282
|
+
const pointer = new Point(x, y);
|
|
283
|
+
let newX = pointer.x;
|
|
284
|
+
let newY = pointer.y;
|
|
285
|
+
|
|
286
|
+
if (eventData.shiftKey) {
|
|
287
|
+
const otherControl = controlKey === 'p1' ? 'p2' : 'p1';
|
|
288
|
+
const otherX = this[otherControl === 'p1' ? 'x1' : 'x2'];
|
|
289
|
+
const otherY = this[otherControl === 'p1' ? 'y1' : 'y2'];
|
|
290
|
+
const snapped = this._snapToAngle(otherX, otherY, newX, newY);
|
|
291
|
+
newX = snapped.x;
|
|
292
|
+
newY = snapped.y;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (this._useEndpointCoords) {
|
|
296
|
+
if (controlKey === 'p1') {
|
|
297
|
+
this.x1 = newX;
|
|
298
|
+
this.y1 = newY;
|
|
299
|
+
} else if (controlKey === 'p2') {
|
|
300
|
+
this.x2 = newX;
|
|
301
|
+
this.y2 = newY;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Update gradient coordinates if stroke is a gradient (but not during SVG export)
|
|
305
|
+
if (this.stroke instanceof Gradient && !this._exportingSVG) {
|
|
306
|
+
this.stroke.coords.x1 = this.x1;
|
|
307
|
+
this.stroke.coords.y1 = this.y1;
|
|
308
|
+
this.stroke.coords.x2 = this.x2;
|
|
309
|
+
this.stroke.coords.y2 = this.y2;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
this.dirty = true;
|
|
313
|
+
this.setCoords();
|
|
314
|
+
this.canvas?.requestRenderAll();
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Fallback for old system
|
|
319
|
+
this._updatingEndpoints = true;
|
|
320
|
+
if (controlKey === 'p1') {
|
|
321
|
+
this.x1 = newX;
|
|
322
|
+
this.y1 = newY;
|
|
323
|
+
} else if (controlKey === 'p2') {
|
|
324
|
+
this.x2 = newX;
|
|
325
|
+
this.y2 = newY;
|
|
326
|
+
}
|
|
327
|
+
this._setWidthHeight();
|
|
328
|
+
this.dirty = true;
|
|
329
|
+
this._updatingEndpoints = false;
|
|
330
|
+
this.canvas?.requestRenderAll();
|
|
331
|
+
this.fire('modified', {
|
|
332
|
+
transform: transformData,
|
|
333
|
+
target: this,
|
|
334
|
+
e: eventData,
|
|
335
|
+
});
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
_snapToAngle(
|
|
340
|
+
fromX: number,
|
|
341
|
+
fromY: number,
|
|
342
|
+
toX: number,
|
|
343
|
+
toY: number,
|
|
344
|
+
): { x: number; y: number } {
|
|
345
|
+
const deltaX = toX - fromX;
|
|
346
|
+
const deltaY = toY - fromY;
|
|
347
|
+
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
348
|
+
if (distance === 0) return { x: toX, y: toY };
|
|
349
|
+
let angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
|
|
350
|
+
const snapIncrement = 15;
|
|
351
|
+
const snappedAngle = Math.round(angle / snapIncrement) * snapIncrement;
|
|
352
|
+
const snappedRadians = snappedAngle * (Math.PI / 180);
|
|
353
|
+
return {
|
|
354
|
+
x: fromX + Math.cos(snappedRadians) * distance,
|
|
355
|
+
y: fromY + Math.sin(snappedRadians) * distance,
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
_setWidthHeight(skipReposition = false) {
|
|
360
|
+
this.width = Math.abs(this.x2 - this.x1) || 1;
|
|
361
|
+
this.height = Math.abs(this.y2 - this.y1) || 1;
|
|
362
|
+
if (!skipReposition && !this._updatingEndpoints) {
|
|
363
|
+
const { left, top, width, height } = makeBoundingBoxFromPoints([
|
|
364
|
+
{ x: this.x1, y: this.y1 },
|
|
365
|
+
{ x: this.x2, y: this.y2 },
|
|
366
|
+
]);
|
|
367
|
+
this.setPositionByOrigin(
|
|
368
|
+
new Point(left + width / 2, top + height / 2),
|
|
369
|
+
CENTER,
|
|
370
|
+
CENTER,
|
|
371
|
+
);
|
|
372
|
+
}
|
|
105
373
|
}
|
|
106
374
|
|
|
107
|
-
/**
|
|
108
|
-
* @private
|
|
109
|
-
* @param {String} key
|
|
110
|
-
* @param {*} value
|
|
111
|
-
*/
|
|
112
375
|
_set(key: string, value: any) {
|
|
376
|
+
const oldLeft = this.left;
|
|
377
|
+
const oldTop = this.top;
|
|
113
378
|
super._set(key, value);
|
|
114
|
-
if (coordProps.includes(key as keyof
|
|
115
|
-
// this doesn't make sense very much, since setting x1 when top or left
|
|
116
|
-
// are already set, is just going to show a strange result since the
|
|
117
|
-
// line will move way more than the developer expect.
|
|
118
|
-
// in fabric5 it worked only when the line didn't have extra transformations,
|
|
119
|
-
// in fabric6 too. With extra transform they behave bad in different ways.
|
|
120
|
-
// This needs probably a good rework or a tutorial if you have to create a dynamic line
|
|
379
|
+
if (coordProps.includes(key as keyof UniqueLineCoords)) {
|
|
121
380
|
this._setWidthHeight();
|
|
381
|
+
this.dirty = true;
|
|
382
|
+
|
|
383
|
+
// Update gradient coordinates if stroke is a gradient (but not during SVG export)
|
|
384
|
+
if (this.stroke instanceof Gradient && !this._exportingSVG) {
|
|
385
|
+
this.stroke.coords.x1 = this.x1;
|
|
386
|
+
this.stroke.coords.y1 = this.y1;
|
|
387
|
+
this.stroke.coords.x2 = this.x2;
|
|
388
|
+
this.stroke.coords.y2 = this.y2;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
if (
|
|
392
|
+
(key === 'left' || key === 'top') &&
|
|
393
|
+
this.canvas &&
|
|
394
|
+
!this._updatingEndpoints
|
|
395
|
+
) {
|
|
396
|
+
const deltaX = this.left - oldLeft;
|
|
397
|
+
const deltaY = this.top - oldTop;
|
|
398
|
+
if (deltaX !== 0 || deltaY !== 0) {
|
|
399
|
+
this._updatingEndpoints = true;
|
|
400
|
+
this.x1 += deltaX;
|
|
401
|
+
this.y1 += deltaY;
|
|
402
|
+
this.x2 += deltaX;
|
|
403
|
+
this.y2 += deltaY;
|
|
404
|
+
|
|
405
|
+
// Update gradient coordinates if stroke is a gradient
|
|
406
|
+
if (this.stroke instanceof Gradient) {
|
|
407
|
+
this.stroke.coords.x1 = this.x1;
|
|
408
|
+
this.stroke.coords.y1 = this.y1;
|
|
409
|
+
this.stroke.coords.x2 = this.x2;
|
|
410
|
+
this.stroke.coords.y2 = this.y2;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
this._updatingEndpoints = false;
|
|
414
|
+
}
|
|
122
415
|
}
|
|
123
416
|
return this;
|
|
124
417
|
}
|
|
125
418
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
419
|
+
render(ctx: CanvasRenderingContext2D) {
|
|
420
|
+
if (this._useEndpointCoords) {
|
|
421
|
+
this._renderDirectly(ctx);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
super.render(ctx);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
_renderDirectly(ctx: CanvasRenderingContext2D) {
|
|
428
|
+
if (!this.visible) return;
|
|
429
|
+
ctx.save();
|
|
430
|
+
ctx.globalAlpha = this.opacity;
|
|
431
|
+
ctx.lineWidth = this.strokeWidth;
|
|
432
|
+
ctx.lineCap = this.strokeLineCap || 'butt';
|
|
131
433
|
ctx.beginPath();
|
|
434
|
+
ctx.moveTo(this.x1, this.y1);
|
|
435
|
+
ctx.lineTo(this.x2, this.y2);
|
|
132
436
|
|
|
437
|
+
const origStrokeStyle = ctx.strokeStyle;
|
|
438
|
+
if (isFiller(this.stroke)) {
|
|
439
|
+
ctx.strokeStyle = this.stroke.toLive(ctx)!;
|
|
440
|
+
} else {
|
|
441
|
+
ctx.strokeStyle = this.stroke?.toString() || '#000';
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
ctx.stroke();
|
|
445
|
+
ctx.strokeStyle = origStrokeStyle;
|
|
446
|
+
ctx.restore();
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
_render(ctx: CanvasRenderingContext2D) {
|
|
450
|
+
if (this._useEndpointCoords) return;
|
|
451
|
+
ctx.beginPath();
|
|
133
452
|
const p = this.calcLinePoints();
|
|
134
453
|
ctx.moveTo(p.x1, p.y1);
|
|
135
454
|
ctx.lineTo(p.x2, p.y2);
|
|
136
|
-
|
|
137
455
|
ctx.lineWidth = this.strokeWidth;
|
|
138
|
-
|
|
139
|
-
// TODO: test this
|
|
140
|
-
// make sure setting "fill" changes color of a line
|
|
141
|
-
// (by copying fillStyle to strokeStyle, since line is stroked, not filled)
|
|
142
456
|
const origStrokeStyle = ctx.strokeStyle;
|
|
143
457
|
if (isFiller(this.stroke)) {
|
|
144
458
|
ctx.strokeStyle = this.stroke.toLive(ctx)!;
|
|
145
|
-
} else {
|
|
146
|
-
ctx.strokeStyle = this.stroke ?? ctx.fillStyle;
|
|
147
459
|
}
|
|
148
460
|
this.stroke && this._renderStroke(ctx);
|
|
149
461
|
ctx.strokeStyle = origStrokeStyle;
|
|
150
462
|
}
|
|
151
463
|
|
|
152
|
-
/**
|
|
153
|
-
* This function is an helper for svg import. it returns the center of the object in the svg
|
|
154
|
-
* untransformed coordinates
|
|
155
|
-
* @private
|
|
156
|
-
* @return {Point} center point from element coordinates
|
|
157
|
-
*/
|
|
158
464
|
_findCenterFromElement(): Point {
|
|
159
465
|
return new Point((this.x1 + this.x2) / 2, (this.y1 + this.y2) / 2);
|
|
160
466
|
}
|
|
161
467
|
|
|
162
|
-
/**
|
|
163
|
-
* Returns object representation of an instance
|
|
164
|
-
* @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
|
|
165
|
-
* @return {Object} object representation of an instance
|
|
166
|
-
*/
|
|
167
468
|
toObject<
|
|
168
469
|
T extends Omit<Props & TClassProperties<this>, keyof SProps>,
|
|
169
470
|
K extends keyof T = never,
|
|
170
471
|
>(propertiesToInclude: K[] = []): Pick<T, K> & SProps {
|
|
472
|
+
if (this._useEndpointCoords) {
|
|
473
|
+
return {
|
|
474
|
+
...super.toObject(propertiesToInclude),
|
|
475
|
+
x1: this.x1,
|
|
476
|
+
y1: this.y1,
|
|
477
|
+
x2: this.x2,
|
|
478
|
+
y2: this.y2,
|
|
479
|
+
};
|
|
480
|
+
}
|
|
171
481
|
return {
|
|
172
482
|
...super.toObject(propertiesToInclude),
|
|
173
483
|
...this.calcLinePoints(),
|
|
174
484
|
};
|
|
175
485
|
}
|
|
176
486
|
|
|
177
|
-
/*
|
|
178
|
-
* Calculate object dimensions from its properties
|
|
179
|
-
* @private
|
|
180
|
-
*/
|
|
181
487
|
_getNonTransformedDimensions(): Point {
|
|
182
488
|
const dim = super._getNonTransformedDimensions();
|
|
183
|
-
if (this.strokeLineCap === '
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
if (this.height === 0) {
|
|
188
|
-
dim.x -= this.strokeWidth;
|
|
189
|
-
}
|
|
489
|
+
if (this.strokeLineCap === 'round') {
|
|
490
|
+
dim.x += this.strokeWidth;
|
|
491
|
+
dim.y += this.strokeWidth;
|
|
190
492
|
}
|
|
191
493
|
return dim;
|
|
192
494
|
}
|
|
193
495
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
496
|
+
calcLinePoints(): UniqueLineCoords {
|
|
497
|
+
if (this._updatingEndpoints) {
|
|
498
|
+
const centerX = (this.x1 + this.x2) / 2;
|
|
499
|
+
const centerY = (this.y1 + this.y2) / 2;
|
|
500
|
+
return {
|
|
501
|
+
x1: this.x1 - centerX,
|
|
502
|
+
y1: this.y1 - centerY,
|
|
503
|
+
x2: this.x2 - centerX,
|
|
504
|
+
y2: this.y2 - centerY,
|
|
505
|
+
};
|
|
506
|
+
}
|
|
202
507
|
const { x1: _x1, x2: _x2, y1: _y1, y2: _y2, width, height } = this;
|
|
203
|
-
const xMult = _x1 <= _x2 ? -1 : 1
|
|
204
|
-
|
|
205
|
-
x1 = (xMult * width) / 2,
|
|
206
|
-
y1 = (yMult * height) / 2,
|
|
207
|
-
x2 = (xMult * -width) / 2,
|
|
208
|
-
y2 = (yMult * -height) / 2;
|
|
209
|
-
|
|
508
|
+
const xMult = _x1 <= _x2 ? -1 : 1;
|
|
509
|
+
const yMult = _y1 <= _y2 ? -1 : 1;
|
|
210
510
|
return {
|
|
211
|
-
x1,
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
y2,
|
|
511
|
+
x1: (xMult * width) / 2,
|
|
512
|
+
y1: (yMult * height) / 2,
|
|
513
|
+
x2: (xMult * -width) / 2,
|
|
514
|
+
y2: (yMult * -height) / 2,
|
|
215
515
|
};
|
|
216
516
|
}
|
|
217
517
|
|
|
218
|
-
/* _FROM_SVG_START_ */
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Returns svg representation of an instance
|
|
222
|
-
* @return {Array} an array of strings with the specific svg representation
|
|
223
|
-
* of the instance
|
|
224
|
-
*/
|
|
225
518
|
_toSVG() {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
'
|
|
230
|
-
|
|
231
|
-
|
|
519
|
+
if (this._useEndpointCoords) {
|
|
520
|
+
// Use absolute coordinates to bypass all Fabric.js transforms
|
|
521
|
+
// Handle gradients manually for proper SVG export
|
|
522
|
+
let strokeAttr = '';
|
|
523
|
+
if (this.stroke instanceof Gradient) {
|
|
524
|
+
// Let Fabric.js handle gradient definition, but we'll use the reference
|
|
525
|
+
strokeAttr = `stroke="url(#${this.stroke.id})"`;
|
|
526
|
+
} else {
|
|
527
|
+
strokeAttr = `stroke="${this.stroke || 'none'}"`;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
return [
|
|
531
|
+
`<line ${strokeAttr} stroke-width="${this.strokeWidth}" stroke-linecap="${this.strokeLineCap}" `,
|
|
532
|
+
`stroke-dasharray="${this.strokeDashArray ? this.strokeDashArray.join(' ') : 'none'}" `,
|
|
533
|
+
`stroke-dashoffset="${this.strokeDashOffset}" stroke-linejoin="${this.strokeLineJoin}" `,
|
|
534
|
+
`stroke-miterlimit="${this.strokeMiterLimit}" fill="${this.fill || 'none'}" `,
|
|
535
|
+
`fill-rule="${this.fillRule}" opacity="${this.opacity}" `,
|
|
536
|
+
`x1="${this.x1}" y1="${this.y1}" x2="${this.x2}" y2="${this.y2}" />\n`,
|
|
537
|
+
];
|
|
538
|
+
} else {
|
|
539
|
+
// Use standard calcLinePoints for legacy mode
|
|
540
|
+
const { x1, x2, y1, y2 } = this.calcLinePoints();
|
|
541
|
+
return [
|
|
542
|
+
'<line ',
|
|
543
|
+
'COMMON_PARTS',
|
|
544
|
+
`x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" />\n`,
|
|
545
|
+
];
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
toSVG(reviver?: (markup: string) => string): string {
|
|
550
|
+
if (this._useEndpointCoords) {
|
|
551
|
+
// For endpoint coords, we need to bypass transforms but still allow gradients
|
|
552
|
+
// Let's temporarily disable transforms during SVG generation
|
|
553
|
+
const originalLeft = this.left;
|
|
554
|
+
const originalTop = this.top;
|
|
555
|
+
|
|
556
|
+
// Set position to center of line for gradient calculation
|
|
557
|
+
this.left = (this.x1 + this.x2) / 2;
|
|
558
|
+
this.top = (this.y1 + this.y2) / 2;
|
|
559
|
+
|
|
560
|
+
// Get the SVG with standard system (for gradient handling)
|
|
561
|
+
const standardSVG = super.toSVG(reviver);
|
|
562
|
+
|
|
563
|
+
// Restore original position
|
|
564
|
+
this.left = originalLeft;
|
|
565
|
+
this.top = originalTop;
|
|
566
|
+
|
|
567
|
+
// Extract gradient definition and clean up the line element
|
|
568
|
+
// Remove the transform wrapper and update coordinates
|
|
569
|
+
const cleanSVG = standardSVG
|
|
570
|
+
.replace(/<g transform="[^"]*"[^>]*>/g, '')
|
|
571
|
+
.replace(/<\/g>/g, '')
|
|
572
|
+
.replace(/x1="[^"]*"/g, `x1="${this.x1}"`)
|
|
573
|
+
.replace(/y1="[^"]*"/g, `y1="${this.y1}"`)
|
|
574
|
+
.replace(/x2="[^"]*"/g, `x2="${this.x2}"`)
|
|
575
|
+
.replace(/y2="[^"]*"/g, `y2="${this.y2}"`);
|
|
576
|
+
|
|
577
|
+
return cleanSVG;
|
|
578
|
+
}
|
|
579
|
+
// Use default behavior for legacy mode
|
|
580
|
+
return super.toSVG(reviver);
|
|
232
581
|
}
|
|
233
582
|
|
|
234
|
-
/**
|
|
235
|
-
* List of attribute names to account for when parsing SVG element (used by {@link Line.fromElement})
|
|
236
|
-
* @see http://www.w3.org/TR/SVG/shapes.html#LineElement
|
|
237
|
-
*/
|
|
238
583
|
static ATTRIBUTE_NAMES = SHARED_ATTRIBUTES.concat(coordProps);
|
|
239
584
|
|
|
240
|
-
/**
|
|
241
|
-
* Returns Line instance from an SVG element
|
|
242
|
-
* @param {HTMLElement} element Element to parse
|
|
243
|
-
* @param {Object} [options] Options object
|
|
244
|
-
* @param {Function} [callback] callback function invoked after parsing
|
|
245
|
-
*/
|
|
246
585
|
static async fromElement(
|
|
247
586
|
element: HTMLElement,
|
|
248
587
|
options?: Abortable,
|
|
@@ -258,13 +597,6 @@ export class Line<
|
|
|
258
597
|
return new this([x1, y1, x2, y2], parsedAttributes);
|
|
259
598
|
}
|
|
260
599
|
|
|
261
|
-
/* _FROM_SVG_END_ */
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Returns Line instance from an object representation
|
|
265
|
-
* @param {Object} object Object to create an instance from
|
|
266
|
-
* @returns {Promise<Line>}
|
|
267
|
-
*/
|
|
268
600
|
static fromObject<T extends TOptions<SerializedLineProps>>({
|
|
269
601
|
x1,
|
|
270
602
|
y1,
|
|
@@ -273,13 +605,8 @@ export class Line<
|
|
|
273
605
|
...object
|
|
274
606
|
}: T) {
|
|
275
607
|
return this._fromObject<Line>(
|
|
276
|
-
{
|
|
277
|
-
|
|
278
|
-
points: [x1, y1, x2, y2],
|
|
279
|
-
},
|
|
280
|
-
{
|
|
281
|
-
extraParam: 'points',
|
|
282
|
-
},
|
|
608
|
+
{ ...object, points: [x1, y1, x2, y2] },
|
|
609
|
+
{ extraParam: 'points' },
|
|
283
610
|
);
|
|
284
611
|
}
|
|
285
612
|
}
|