fabric 4.6.0-browser → 5.1.0-browser
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/CHANGELOG.md +54 -0
- package/HEADER.js +1 -1
- package/README.md +1 -6
- package/SECURITY.md +5 -0
- package/dist/fabric.js +692 -400
- package/dist/fabric.min.js +1 -1
- package/lib/event.js +7 -3
- package/package.json +5 -3
- package/src/brushes/base_brush.class.js +2 -2
- package/src/brushes/pattern_brush.class.js +7 -5
- package/src/brushes/pencil_brush.class.js +33 -4
- package/src/canvas.class.js +9 -17
- package/src/filters/blendcolor_filter.class.js +6 -0
- package/src/filters/blendimage_filter.class.js +3 -2
- package/src/filters/blur_filter.class.js +2 -0
- package/src/filters/colormatrix_filter.class.js +3 -1
- package/src/mixins/animation.mixin.js +16 -21
- package/src/mixins/canvas_events.mixin.js +27 -56
- package/src/mixins/eraser_brush.mixin.js +354 -420
- package/src/mixins/itext_behavior.mixin.js +7 -1
- package/src/mixins/object_geometry.mixin.js +3 -34
- package/src/mixins/object_straightening.mixin.js +4 -9
- package/src/parser.js +13 -9
- package/src/shapes/circle.class.js +20 -17
- package/src/shapes/group.class.js +13 -25
- package/src/shapes/image.class.js +3 -3
- package/src/shapes/object.class.js +46 -19
- package/src/shapes/path.class.js +13 -9
- package/src/shapes/polygon.class.js +9 -1
- package/src/shapes/polyline.class.js +33 -9
- package/src/shapes/text.class.js +38 -21
- package/src/static_canvas.class.js +11 -7
- package/src/util/animate.js +175 -26
- package/src/util/misc.js +193 -45
- package/src/util/path.js +2 -56
package/dist/fabric.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* build: `node build.js modules=ALL exclude=gestures,accessors,erasing requirejs minifier=uglifyjs` */
|
|
2
2
|
/*! Fabric.js Copyright 2008-2015, Printio (Juriy Zaytsev, Maxim Chernyak) */
|
|
3
3
|
|
|
4
|
-
var fabric = fabric || { version: '
|
|
4
|
+
var fabric = fabric || { version: '5.1.0' };
|
|
5
5
|
if (typeof exports !== 'undefined') {
|
|
6
6
|
exports.fabric = fabric;
|
|
7
7
|
}
|
|
@@ -762,6 +762,135 @@ fabric.CommonMethods = {
|
|
|
762
762
|
};
|
|
763
763
|
},
|
|
764
764
|
|
|
765
|
+
/**
|
|
766
|
+
* Creates a vetor from points represented as a point
|
|
767
|
+
* @static
|
|
768
|
+
* @memberOf fabric.util
|
|
769
|
+
*
|
|
770
|
+
* @typedef {Object} Point
|
|
771
|
+
* @property {number} x
|
|
772
|
+
* @property {number} y
|
|
773
|
+
*
|
|
774
|
+
* @param {Point} from
|
|
775
|
+
* @param {Point} to
|
|
776
|
+
* @returns {Point} vector
|
|
777
|
+
*/
|
|
778
|
+
createVector: function (from, to) {
|
|
779
|
+
return new fabric.Point(to.x - from.x, to.y - from.y);
|
|
780
|
+
},
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Calculates angle between 2 vectors using dot product
|
|
784
|
+
* @static
|
|
785
|
+
* @memberOf fabric.util
|
|
786
|
+
* @param {Point} a
|
|
787
|
+
* @param {Point} b
|
|
788
|
+
* @returns the angle in radian between the vectors
|
|
789
|
+
*/
|
|
790
|
+
calcAngleBetweenVectors: function (a, b) {
|
|
791
|
+
return Math.acos((a.x * b.x + a.y * b.y) / (Math.hypot(a.x, a.y) * Math.hypot(b.x, b.y)));
|
|
792
|
+
},
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* @static
|
|
796
|
+
* @memberOf fabric.util
|
|
797
|
+
* @param {Point} v
|
|
798
|
+
* @returns {Point} vector representing the unit vector of pointing to the direction of `v`
|
|
799
|
+
*/
|
|
800
|
+
getHatVector: function (v) {
|
|
801
|
+
return new fabric.Point(v.x, v.y).multiply(1 / Math.hypot(v.x, v.y));
|
|
802
|
+
},
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* @static
|
|
806
|
+
* @memberOf fabric.util
|
|
807
|
+
* @param {Point} A
|
|
808
|
+
* @param {Point} B
|
|
809
|
+
* @param {Point} C
|
|
810
|
+
* @returns {{ vector: Point, angle: number }} vector representing the bisector of A and A's angle
|
|
811
|
+
*/
|
|
812
|
+
getBisector: function (A, B, C) {
|
|
813
|
+
var AB = fabric.util.createVector(A, B), AC = fabric.util.createVector(A, C);
|
|
814
|
+
var alpha = fabric.util.calcAngleBetweenVectors(AB, AC);
|
|
815
|
+
// check if alpha is relative to AB->BC
|
|
816
|
+
var ro = fabric.util.calcAngleBetweenVectors(fabric.util.rotateVector(AB, alpha), AC);
|
|
817
|
+
var phi = alpha * (ro === 0 ? 1 : -1) / 2;
|
|
818
|
+
return {
|
|
819
|
+
vector: fabric.util.getHatVector(fabric.util.rotateVector(AB, phi)),
|
|
820
|
+
angle: alpha
|
|
821
|
+
};
|
|
822
|
+
},
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Project stroke width on points returning 2 projections for each point as follows:
|
|
826
|
+
* - `miter`: 2 points corresponding to the outer boundary and the inner boundary of stroke.
|
|
827
|
+
* - `bevel`: 2 points corresponding to the bevel boundaries, tangent to the bisector.
|
|
828
|
+
* - `round`: same as `bevel`
|
|
829
|
+
* Used to calculate object's bounding box
|
|
830
|
+
* @static
|
|
831
|
+
* @memberOf fabric.util
|
|
832
|
+
* @param {Point[]} points
|
|
833
|
+
* @param {Object} options
|
|
834
|
+
* @param {number} options.strokeWidth
|
|
835
|
+
* @param {'miter'|'bevel'|'round'} options.strokeLineJoin
|
|
836
|
+
* @param {number} options.strokeMiterLimit https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit
|
|
837
|
+
* @param {boolean} options.strokeUniform
|
|
838
|
+
* @param {number} options.scaleX
|
|
839
|
+
* @param {number} options.scaleY
|
|
840
|
+
* @param {boolean} [openPath] whether the shape is open or not, affects the calculations of the first and last points
|
|
841
|
+
* @returns {fabric.Point[]} array of size 2n/4n of all suspected points
|
|
842
|
+
*/
|
|
843
|
+
projectStrokeOnPoints: function (points, options, openPath) {
|
|
844
|
+
var coords = [], s = options.strokeWidth / 2,
|
|
845
|
+
strokeUniformScalar = options.strokeUniform ?
|
|
846
|
+
new fabric.Point(1 / options.scaleX, 1 / options.scaleY) : new fabric.Point(1, 1),
|
|
847
|
+
getStrokeHatVector = function (v) {
|
|
848
|
+
var scalar = s / (Math.hypot(v.x, v.y));
|
|
849
|
+
return new fabric.Point(v.x * scalar * strokeUniformScalar.x, v.y * scalar * strokeUniformScalar.y);
|
|
850
|
+
};
|
|
851
|
+
if (points.length <= 1) {return coords;}
|
|
852
|
+
points.forEach(function (p, index) {
|
|
853
|
+
var A = new fabric.Point(p.x, p.y), B, C;
|
|
854
|
+
if (index === 0) {
|
|
855
|
+
C = points[index + 1];
|
|
856
|
+
B = openPath ? getStrokeHatVector(fabric.util.createVector(C, A)).addEquals(A) : points[points.length - 1];
|
|
857
|
+
}
|
|
858
|
+
else if (index === points.length - 1) {
|
|
859
|
+
B = points[index - 1];
|
|
860
|
+
C = openPath ? getStrokeHatVector(fabric.util.createVector(B, A)).addEquals(A) : points[0];
|
|
861
|
+
}
|
|
862
|
+
else {
|
|
863
|
+
B = points[index - 1];
|
|
864
|
+
C = points[index + 1];
|
|
865
|
+
}
|
|
866
|
+
var bisector = fabric.util.getBisector(A, B, C),
|
|
867
|
+
bisectorVector = bisector.vector,
|
|
868
|
+
alpha = bisector.angle,
|
|
869
|
+
scalar,
|
|
870
|
+
miterVector;
|
|
871
|
+
if (options.strokeLineJoin === 'miter') {
|
|
872
|
+
scalar = -s / Math.sin(alpha / 2);
|
|
873
|
+
miterVector = new fabric.Point(
|
|
874
|
+
bisectorVector.x * scalar * strokeUniformScalar.x,
|
|
875
|
+
bisectorVector.y * scalar * strokeUniformScalar.y
|
|
876
|
+
);
|
|
877
|
+
if (Math.hypot(miterVector.x, miterVector.y) / s <= options.strokeMiterLimit) {
|
|
878
|
+
coords.push(A.add(miterVector));
|
|
879
|
+
coords.push(A.subtract(miterVector));
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
scalar = -s * Math.SQRT2;
|
|
884
|
+
miterVector = new fabric.Point(
|
|
885
|
+
bisectorVector.x * scalar * strokeUniformScalar.x,
|
|
886
|
+
bisectorVector.y * scalar * strokeUniformScalar.y
|
|
887
|
+
);
|
|
888
|
+
coords.push(A.add(miterVector));
|
|
889
|
+
coords.push(A.subtract(miterVector));
|
|
890
|
+
});
|
|
891
|
+
return coords;
|
|
892
|
+
},
|
|
893
|
+
|
|
765
894
|
/**
|
|
766
895
|
* Apply transform t to point p
|
|
767
896
|
* @static
|
|
@@ -1074,6 +1203,25 @@ fabric.CommonMethods = {
|
|
|
1074
1203
|
});
|
|
1075
1204
|
},
|
|
1076
1205
|
|
|
1206
|
+
/**
|
|
1207
|
+
* Creates corresponding fabric instances residing in an object, e.g. `clipPath`
|
|
1208
|
+
* @see {@link fabric.Object.ENLIVEN_PROPS}
|
|
1209
|
+
* @param {Object} object
|
|
1210
|
+
* @param {Object} [context] assign enlived props to this object (pass null to skip this)
|
|
1211
|
+
* @param {(objects:fabric.Object[]) => void} callback
|
|
1212
|
+
*/
|
|
1213
|
+
enlivenObjectEnlivables: function (object, context, callback) {
|
|
1214
|
+
var enlivenProps = fabric.Object.ENLIVEN_PROPS.filter(function (key) { return !!object[key]; });
|
|
1215
|
+
fabric.util.enlivenObjects(enlivenProps.map(function (key) { return object[key]; }), function (enlivedProps) {
|
|
1216
|
+
var objects = {};
|
|
1217
|
+
enlivenProps.forEach(function (key, index) {
|
|
1218
|
+
objects[key] = enlivedProps[index];
|
|
1219
|
+
context && (context[key] = enlivedProps[index]);
|
|
1220
|
+
});
|
|
1221
|
+
callback && callback(objects);
|
|
1222
|
+
});
|
|
1223
|
+
},
|
|
1224
|
+
|
|
1077
1225
|
/**
|
|
1078
1226
|
* Create and wait for loading of patterns
|
|
1079
1227
|
* @static
|
|
@@ -1165,49 +1313,6 @@ fabric.CommonMethods = {
|
|
|
1165
1313
|
}
|
|
1166
1314
|
},
|
|
1167
1315
|
|
|
1168
|
-
/**
|
|
1169
|
-
* WARNING: THIS WAS TO SUPPORT OLD BROWSERS. deprecated.
|
|
1170
|
-
* WILL BE REMOVED IN FABRIC 5.0
|
|
1171
|
-
* Draws a dashed line between two points
|
|
1172
|
-
*
|
|
1173
|
-
* This method is used to draw dashed line around selection area.
|
|
1174
|
-
* See <a href="http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas">dotted stroke in canvas</a>
|
|
1175
|
-
*
|
|
1176
|
-
* @param {CanvasRenderingContext2D} ctx context
|
|
1177
|
-
* @param {Number} x start x coordinate
|
|
1178
|
-
* @param {Number} y start y coordinate
|
|
1179
|
-
* @param {Number} x2 end x coordinate
|
|
1180
|
-
* @param {Number} y2 end y coordinate
|
|
1181
|
-
* @param {Array} da dash array pattern
|
|
1182
|
-
* @deprecated
|
|
1183
|
-
*/
|
|
1184
|
-
drawDashedLine: function(ctx, x, y, x2, y2, da) {
|
|
1185
|
-
var dx = x2 - x,
|
|
1186
|
-
dy = y2 - y,
|
|
1187
|
-
len = sqrt(dx * dx + dy * dy),
|
|
1188
|
-
rot = atan2(dy, dx),
|
|
1189
|
-
dc = da.length,
|
|
1190
|
-
di = 0,
|
|
1191
|
-
draw = true;
|
|
1192
|
-
|
|
1193
|
-
ctx.save();
|
|
1194
|
-
ctx.translate(x, y);
|
|
1195
|
-
ctx.moveTo(0, 0);
|
|
1196
|
-
ctx.rotate(rot);
|
|
1197
|
-
|
|
1198
|
-
x = 0;
|
|
1199
|
-
while (len > x) {
|
|
1200
|
-
x += da[di++ % dc];
|
|
1201
|
-
if (x > len) {
|
|
1202
|
-
x = len;
|
|
1203
|
-
}
|
|
1204
|
-
ctx[draw ? 'lineTo' : 'moveTo'](x, 0);
|
|
1205
|
-
draw = !draw;
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
ctx.restore();
|
|
1209
|
-
},
|
|
1210
|
-
|
|
1211
1316
|
/**
|
|
1212
1317
|
* Creates canvas element
|
|
1213
1318
|
* @static
|
|
@@ -1335,7 +1440,7 @@ fabric.CommonMethods = {
|
|
|
1335
1440
|
* @param {Boolean} [options.flipX]
|
|
1336
1441
|
* @param {Boolean} [options.flipY]
|
|
1337
1442
|
* @param {Number} [options.skewX]
|
|
1338
|
-
* @param {Number} [options.
|
|
1443
|
+
* @param {Number} [options.skewY]
|
|
1339
1444
|
* @return {Number[]} transform matrix
|
|
1340
1445
|
*/
|
|
1341
1446
|
calcDimensionsMatrix: function(options) {
|
|
@@ -1689,7 +1794,50 @@ fabric.CommonMethods = {
|
|
|
1689
1794
|
x: bbox.width,
|
|
1690
1795
|
y: bbox.height,
|
|
1691
1796
|
};
|
|
1692
|
-
}
|
|
1797
|
+
},
|
|
1798
|
+
|
|
1799
|
+
/**
|
|
1800
|
+
* Merges 2 clip paths into one visually equal clip path
|
|
1801
|
+
*
|
|
1802
|
+
* **IMPORTANT**:\
|
|
1803
|
+
* Does **NOT** clone the arguments, clone them proir if necessary.
|
|
1804
|
+
*
|
|
1805
|
+
* Creates a wrapper (group) that contains one clip path and is clipped by the other so content is kept where both overlap.
|
|
1806
|
+
* Use this method if both the clip paths may have nested clip paths of their own, so assigning one to the other's clip path property is not possible.
|
|
1807
|
+
*
|
|
1808
|
+
* In order to handle the `inverted` property we follow logic described in the following cases:\
|
|
1809
|
+
* **(1)** both clip paths are inverted - the clip paths pass the inverted prop to the wrapper and loose it themselves.\
|
|
1810
|
+
* **(2)** one is inverted and the other isn't - the wrapper shouldn't become inverted and the inverted clip path must clip the non inverted one to produce an identical visual effect.\
|
|
1811
|
+
* **(3)** both clip paths are not inverted - wrapper and clip paths remain unchanged.
|
|
1812
|
+
*
|
|
1813
|
+
* @memberOf fabric.util
|
|
1814
|
+
* @param {fabric.Object} c1
|
|
1815
|
+
* @param {fabric.Object} c2
|
|
1816
|
+
* @returns {fabric.Object} merged clip path
|
|
1817
|
+
*/
|
|
1818
|
+
mergeClipPaths: function (c1, c2) {
|
|
1819
|
+
var a = c1, b = c2;
|
|
1820
|
+
if (a.inverted && !b.inverted) {
|
|
1821
|
+
// case (2)
|
|
1822
|
+
a = c2;
|
|
1823
|
+
b = c1;
|
|
1824
|
+
}
|
|
1825
|
+
// `b` becomes `a`'s clip path so we transform `b` to `a` coordinate plane
|
|
1826
|
+
fabric.util.applyTransformToObject(
|
|
1827
|
+
b,
|
|
1828
|
+
fabric.util.multiplyTransformMatrices(
|
|
1829
|
+
fabric.util.invertTransform(a.calcTransformMatrix()),
|
|
1830
|
+
b.calcTransformMatrix()
|
|
1831
|
+
)
|
|
1832
|
+
);
|
|
1833
|
+
// assign the `inverted` prop to the wrapping group
|
|
1834
|
+
var inverted = a.inverted && b.inverted;
|
|
1835
|
+
if (inverted) {
|
|
1836
|
+
// case (1)
|
|
1837
|
+
a.inverted = b.inverted = false;
|
|
1838
|
+
}
|
|
1839
|
+
return new fabric.Group([a], { clipPath: b, inverted: inverted });
|
|
1840
|
+
},
|
|
1693
1841
|
};
|
|
1694
1842
|
})(typeof exports !== 'undefined' ? exports : this);
|
|
1695
1843
|
|
|
@@ -2203,15 +2351,15 @@ fabric.CommonMethods = {
|
|
|
2203
2351
|
p, nextLen, nextStep = 0.01, angleFinder = segInfo.angleFinder, lastPerc;
|
|
2204
2352
|
// nextStep > 0.0001 covers 0.00015625 that 1/64th of 1/100
|
|
2205
2353
|
// the path
|
|
2206
|
-
while (tmpLen < distance &&
|
|
2354
|
+
while (tmpLen < distance && nextStep > 0.0001) {
|
|
2207
2355
|
p = iterator(perc);
|
|
2208
2356
|
lastPerc = perc;
|
|
2209
2357
|
nextLen = calcLineLength(tempP.x, tempP.y, p.x, p.y);
|
|
2210
2358
|
// compare tmpLen each cycle with distance, decide next perc to test.
|
|
2211
2359
|
if ((nextLen + tmpLen) > distance) {
|
|
2212
2360
|
// we discard this step and we make smaller steps.
|
|
2213
|
-
nextStep /= 2;
|
|
2214
2361
|
perc -= nextStep;
|
|
2362
|
+
nextStep /= 2;
|
|
2215
2363
|
}
|
|
2216
2364
|
else {
|
|
2217
2365
|
tempP = p;
|
|
@@ -2507,50 +2655,6 @@ fabric.CommonMethods = {
|
|
|
2507
2655
|
});
|
|
2508
2656
|
}
|
|
2509
2657
|
|
|
2510
|
-
/**
|
|
2511
|
-
* Calculate bounding box of a elliptic-arc
|
|
2512
|
-
* @deprecated
|
|
2513
|
-
* @param {Number} fx start point of arc
|
|
2514
|
-
* @param {Number} fy
|
|
2515
|
-
* @param {Number} rx horizontal radius
|
|
2516
|
-
* @param {Number} ry vertical radius
|
|
2517
|
-
* @param {Number} rot angle of horizontal axis
|
|
2518
|
-
* @param {Number} large 1 or 0, whatever the arc is the big or the small on the 2 points
|
|
2519
|
-
* @param {Number} sweep 1 or 0, 1 clockwise or counterclockwise direction
|
|
2520
|
-
* @param {Number} tx end point of arc
|
|
2521
|
-
* @param {Number} ty
|
|
2522
|
-
*/
|
|
2523
|
-
function getBoundsOfArc(fx, fy, rx, ry, rot, large, sweep, tx, ty) {
|
|
2524
|
-
|
|
2525
|
-
var fromX = 0, fromY = 0, bound, bounds = [],
|
|
2526
|
-
segs = arcToSegments(tx - fx, ty - fy, rx, ry, large, sweep, rot);
|
|
2527
|
-
|
|
2528
|
-
for (var i = 0, len = segs.length; i < len; i++) {
|
|
2529
|
-
bound = getBoundsOfCurve(fromX, fromY, segs[i][1], segs[i][2], segs[i][3], segs[i][4], segs[i][5], segs[i][6]);
|
|
2530
|
-
bounds.push({ x: bound[0].x + fx, y: bound[0].y + fy });
|
|
2531
|
-
bounds.push({ x: bound[1].x + fx, y: bound[1].y + fy });
|
|
2532
|
-
fromX = segs[i][5];
|
|
2533
|
-
fromY = segs[i][6];
|
|
2534
|
-
}
|
|
2535
|
-
return bounds;
|
|
2536
|
-
};
|
|
2537
|
-
|
|
2538
|
-
/**
|
|
2539
|
-
* Draws arc
|
|
2540
|
-
* @deprecated
|
|
2541
|
-
* @param {CanvasRenderingContext2D} ctx
|
|
2542
|
-
* @param {Number} fx
|
|
2543
|
-
* @param {Number} fy
|
|
2544
|
-
* @param {Array} coords coords of the arc, without the front 'A/a'
|
|
2545
|
-
*/
|
|
2546
|
-
function drawArc(ctx, fx, fy, coords) {
|
|
2547
|
-
coords = coords.slice(0).unshift('X'); // command A or a does not matter
|
|
2548
|
-
var beziers = fromArcToBeziers(fx, fy, coords);
|
|
2549
|
-
beziers.forEach(function(bezier) {
|
|
2550
|
-
ctx.bezierCurveTo.apply(ctx, bezier.slice(1));
|
|
2551
|
-
});
|
|
2552
|
-
};
|
|
2553
|
-
|
|
2554
2658
|
/**
|
|
2555
2659
|
* Join path commands to go back to svg format
|
|
2556
2660
|
* @param {Array} pathData fabricJS parsed path commands
|
|
@@ -2566,16 +2670,6 @@ fabric.CommonMethods = {
|
|
|
2566
2670
|
fabric.util.getBoundsOfCurve = getBoundsOfCurve;
|
|
2567
2671
|
fabric.util.getPointOnPath = getPointOnPath;
|
|
2568
2672
|
fabric.util.transformPath = transformPath;
|
|
2569
|
-
/**
|
|
2570
|
-
* Typo of `fromArcToBeziers` kept for not breaking the api once corrected.
|
|
2571
|
-
* Will be removed in fabric 5.0
|
|
2572
|
-
* @deprecated
|
|
2573
|
-
*/
|
|
2574
|
-
fabric.util.fromArcToBeizers = fromArcToBeziers;
|
|
2575
|
-
// kept because we do not want to make breaking changes.
|
|
2576
|
-
// but useless and deprecated.
|
|
2577
|
-
fabric.util.getBoundsOfArc = getBoundsOfArc;
|
|
2578
|
-
fabric.util.drawArc = drawArc;
|
|
2579
2673
|
})();
|
|
2580
2674
|
|
|
2581
2675
|
|
|
@@ -3476,7 +3570,132 @@ fabric.log = console.log;
|
|
|
3476
3570
|
fabric.warn = console.warn;
|
|
3477
3571
|
|
|
3478
3572
|
|
|
3479
|
-
(function() {
|
|
3573
|
+
(function () {
|
|
3574
|
+
|
|
3575
|
+
var extend = fabric.util.object.extend,
|
|
3576
|
+
clone = fabric.util.object.clone;
|
|
3577
|
+
|
|
3578
|
+
/**
|
|
3579
|
+
* @typedef {Object} AnimationOptions
|
|
3580
|
+
* Animation of a value or list of values.
|
|
3581
|
+
* When using lists, think of something like this:
|
|
3582
|
+
* fabric.util.animate({
|
|
3583
|
+
* startValue: [1, 2, 3],
|
|
3584
|
+
* endValue: [2, 4, 6],
|
|
3585
|
+
* onChange: function([a, b, c]) {
|
|
3586
|
+
* canvas.zoomToPoint({x: b, y: c}, a)
|
|
3587
|
+
* canvas.renderAll()
|
|
3588
|
+
* }
|
|
3589
|
+
* });
|
|
3590
|
+
* @example
|
|
3591
|
+
* @property {Function} [onChange] Callback; invoked on every value change
|
|
3592
|
+
* @property {Function} [onComplete] Callback; invoked when value change is completed
|
|
3593
|
+
* @example
|
|
3594
|
+
* // Note: startValue, endValue, and byValue must match the type
|
|
3595
|
+
* var animationOptions = { startValue: 0, endValue: 1, byValue: 0.25 }
|
|
3596
|
+
* var animationOptions = { startValue: [0, 1], endValue: [1, 2], byValue: [0.25, 0.25] }
|
|
3597
|
+
* @property {number | number[]} [startValue=0] Starting value
|
|
3598
|
+
* @property {number | number[]} [endValue=100] Ending value
|
|
3599
|
+
* @property {number | number[]} [byValue=100] Value to modify the property by
|
|
3600
|
+
* @property {Function} [easing] Easing function
|
|
3601
|
+
* @property {Number} [duration=500] Duration of change (in ms)
|
|
3602
|
+
* @property {Function} [abort] Additional function with logic. If returns true, animation aborts.
|
|
3603
|
+
*
|
|
3604
|
+
* @typedef {() => void} CancelFunction
|
|
3605
|
+
*
|
|
3606
|
+
* @typedef {Object} AnimationCurrentState
|
|
3607
|
+
* @property {number | number[]} currentValue value in range [`startValue`, `endValue`]
|
|
3608
|
+
* @property {number} completionRate value in range [0, 1]
|
|
3609
|
+
* @property {number} durationRate value in range [0, 1]
|
|
3610
|
+
*
|
|
3611
|
+
* @typedef {(AnimationOptions & AnimationCurrentState & { cancel: CancelFunction }} AnimationContext
|
|
3612
|
+
*/
|
|
3613
|
+
|
|
3614
|
+
/**
|
|
3615
|
+
* Array holding all running animations
|
|
3616
|
+
* @memberof fabric
|
|
3617
|
+
* @type {AnimationContext[]}
|
|
3618
|
+
*/
|
|
3619
|
+
var RUNNING_ANIMATIONS = [];
|
|
3620
|
+
fabric.util.object.extend(RUNNING_ANIMATIONS, {
|
|
3621
|
+
|
|
3622
|
+
/**
|
|
3623
|
+
* cancel all running animations at the next requestAnimFrame
|
|
3624
|
+
* @returns {AnimationContext[]}
|
|
3625
|
+
*/
|
|
3626
|
+
cancelAll: function () {
|
|
3627
|
+
var animations = this.splice(0);
|
|
3628
|
+
animations.forEach(function (animation) {
|
|
3629
|
+
animation.cancel();
|
|
3630
|
+
});
|
|
3631
|
+
return animations;
|
|
3632
|
+
},
|
|
3633
|
+
|
|
3634
|
+
/**
|
|
3635
|
+
* cancel all running animations attached to canvas at the next requestAnimFrame
|
|
3636
|
+
* @param {fabric.Canvas} canvas
|
|
3637
|
+
* @returns {AnimationContext[]}
|
|
3638
|
+
*/
|
|
3639
|
+
cancelByCanvas: function (canvas) {
|
|
3640
|
+
if (!canvas) {
|
|
3641
|
+
return [];
|
|
3642
|
+
}
|
|
3643
|
+
var cancelled = this.filter(function (animation) {
|
|
3644
|
+
return typeof animation.target === 'object' && animation.target.canvas === canvas;
|
|
3645
|
+
});
|
|
3646
|
+
cancelled.forEach(function (animation) {
|
|
3647
|
+
animation.cancel();
|
|
3648
|
+
});
|
|
3649
|
+
return cancelled;
|
|
3650
|
+
},
|
|
3651
|
+
|
|
3652
|
+
/**
|
|
3653
|
+
* cancel all running animations for target at the next requestAnimFrame
|
|
3654
|
+
* @param {*} target
|
|
3655
|
+
* @returns {AnimationContext[]}
|
|
3656
|
+
*/
|
|
3657
|
+
cancelByTarget: function (target) {
|
|
3658
|
+
var cancelled = this.findAnimationsByTarget(target);
|
|
3659
|
+
cancelled.forEach(function (animation) {
|
|
3660
|
+
animation.cancel();
|
|
3661
|
+
});
|
|
3662
|
+
return cancelled;
|
|
3663
|
+
},
|
|
3664
|
+
|
|
3665
|
+
/**
|
|
3666
|
+
*
|
|
3667
|
+
* @param {CancelFunction} cancelFunc the function returned by animate
|
|
3668
|
+
* @returns {number}
|
|
3669
|
+
*/
|
|
3670
|
+
findAnimationIndex: function (cancelFunc) {
|
|
3671
|
+
return this.indexOf(this.findAnimation(cancelFunc));
|
|
3672
|
+
},
|
|
3673
|
+
|
|
3674
|
+
/**
|
|
3675
|
+
*
|
|
3676
|
+
* @param {CancelFunction} cancelFunc the function returned by animate
|
|
3677
|
+
* @returns {AnimationContext | undefined} animation's options object
|
|
3678
|
+
*/
|
|
3679
|
+
findAnimation: function (cancelFunc) {
|
|
3680
|
+
return this.find(function (animation) {
|
|
3681
|
+
return animation.cancel === cancelFunc;
|
|
3682
|
+
});
|
|
3683
|
+
},
|
|
3684
|
+
|
|
3685
|
+
/**
|
|
3686
|
+
*
|
|
3687
|
+
* @param {*} target the object that is assigned to the target property of the animation context
|
|
3688
|
+
* @returns {AnimationContext[]} array of animation options object associated with target
|
|
3689
|
+
*/
|
|
3690
|
+
findAnimationsByTarget: function (target) {
|
|
3691
|
+
if (!target) {
|
|
3692
|
+
return [];
|
|
3693
|
+
}
|
|
3694
|
+
return this.filter(function (animation) {
|
|
3695
|
+
return animation.target === target;
|
|
3696
|
+
});
|
|
3697
|
+
}
|
|
3698
|
+
});
|
|
3480
3699
|
|
|
3481
3700
|
function noop() {
|
|
3482
3701
|
return false;
|
|
@@ -3489,22 +3708,34 @@ fabric.warn = console.warn;
|
|
|
3489
3708
|
/**
|
|
3490
3709
|
* Changes value from one to another within certain period of time, invoking callbacks as value is being changed.
|
|
3491
3710
|
* @memberOf fabric.util
|
|
3492
|
-
* @param {
|
|
3493
|
-
* @
|
|
3494
|
-
*
|
|
3495
|
-
*
|
|
3496
|
-
*
|
|
3497
|
-
* @
|
|
3498
|
-
* @param {Function} [options.easing] Easing function
|
|
3499
|
-
* @param {Number} [options.duration=500] Duration of change (in ms)
|
|
3500
|
-
* @param {Function} [options.abort] Additional function with logic. If returns true, onComplete is called.
|
|
3501
|
-
* @returns {Function} abort function
|
|
3711
|
+
* @param {AnimationOptions} [options] Animation options
|
|
3712
|
+
* @example
|
|
3713
|
+
* // Note: startValue, endValue, and byValue must match the type
|
|
3714
|
+
* fabric.util.animate({ startValue: 0, endValue: 1, byValue: 0.25 })
|
|
3715
|
+
* fabric.util.animate({ startValue: [0, 1], endValue: [1, 2], byValue: [0.25, 0.25] })
|
|
3716
|
+
* @returns {CancelFunction} cancel function
|
|
3502
3717
|
*/
|
|
3503
3718
|
function animate(options) {
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3719
|
+
options || (options = {});
|
|
3720
|
+
var cancel = false,
|
|
3721
|
+
context,
|
|
3722
|
+
removeFromRegistry = function () {
|
|
3723
|
+
var index = fabric.runningAnimations.indexOf(context);
|
|
3724
|
+
return index > -1 && fabric.runningAnimations.splice(index, 1)[0];
|
|
3725
|
+
};
|
|
3726
|
+
|
|
3727
|
+
context = extend(clone(options), {
|
|
3728
|
+
cancel: function () {
|
|
3729
|
+
cancel = true;
|
|
3730
|
+
return removeFromRegistry();
|
|
3731
|
+
},
|
|
3732
|
+
currentValue: 'startValue' in options ? options.startValue : 0,
|
|
3733
|
+
completionRate: 0,
|
|
3734
|
+
durationRate: 0
|
|
3735
|
+
});
|
|
3736
|
+
fabric.runningAnimations.push(context);
|
|
3507
3737
|
|
|
3738
|
+
requestAnimFrame(function(timestamp) {
|
|
3508
3739
|
var start = timestamp || +new Date(),
|
|
3509
3740
|
duration = options.duration || 500,
|
|
3510
3741
|
finish = start + duration, time,
|
|
@@ -3512,32 +3743,44 @@ fabric.warn = console.warn;
|
|
|
3512
3743
|
abort = options.abort || noop,
|
|
3513
3744
|
onComplete = options.onComplete || noop,
|
|
3514
3745
|
easing = options.easing || defaultEasing,
|
|
3746
|
+
isMany = 'startValue' in options ? options.startValue.length > 0 : false,
|
|
3515
3747
|
startValue = 'startValue' in options ? options.startValue : 0,
|
|
3516
3748
|
endValue = 'endValue' in options ? options.endValue : 100,
|
|
3517
|
-
byValue = options.byValue ||
|
|
3749
|
+
byValue = options.byValue || (isMany ? startValue.map(function(value, i) {
|
|
3750
|
+
return endValue[i] - startValue[i];
|
|
3751
|
+
}) : endValue - startValue);
|
|
3518
3752
|
|
|
3519
3753
|
options.onStart && options.onStart();
|
|
3520
3754
|
|
|
3521
3755
|
(function tick(ticktime) {
|
|
3522
|
-
// TODO: move abort call after calculation
|
|
3523
|
-
// and pass (current,valuePerc, timePerc) as arguments
|
|
3524
3756
|
time = ticktime || +new Date();
|
|
3525
3757
|
var currentTime = time > finish ? duration : (time - start),
|
|
3526
3758
|
timePerc = currentTime / duration,
|
|
3527
|
-
current =
|
|
3528
|
-
|
|
3759
|
+
current = isMany ? startValue.map(function(_value, i) {
|
|
3760
|
+
return easing(currentTime, startValue[i], byValue[i], duration);
|
|
3761
|
+
}) : easing(currentTime, startValue, byValue, duration),
|
|
3762
|
+
valuePerc = isMany ? Math.abs((current[0] - startValue[0]) / byValue[0])
|
|
3763
|
+
: Math.abs((current - startValue) / byValue);
|
|
3764
|
+
// update context
|
|
3765
|
+
context.currentValue = isMany ? current.slice() : current;
|
|
3766
|
+
context.completionRate = valuePerc;
|
|
3767
|
+
context.durationRate = timePerc;
|
|
3529
3768
|
if (cancel) {
|
|
3530
3769
|
return;
|
|
3531
3770
|
}
|
|
3532
3771
|
if (abort(current, valuePerc, timePerc)) {
|
|
3533
|
-
|
|
3534
|
-
// does to even make sense to abort and run onComplete?
|
|
3535
|
-
onComplete(endValue, 1, 1);
|
|
3772
|
+
removeFromRegistry();
|
|
3536
3773
|
return;
|
|
3537
3774
|
}
|
|
3538
3775
|
if (time > finish) {
|
|
3539
|
-
|
|
3776
|
+
// update context
|
|
3777
|
+
context.currentValue = isMany ? endValue.slice() : endValue;
|
|
3778
|
+
context.completionRate = 1;
|
|
3779
|
+
context.durationRate = 1;
|
|
3780
|
+
// execute callbacks
|
|
3781
|
+
onChange(isMany ? endValue.slice() : endValue, 1, 1);
|
|
3540
3782
|
onComplete(endValue, 1, 1);
|
|
3783
|
+
removeFromRegistry();
|
|
3541
3784
|
return;
|
|
3542
3785
|
}
|
|
3543
3786
|
else {
|
|
@@ -3546,9 +3789,8 @@ fabric.warn = console.warn;
|
|
|
3546
3789
|
}
|
|
3547
3790
|
})(start);
|
|
3548
3791
|
});
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
};
|
|
3792
|
+
|
|
3793
|
+
return context.cancel;
|
|
3552
3794
|
}
|
|
3553
3795
|
|
|
3554
3796
|
var _requestAnimFrame = fabric.window.requestAnimationFrame ||
|
|
@@ -3580,6 +3822,7 @@ fabric.warn = console.warn;
|
|
|
3580
3822
|
fabric.util.animate = animate;
|
|
3581
3823
|
fabric.util.requestAnimFrame = requestAnimFrame;
|
|
3582
3824
|
fabric.util.cancelAnimFrame = cancelAnimFrame;
|
|
3825
|
+
fabric.runningAnimations = RUNNING_ANIMATIONS;
|
|
3583
3826
|
})();
|
|
3584
3827
|
|
|
3585
3828
|
|
|
@@ -5062,22 +5305,26 @@ fabric.warn = console.warn;
|
|
|
5062
5305
|
if (styleContents.trim() === '') {
|
|
5063
5306
|
continue;
|
|
5064
5307
|
}
|
|
5065
|
-
|
|
5066
|
-
rules =
|
|
5308
|
+
// recovers all the rule in this form `body { style code... }`
|
|
5309
|
+
// rules = styleContents.match(/[^{]*\{[\s\S]*?\}/g);
|
|
5310
|
+
rules = styleContents.split('}');
|
|
5311
|
+
// remove empty rules.
|
|
5312
|
+
rules = rules.filter(function(rule) { return rule.trim(); });
|
|
5313
|
+
// at this point we have hopefully an array of rules `body { style code... `
|
|
5067
5314
|
// eslint-disable-next-line no-loop-func
|
|
5068
5315
|
rules.forEach(function(rule) {
|
|
5069
5316
|
|
|
5070
|
-
var match = rule.
|
|
5071
|
-
ruleObj = { }, declaration = match[
|
|
5072
|
-
propertyValuePairs = declaration.
|
|
5317
|
+
var match = rule.split('{'),
|
|
5318
|
+
ruleObj = { }, declaration = match[1].trim(),
|
|
5319
|
+
propertyValuePairs = declaration.split(';').filter(function(pair) { return pair.trim(); });
|
|
5073
5320
|
|
|
5074
5321
|
for (i = 0, len = propertyValuePairs.length; i < len; i++) {
|
|
5075
|
-
var pair = propertyValuePairs[i].split(
|
|
5076
|
-
property = pair[0],
|
|
5077
|
-
value = pair[1];
|
|
5322
|
+
var pair = propertyValuePairs[i].split(':'),
|
|
5323
|
+
property = pair[0].trim(),
|
|
5324
|
+
value = pair[1].trim();
|
|
5078
5325
|
ruleObj[property] = value;
|
|
5079
5326
|
}
|
|
5080
|
-
rule = match[
|
|
5327
|
+
rule = match[0].trim();
|
|
5081
5328
|
rule.split(',').forEach(function(_rule) {
|
|
5082
5329
|
_rule = _rule.replace(/^svg/i, '').trim();
|
|
5083
5330
|
if (_rule === '') {
|
|
@@ -8652,8 +8899,12 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
8652
8899
|
imageSmoothingEnabled: true,
|
|
8653
8900
|
|
|
8654
8901
|
/**
|
|
8655
|
-
* The transformation (
|
|
8902
|
+
* The transformation (a Canvas 2D API transform matrix) which focuses the viewport
|
|
8656
8903
|
* @type Array
|
|
8904
|
+
* @example <caption>Default transform</caption>
|
|
8905
|
+
* canvas.viewportTransform = [1, 0, 0, 1, 0, 0];
|
|
8906
|
+
* @example <caption>Scale by 70% and translate toward bottom-right by 50, without skewing</caption>
|
|
8907
|
+
* canvas.viewportTransform = [0.7, 0, 0, 0.7, 50, 50];
|
|
8657
8908
|
* @default
|
|
8658
8909
|
*/
|
|
8659
8910
|
viewportTransform: fabric.iMatrix.concat(),
|
|
@@ -8747,7 +8998,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
8747
8998
|
* @private
|
|
8748
8999
|
*/
|
|
8749
9000
|
_isRetinaScaling: function() {
|
|
8750
|
-
return (fabric.devicePixelRatio
|
|
9001
|
+
return (fabric.devicePixelRatio > 1 && this.enableRetinaScaling);
|
|
8751
9002
|
},
|
|
8752
9003
|
|
|
8753
9004
|
/**
|
|
@@ -8755,7 +9006,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
8755
9006
|
* @return {Number} retinaScaling if applied, otherwise 1;
|
|
8756
9007
|
*/
|
|
8757
9008
|
getRetinaScaling: function() {
|
|
8758
|
-
return this._isRetinaScaling() ? fabric.devicePixelRatio : 1;
|
|
9009
|
+
return this._isRetinaScaling() ? Math.max(1, fabric.devicePixelRatio) : 1;
|
|
8759
9010
|
},
|
|
8760
9011
|
|
|
8761
9012
|
/**
|
|
@@ -9122,7 +9373,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
9122
9373
|
}
|
|
9123
9374
|
}
|
|
9124
9375
|
if (this._isCurrentlyDrawing) {
|
|
9125
|
-
this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles();
|
|
9376
|
+
this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles(this.contextTop);
|
|
9126
9377
|
}
|
|
9127
9378
|
this._initRetinaScaling();
|
|
9128
9379
|
this.calcOffset();
|
|
@@ -9189,8 +9440,8 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
9189
9440
|
},
|
|
9190
9441
|
|
|
9191
9442
|
/**
|
|
9192
|
-
* Sets viewport
|
|
9193
|
-
* @param {Array} vpt
|
|
9443
|
+
* Sets viewport transformation of this canvas instance
|
|
9444
|
+
* @param {Array} vpt a Canvas 2D API transform matrix
|
|
9194
9445
|
* @return {fabric.Canvas} instance
|
|
9195
9446
|
* @chainable true
|
|
9196
9447
|
*/
|
|
@@ -10291,7 +10542,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
10291
10542
|
this.contextContainer = null;
|
|
10292
10543
|
// restore canvas style
|
|
10293
10544
|
this.lowerCanvasEl.classList.remove('lower-canvas');
|
|
10294
|
-
this.lowerCanvasEl
|
|
10545
|
+
fabric.util.setStyle(this.lowerCanvasEl, this._originalCanvasStyle);
|
|
10295
10546
|
delete this._originalCanvasStyle;
|
|
10296
10547
|
// restore canvas size to original size in case retina scaling was applied
|
|
10297
10548
|
this.lowerCanvasEl.setAttribute('width', this.width);
|
|
@@ -10459,9 +10710,9 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10459
10710
|
/**
|
|
10460
10711
|
* Sets brush styles
|
|
10461
10712
|
* @private
|
|
10713
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
10462
10714
|
*/
|
|
10463
|
-
_setBrushStyles: function() {
|
|
10464
|
-
var ctx = this.canvas.contextTop;
|
|
10715
|
+
_setBrushStyles: function (ctx) {
|
|
10465
10716
|
ctx.strokeStyle = this.color;
|
|
10466
10717
|
ctx.lineWidth = this.width;
|
|
10467
10718
|
ctx.lineCap = this.strokeLineCap;
|
|
@@ -10546,6 +10797,22 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10546
10797
|
*/
|
|
10547
10798
|
decimate: 0.4,
|
|
10548
10799
|
|
|
10800
|
+
/**
|
|
10801
|
+
* Draws a straight line between last recorded point to current pointer
|
|
10802
|
+
* Used for `shift` functionality
|
|
10803
|
+
*
|
|
10804
|
+
* @type boolean
|
|
10805
|
+
* @default false
|
|
10806
|
+
*/
|
|
10807
|
+
drawStraightLine: false,
|
|
10808
|
+
|
|
10809
|
+
/**
|
|
10810
|
+
* The event modifier key that makes the brush draw a straight line.
|
|
10811
|
+
* If `null` or 'none' or any other string that is not a modifier key the feature is disabled.
|
|
10812
|
+
* @type {'altKey' | 'shiftKey' | 'ctrlKey' | 'none' | undefined | null}
|
|
10813
|
+
*/
|
|
10814
|
+
straightLineKey: 'shiftKey',
|
|
10815
|
+
|
|
10549
10816
|
/**
|
|
10550
10817
|
* Constructor
|
|
10551
10818
|
* @param {fabric.Canvas} canvas
|
|
@@ -10556,6 +10823,10 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10556
10823
|
this._points = [];
|
|
10557
10824
|
},
|
|
10558
10825
|
|
|
10826
|
+
needsFullRender: function () {
|
|
10827
|
+
return this.callSuper('needsFullRender') || this._hasStraightLine;
|
|
10828
|
+
},
|
|
10829
|
+
|
|
10559
10830
|
/**
|
|
10560
10831
|
* Invoked inside on mouse down and mouse move
|
|
10561
10832
|
* @param {Object} pointer
|
|
@@ -10574,6 +10845,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10574
10845
|
if (!this.canvas._isMainEvent(options.e)) {
|
|
10575
10846
|
return;
|
|
10576
10847
|
}
|
|
10848
|
+
this.drawStraightLine = options.e[this.straightLineKey];
|
|
10577
10849
|
this._prepareForDrawing(pointer);
|
|
10578
10850
|
// capture coordinates immediately
|
|
10579
10851
|
// this allows to draw dots (when movement never occurs)
|
|
@@ -10589,6 +10861,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10589
10861
|
if (!this.canvas._isMainEvent(options.e)) {
|
|
10590
10862
|
return;
|
|
10591
10863
|
}
|
|
10864
|
+
this.drawStraightLine = options.e[this.straightLineKey];
|
|
10592
10865
|
if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {
|
|
10593
10866
|
return;
|
|
10594
10867
|
}
|
|
@@ -10621,6 +10894,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10621
10894
|
if (!this.canvas._isMainEvent(options.e)) {
|
|
10622
10895
|
return true;
|
|
10623
10896
|
}
|
|
10897
|
+
this.drawStraightLine = false;
|
|
10624
10898
|
this.oldEnd = undefined;
|
|
10625
10899
|
this._finalizeAndAddPath();
|
|
10626
10900
|
return false;
|
|
@@ -10647,6 +10921,10 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10647
10921
|
if (this._points.length > 1 && point.eq(this._points[this._points.length - 1])) {
|
|
10648
10922
|
return false;
|
|
10649
10923
|
}
|
|
10924
|
+
if (this.drawStraightLine && this._points.length > 1) {
|
|
10925
|
+
this._hasStraightLine = true;
|
|
10926
|
+
this._points.pop();
|
|
10927
|
+
}
|
|
10650
10928
|
this._points.push(point);
|
|
10651
10929
|
return true;
|
|
10652
10930
|
},
|
|
@@ -10657,8 +10935,9 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10657
10935
|
*/
|
|
10658
10936
|
_reset: function() {
|
|
10659
10937
|
this._points = [];
|
|
10660
|
-
this._setBrushStyles();
|
|
10938
|
+
this._setBrushStyles(this.canvas.contextTop);
|
|
10661
10939
|
this._setShadow();
|
|
10940
|
+
this._hasStraightLine = false;
|
|
10662
10941
|
},
|
|
10663
10942
|
|
|
10664
10943
|
/**
|
|
@@ -10673,12 +10952,13 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10673
10952
|
/**
|
|
10674
10953
|
* Draw a smooth path on the topCanvas using quadraticCurveTo
|
|
10675
10954
|
* @private
|
|
10955
|
+
* @param {CanvasRenderingContext2D} [ctx]
|
|
10676
10956
|
*/
|
|
10677
|
-
_render: function() {
|
|
10678
|
-
var
|
|
10957
|
+
_render: function(ctx) {
|
|
10958
|
+
var i, len,
|
|
10679
10959
|
p1 = this._points[0],
|
|
10680
10960
|
p2 = this._points[1];
|
|
10681
|
-
|
|
10961
|
+
ctx = ctx || this.canvas.contextTop;
|
|
10682
10962
|
this._saveAndTransform(ctx);
|
|
10683
10963
|
ctx.beginPath();
|
|
10684
10964
|
//if we only have 2 points in the path and they are the same
|
|
@@ -11212,17 +11492,19 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
11212
11492
|
|
|
11213
11493
|
/**
|
|
11214
11494
|
* Creates "pattern" instance property
|
|
11495
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
11215
11496
|
*/
|
|
11216
|
-
getPattern: function() {
|
|
11217
|
-
return
|
|
11497
|
+
getPattern: function(ctx) {
|
|
11498
|
+
return ctx.createPattern(this.source || this.getPatternSrc(), 'repeat');
|
|
11218
11499
|
},
|
|
11219
11500
|
|
|
11220
11501
|
/**
|
|
11221
11502
|
* Sets brush styles
|
|
11503
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
11222
11504
|
*/
|
|
11223
|
-
_setBrushStyles: function() {
|
|
11224
|
-
this.callSuper('_setBrushStyles');
|
|
11225
|
-
|
|
11505
|
+
_setBrushStyles: function(ctx) {
|
|
11506
|
+
this.callSuper('_setBrushStyles', ctx);
|
|
11507
|
+
ctx.strokeStyle = this.getPattern(ctx);
|
|
11226
11508
|
},
|
|
11227
11509
|
|
|
11228
11510
|
/**
|
|
@@ -11281,15 +11563,11 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
11281
11563
|
* @fires dragover
|
|
11282
11564
|
* @fires dragenter
|
|
11283
11565
|
* @fires dragleave
|
|
11566
|
+
* @fires drop:before before drop event. same native event. This is added to handle edge cases
|
|
11284
11567
|
* @fires drop
|
|
11285
11568
|
* @fires after:render at the end of the render process, receives the context in the callback
|
|
11286
11569
|
* @fires before:render at start the render process, receives the context in the callback
|
|
11287
11570
|
*
|
|
11288
|
-
* the following events are deprecated:
|
|
11289
|
-
* @fires object:rotated at the end of a rotation transform
|
|
11290
|
-
* @fires object:scaled at the end of a scale transform
|
|
11291
|
-
* @fires object:moved at the end of translation transform
|
|
11292
|
-
* @fires object:skewed at the end of a skew transform
|
|
11293
11571
|
*/
|
|
11294
11572
|
fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ {
|
|
11295
11573
|
|
|
@@ -11474,13 +11752,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
11474
11752
|
*/
|
|
11475
11753
|
freeDrawingCursor: 'crosshair',
|
|
11476
11754
|
|
|
11477
|
-
/**
|
|
11478
|
-
* Cursor value used for rotation point
|
|
11479
|
-
* @type String
|
|
11480
|
-
* @default
|
|
11481
|
-
*/
|
|
11482
|
-
rotationCursor: 'crosshair',
|
|
11483
|
-
|
|
11484
11755
|
/**
|
|
11485
11756
|
* Cursor value used for disabled elements ( corners with disabled action )
|
|
11486
11757
|
* @type String
|
|
@@ -11586,6 +11857,13 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
11586
11857
|
*/
|
|
11587
11858
|
targets: [],
|
|
11588
11859
|
|
|
11860
|
+
/**
|
|
11861
|
+
* When the option is enabled, PointerEvent is used instead of MouseEvent.
|
|
11862
|
+
* @type Boolean
|
|
11863
|
+
* @default
|
|
11864
|
+
*/
|
|
11865
|
+
enablePointerEvents: false,
|
|
11866
|
+
|
|
11589
11867
|
/**
|
|
11590
11868
|
* Keep track of the hovered target
|
|
11591
11869
|
* @type fabric.Object
|
|
@@ -11661,6 +11939,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
11661
11939
|
}
|
|
11662
11940
|
if (this.hasLostContext) {
|
|
11663
11941
|
this.renderTopLayer(this.contextTop);
|
|
11942
|
+
this.hasLostContext = false;
|
|
11664
11943
|
}
|
|
11665
11944
|
var canvasToDrawOn = this.contextContainer;
|
|
11666
11945
|
this.renderCanvas(canvasToDrawOn, this._chooseObjectsToRender());
|
|
@@ -12330,17 +12609,12 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
12330
12609
|
e: e,
|
|
12331
12610
|
selected: added,
|
|
12332
12611
|
deselected: removed,
|
|
12333
|
-
// added for backward compatibility
|
|
12334
|
-
// deprecated
|
|
12335
|
-
updated: added[0] || removed[0],
|
|
12336
|
-
target: this._activeObject,
|
|
12337
12612
|
});
|
|
12338
12613
|
}
|
|
12339
12614
|
else if (objects.length > 0) {
|
|
12340
12615
|
this.fire('selection:created', {
|
|
12341
12616
|
e: e,
|
|
12342
12617
|
selected: added,
|
|
12343
|
-
target: this._activeObject,
|
|
12344
12618
|
});
|
|
12345
12619
|
}
|
|
12346
12620
|
else if (oldObjects.length > 0) {
|
|
@@ -12664,7 +12938,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
12664
12938
|
this._onDragOver = this._onDragOver.bind(this);
|
|
12665
12939
|
this._onDragEnter = this._simpleEventHandler.bind(this, 'dragenter');
|
|
12666
12940
|
this._onDragLeave = this._simpleEventHandler.bind(this, 'dragleave');
|
|
12667
|
-
this._onDrop = this.
|
|
12941
|
+
this._onDrop = this._onDrop.bind(this);
|
|
12668
12942
|
this.eventsBound = true;
|
|
12669
12943
|
},
|
|
12670
12944
|
|
|
@@ -12776,6 +13050,18 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
12776
13050
|
this._fireEnterLeaveEvents(target, e);
|
|
12777
13051
|
},
|
|
12778
13052
|
|
|
13053
|
+
/**
|
|
13054
|
+
* `drop:before` is a an event that allow you to schedule logic
|
|
13055
|
+
* before the `drop` event. Prefer `drop` event always, but if you need
|
|
13056
|
+
* to run some drop-disabling logic on an event, since there is no way
|
|
13057
|
+
* to handle event handlers ordering, use `drop:before`
|
|
13058
|
+
* @param {Event} e
|
|
13059
|
+
*/
|
|
13060
|
+
_onDrop: function (e) {
|
|
13061
|
+
this._simpleEventHandler('drop:before', e);
|
|
13062
|
+
return this._simpleEventHandler('drop', e);
|
|
13063
|
+
},
|
|
13064
|
+
|
|
12779
13065
|
/**
|
|
12780
13066
|
* @private
|
|
12781
13067
|
* @param {Event} e Event object fired on mousedown
|
|
@@ -13008,25 +13294,34 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
13008
13294
|
);
|
|
13009
13295
|
}
|
|
13010
13296
|
}
|
|
13297
|
+
var corner, pointer;
|
|
13011
13298
|
if (target) {
|
|
13299
|
+
corner = target._findTargetCorner(
|
|
13300
|
+
this.getPointer(e, true),
|
|
13301
|
+
fabric.util.isTouchEvent(e)
|
|
13302
|
+
);
|
|
13012
13303
|
if (target.selectable && target !== this._activeObject && target.activeOn === 'up') {
|
|
13013
13304
|
this.setActiveObject(target, e);
|
|
13014
13305
|
shouldRender = true;
|
|
13015
13306
|
}
|
|
13016
13307
|
else {
|
|
13017
|
-
var corner = target._findTargetCorner(
|
|
13018
|
-
this.getPointer(e, true),
|
|
13019
|
-
fabric.util.isTouchEvent(e)
|
|
13020
|
-
);
|
|
13021
13308
|
var control = target.controls[corner],
|
|
13022
13309
|
mouseUpHandler = control && control.getMouseUpHandler(e, target, control);
|
|
13023
13310
|
if (mouseUpHandler) {
|
|
13024
|
-
|
|
13311
|
+
pointer = this.getPointer(e);
|
|
13025
13312
|
mouseUpHandler(e, transform, pointer.x, pointer.y);
|
|
13026
13313
|
}
|
|
13027
13314
|
}
|
|
13028
13315
|
target.isMoving = false;
|
|
13029
13316
|
}
|
|
13317
|
+
// if we are ending up a transform on a different control or a new object
|
|
13318
|
+
// fire the original mouse up from the corner that started the transform
|
|
13319
|
+
if (transform && (transform.target !== target || transform.corner !== corner)) {
|
|
13320
|
+
var originalControl = transform.target && transform.target.controls[transform.corner],
|
|
13321
|
+
originalMouseUpHandler = originalControl && originalControl.getMouseUpHandler(e, target, control);
|
|
13322
|
+
pointer = pointer || this.getPointer(e);
|
|
13323
|
+
originalMouseUpHandler && originalMouseUpHandler(e, transform, pointer.x, pointer.y);
|
|
13324
|
+
}
|
|
13030
13325
|
this._setCursorFromEvent(e, target);
|
|
13031
13326
|
this._handleEvent(e, 'up', LEFT_CLICK, isClick);
|
|
13032
13327
|
this._groupSelector = null;
|
|
@@ -13108,7 +13403,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
13108
13403
|
|
|
13109
13404
|
var transform = this._currentTransform,
|
|
13110
13405
|
target = transform.target,
|
|
13111
|
-
eventName,
|
|
13112
13406
|
options = {
|
|
13113
13407
|
e: e,
|
|
13114
13408
|
target: target,
|
|
@@ -13123,59 +13417,10 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
13123
13417
|
target.setCoords();
|
|
13124
13418
|
|
|
13125
13419
|
if (transform.actionPerformed || (this.stateful && target.hasStateChanged())) {
|
|
13126
|
-
if (transform.actionPerformed) {
|
|
13127
|
-
// this is not friendly to the new control api.
|
|
13128
|
-
// is deprecated.
|
|
13129
|
-
eventName = this._addEventOptions(options, transform);
|
|
13130
|
-
this._fire(eventName, options);
|
|
13131
|
-
}
|
|
13132
13420
|
this._fire('modified', options);
|
|
13133
13421
|
}
|
|
13134
13422
|
},
|
|
13135
13423
|
|
|
13136
|
-
/**
|
|
13137
|
-
* Mutate option object in order to add by property and give back the event name.
|
|
13138
|
-
* @private
|
|
13139
|
-
* @deprecated since 4.2.0
|
|
13140
|
-
* @param {Object} options to mutate
|
|
13141
|
-
* @param {Object} transform to inspect action from
|
|
13142
|
-
*/
|
|
13143
|
-
_addEventOptions: function(options, transform) {
|
|
13144
|
-
// we can probably add more details at low cost
|
|
13145
|
-
// scale change, rotation changes, translation changes
|
|
13146
|
-
var eventName, by;
|
|
13147
|
-
switch (transform.action) {
|
|
13148
|
-
case 'scaleX':
|
|
13149
|
-
eventName = 'scaled';
|
|
13150
|
-
by = 'x';
|
|
13151
|
-
break;
|
|
13152
|
-
case 'scaleY':
|
|
13153
|
-
eventName = 'scaled';
|
|
13154
|
-
by = 'y';
|
|
13155
|
-
break;
|
|
13156
|
-
case 'skewX':
|
|
13157
|
-
eventName = 'skewed';
|
|
13158
|
-
by = 'x';
|
|
13159
|
-
break;
|
|
13160
|
-
case 'skewY':
|
|
13161
|
-
eventName = 'skewed';
|
|
13162
|
-
by = 'y';
|
|
13163
|
-
break;
|
|
13164
|
-
case 'scale':
|
|
13165
|
-
eventName = 'scaled';
|
|
13166
|
-
by = 'equally';
|
|
13167
|
-
break;
|
|
13168
|
-
case 'rotate':
|
|
13169
|
-
eventName = 'rotated';
|
|
13170
|
-
break;
|
|
13171
|
-
case 'drag':
|
|
13172
|
-
eventName = 'moved';
|
|
13173
|
-
break;
|
|
13174
|
-
}
|
|
13175
|
-
options.by = by;
|
|
13176
|
-
return eventName;
|
|
13177
|
-
},
|
|
13178
|
-
|
|
13179
13424
|
/**
|
|
13180
13425
|
* @private
|
|
13181
13426
|
* @param {Event} e Event object fired on mousedown
|
|
@@ -14615,6 +14860,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
14615
14860
|
/**
|
|
14616
14861
|
* When `false`, the stoke width will scale with the object.
|
|
14617
14862
|
* When `true`, the stroke will always match the exact pixel size entered for stroke width.
|
|
14863
|
+
* this Property does not work on Text classes or drawing call that uses strokeText,fillText methods
|
|
14618
14864
|
* default to false
|
|
14619
14865
|
* @since 2.6.0
|
|
14620
14866
|
* @type Boolean
|
|
@@ -15265,26 +15511,26 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
15265
15511
|
/**
|
|
15266
15512
|
* Execute the drawing operation for an object clipPath
|
|
15267
15513
|
* @param {CanvasRenderingContext2D} ctx Context to render on
|
|
15514
|
+
* @param {fabric.Object} clipPath
|
|
15268
15515
|
*/
|
|
15269
|
-
drawClipPathOnCache: function(ctx) {
|
|
15270
|
-
var path = this.clipPath;
|
|
15516
|
+
drawClipPathOnCache: function(ctx, clipPath) {
|
|
15271
15517
|
ctx.save();
|
|
15272
15518
|
// DEBUG: uncomment this line, comment the following
|
|
15273
15519
|
// ctx.globalAlpha = 0.4
|
|
15274
|
-
if (
|
|
15520
|
+
if (clipPath.inverted) {
|
|
15275
15521
|
ctx.globalCompositeOperation = 'destination-out';
|
|
15276
15522
|
}
|
|
15277
15523
|
else {
|
|
15278
15524
|
ctx.globalCompositeOperation = 'destination-in';
|
|
15279
15525
|
}
|
|
15280
15526
|
//ctx.scale(1 / 2, 1 / 2);
|
|
15281
|
-
if (
|
|
15527
|
+
if (clipPath.absolutePositioned) {
|
|
15282
15528
|
var m = fabric.util.invertTransform(this.calcTransformMatrix());
|
|
15283
15529
|
ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
|
15284
15530
|
}
|
|
15285
|
-
|
|
15286
|
-
ctx.scale(1 /
|
|
15287
|
-
ctx.drawImage(
|
|
15531
|
+
clipPath.transform(ctx);
|
|
15532
|
+
ctx.scale(1 / clipPath.zoomX, 1 / clipPath.zoomY);
|
|
15533
|
+
ctx.drawImage(clipPath._cacheCanvas, -clipPath.cacheTranslationX, -clipPath.cacheTranslationY);
|
|
15288
15534
|
ctx.restore();
|
|
15289
15535
|
},
|
|
15290
15536
|
|
|
@@ -15303,22 +15549,26 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
15303
15549
|
this._renderBackground(ctx);
|
|
15304
15550
|
}
|
|
15305
15551
|
this._render(ctx);
|
|
15306
|
-
this._drawClipPath(ctx);
|
|
15552
|
+
this._drawClipPath(ctx, this.clipPath);
|
|
15307
15553
|
this.fill = originalFill;
|
|
15308
15554
|
this.stroke = originalStroke;
|
|
15309
15555
|
},
|
|
15310
15556
|
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
15557
|
+
/**
|
|
15558
|
+
* Prepare clipPath state and cache and draw it on instance's cache
|
|
15559
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
15560
|
+
* @param {fabric.Object} clipPath
|
|
15561
|
+
*/
|
|
15562
|
+
_drawClipPath: function (ctx, clipPath) {
|
|
15563
|
+
if (!clipPath) { return; }
|
|
15314
15564
|
// needed to setup a couple of variables
|
|
15315
15565
|
// path canvas gets overridden with this one.
|
|
15316
15566
|
// TODO find a better solution?
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15321
|
-
this.drawClipPathOnCache(ctx);
|
|
15567
|
+
clipPath.canvas = this.canvas;
|
|
15568
|
+
clipPath.shouldCache();
|
|
15569
|
+
clipPath._transformDone = true;
|
|
15570
|
+
clipPath.renderCache({ forClipping: true });
|
|
15571
|
+
this.drawClipPathOnCache(ctx, clipPath);
|
|
15322
15572
|
},
|
|
15323
15573
|
|
|
15324
15574
|
/**
|
|
@@ -15462,6 +15712,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
15462
15712
|
|
|
15463
15713
|
/**
|
|
15464
15714
|
* Renders controls and borders for the object
|
|
15715
|
+
* the context here is not transformed
|
|
15465
15716
|
* @param {CanvasRenderingContext2D} ctx Context to render on
|
|
15466
15717
|
* @param {Object} [styleOverride] properties to override the object style
|
|
15467
15718
|
*/
|
|
@@ -15480,7 +15731,10 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
15480
15731
|
if (!this.group) {
|
|
15481
15732
|
ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
|
|
15482
15733
|
}
|
|
15483
|
-
|
|
15734
|
+
if (this.flipX) {
|
|
15735
|
+
options.angle -= 180;
|
|
15736
|
+
}
|
|
15737
|
+
ctx.rotate(degreesToRadians(this.group ? options.angle : this.angle));
|
|
15484
15738
|
if (styleOverride.forActiveSelection || this.group) {
|
|
15485
15739
|
drawBorders && this.drawBordersInGroup(ctx, options, styleOverride);
|
|
15486
15740
|
}
|
|
@@ -16016,6 +16270,16 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16016
16270
|
if (this.globalCompositeOperation) {
|
|
16017
16271
|
ctx.globalCompositeOperation = this.globalCompositeOperation;
|
|
16018
16272
|
}
|
|
16273
|
+
},
|
|
16274
|
+
|
|
16275
|
+
/**
|
|
16276
|
+
* cancel instance's running animations
|
|
16277
|
+
* override if necessary to dispose artifacts such as `clipPath`
|
|
16278
|
+
*/
|
|
16279
|
+
dispose: function () {
|
|
16280
|
+
if (fabric.runningAnimations) {
|
|
16281
|
+
fabric.runningAnimations.cancelByTarget(this);
|
|
16282
|
+
}
|
|
16019
16283
|
}
|
|
16020
16284
|
});
|
|
16021
16285
|
|
|
@@ -16033,6 +16297,15 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16033
16297
|
*/
|
|
16034
16298
|
fabric.Object.NUM_FRACTION_DIGITS = 2;
|
|
16035
16299
|
|
|
16300
|
+
/**
|
|
16301
|
+
* Defines which properties should be enlivened from the object passed to {@link fabric.Object._fromObject}
|
|
16302
|
+
* @static
|
|
16303
|
+
* @memberOf fabric.Object
|
|
16304
|
+
* @constant
|
|
16305
|
+
* @type string[]
|
|
16306
|
+
*/
|
|
16307
|
+
fabric.Object.ENLIVEN_PROPS = ['clipPath'];
|
|
16308
|
+
|
|
16036
16309
|
fabric.Object._fromObject = function(className, object, callback, extraParam) {
|
|
16037
16310
|
var klass = fabric[className];
|
|
16038
16311
|
object = clone(object, true);
|
|
@@ -16043,8 +16316,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16043
16316
|
if (typeof patterns[1] !== 'undefined') {
|
|
16044
16317
|
object.stroke = patterns[1];
|
|
16045
16318
|
}
|
|
16046
|
-
fabric.util.
|
|
16047
|
-
object.clipPath = enlivedProps[0];
|
|
16319
|
+
fabric.util.enlivenObjectEnlivables(object, object, function () {
|
|
16048
16320
|
var instance = extraParam ? new klass(object[extraParam], object) : new klass(object);
|
|
16049
16321
|
callback && callback(instance);
|
|
16050
16322
|
});
|
|
@@ -16365,7 +16637,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16365
16637
|
/**
|
|
16366
16638
|
* Describe object's corner position in canvas element coordinates.
|
|
16367
16639
|
* includes padding. Used of object detection.
|
|
16368
|
-
* set and refreshed with setCoords
|
|
16640
|
+
* set and refreshed with setCoords.
|
|
16369
16641
|
* @memberOf fabric.Object.prototype
|
|
16370
16642
|
*/
|
|
16371
16643
|
lineCoords: null,
|
|
@@ -16749,21 +17021,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16749
17021
|
return this.scale(value / this.height / boundingRectFactor);
|
|
16750
17022
|
},
|
|
16751
17023
|
|
|
16752
|
-
/**
|
|
16753
|
-
* Calculates and returns the .coords of an object.
|
|
16754
|
-
* unused by the library, only for the end dev.
|
|
16755
|
-
* @return {Object} Object with tl, tr, br, bl ....
|
|
16756
|
-
* @chainable
|
|
16757
|
-
* @deprecated
|
|
16758
|
-
*/
|
|
16759
|
-
calcCoords: function(absolute) {
|
|
16760
|
-
// this is a compatibility function to avoid removing calcCoords now.
|
|
16761
|
-
if (absolute) {
|
|
16762
|
-
return this.calcACoords();
|
|
16763
|
-
}
|
|
16764
|
-
return this.calcOCoords();
|
|
16765
|
-
},
|
|
16766
|
-
|
|
16767
17024
|
calcLineCoords: function() {
|
|
16768
17025
|
var vpt = this.getViewportTransform(),
|
|
16769
17026
|
padding = this.padding, angle = degreesToRadians(this.angle),
|
|
@@ -16838,7 +17095,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16838
17095
|
* oCoords are used to find the corners
|
|
16839
17096
|
* aCoords are used to quickly find an object on the canvas
|
|
16840
17097
|
* lineCoords are used to quickly find object during pointer events.
|
|
16841
|
-
* See {@link https://github.com/
|
|
17098
|
+
* See {@link https://github.com/fabricjs/fabric.js/wiki/When-to-call-setCoords} and {@link http://fabricjs.com/fabric-gotchas}
|
|
17099
|
+
*
|
|
16842
17100
|
* @param {Boolean} [skipCorners] skip calculation of oCoords.
|
|
16843
17101
|
* @return {fabric.Object} thisArg
|
|
16844
17102
|
* @chainable
|
|
@@ -16935,23 +17193,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16935
17193
|
return cache.value;
|
|
16936
17194
|
},
|
|
16937
17195
|
|
|
16938
|
-
/*
|
|
16939
|
-
* Calculate object dimensions from its properties
|
|
16940
|
-
* @private
|
|
16941
|
-
* @deprecated since 3.4.0, please use fabric.util._calcDimensionsTransformMatrix
|
|
16942
|
-
* not including or including flipX, flipY to emulate the flipping boolean
|
|
16943
|
-
* @return {Object} .x width dimension
|
|
16944
|
-
* @return {Object} .y height dimension
|
|
16945
|
-
*/
|
|
16946
|
-
_calcDimensionsTransformMatrix: function(skewX, skewY, flipping) {
|
|
16947
|
-
return util.calcDimensionsMatrix({
|
|
16948
|
-
skewX: skewX,
|
|
16949
|
-
skewY: skewY,
|
|
16950
|
-
scaleX: this.scaleX * (flipping && this.flipX ? -1 : 1),
|
|
16951
|
-
scaleY: this.scaleY * (flipping && this.flipY ? -1 : 1)
|
|
16952
|
-
});
|
|
16953
|
-
},
|
|
16954
|
-
|
|
16955
17196
|
/*
|
|
16956
17197
|
* Calculate object dimensions from its properties
|
|
16957
17198
|
* @private
|
|
@@ -17816,8 +18057,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17816
18057
|
* @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
|
|
17817
18058
|
* @param {Function} [callbacks.onComplete] Invoked on completion
|
|
17818
18059
|
* @param {Function} [callbacks.onChange] Invoked on every step of animation
|
|
17819
|
-
* @return {fabric.
|
|
17820
|
-
* @chainable
|
|
18060
|
+
* @return {fabric.AnimationContext} context
|
|
17821
18061
|
*/
|
|
17822
18062
|
fxCenterObjectH: function (object, callbacks) {
|
|
17823
18063
|
callbacks = callbacks || { };
|
|
@@ -17827,7 +18067,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17827
18067
|
onChange = callbacks.onChange || empty,
|
|
17828
18068
|
_this = this;
|
|
17829
18069
|
|
|
17830
|
-
fabric.util.animate({
|
|
18070
|
+
return fabric.util.animate({
|
|
18071
|
+
target: this,
|
|
17831
18072
|
startValue: object.left,
|
|
17832
18073
|
endValue: this.getCenter().left,
|
|
17833
18074
|
duration: this.FX_DURATION,
|
|
@@ -17841,8 +18082,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17841
18082
|
onComplete();
|
|
17842
18083
|
}
|
|
17843
18084
|
});
|
|
17844
|
-
|
|
17845
|
-
return this;
|
|
17846
18085
|
},
|
|
17847
18086
|
|
|
17848
18087
|
/**
|
|
@@ -17851,8 +18090,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17851
18090
|
* @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
|
|
17852
18091
|
* @param {Function} [callbacks.onComplete] Invoked on completion
|
|
17853
18092
|
* @param {Function} [callbacks.onChange] Invoked on every step of animation
|
|
17854
|
-
* @return {fabric.
|
|
17855
|
-
* @chainable
|
|
18093
|
+
* @return {fabric.AnimationContext} context
|
|
17856
18094
|
*/
|
|
17857
18095
|
fxCenterObjectV: function (object, callbacks) {
|
|
17858
18096
|
callbacks = callbacks || { };
|
|
@@ -17862,7 +18100,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17862
18100
|
onChange = callbacks.onChange || empty,
|
|
17863
18101
|
_this = this;
|
|
17864
18102
|
|
|
17865
|
-
fabric.util.animate({
|
|
18103
|
+
return fabric.util.animate({
|
|
18104
|
+
target: this,
|
|
17866
18105
|
startValue: object.top,
|
|
17867
18106
|
endValue: this.getCenter().top,
|
|
17868
18107
|
duration: this.FX_DURATION,
|
|
@@ -17876,8 +18115,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17876
18115
|
onComplete();
|
|
17877
18116
|
}
|
|
17878
18117
|
});
|
|
17879
|
-
|
|
17880
|
-
return this;
|
|
17881
18118
|
},
|
|
17882
18119
|
|
|
17883
18120
|
/**
|
|
@@ -17886,8 +18123,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17886
18123
|
* @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
|
|
17887
18124
|
* @param {Function} [callbacks.onComplete] Invoked on completion
|
|
17888
18125
|
* @param {Function} [callbacks.onChange] Invoked on every step of animation
|
|
17889
|
-
* @return {fabric.
|
|
17890
|
-
* @chainable
|
|
18126
|
+
* @return {fabric.AnimationContext} context
|
|
17891
18127
|
*/
|
|
17892
18128
|
fxRemove: function (object, callbacks) {
|
|
17893
18129
|
callbacks = callbacks || { };
|
|
@@ -17897,7 +18133,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17897
18133
|
onChange = callbacks.onChange || empty,
|
|
17898
18134
|
_this = this;
|
|
17899
18135
|
|
|
17900
|
-
fabric.util.animate({
|
|
18136
|
+
return fabric.util.animate({
|
|
18137
|
+
target: this,
|
|
17901
18138
|
startValue: object.opacity,
|
|
17902
18139
|
endValue: 0,
|
|
17903
18140
|
duration: this.FX_DURATION,
|
|
@@ -17911,8 +18148,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17911
18148
|
onComplete();
|
|
17912
18149
|
}
|
|
17913
18150
|
});
|
|
17914
|
-
|
|
17915
|
-
return this;
|
|
17916
18151
|
}
|
|
17917
18152
|
});
|
|
17918
18153
|
|
|
@@ -17923,7 +18158,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
17923
18158
|
* @param {Number|Object} value Value to animate property to (if string was given first) or options object
|
|
17924
18159
|
* @return {fabric.Object} thisArg
|
|
17925
18160
|
* @tutorial {@link http://fabricjs.com/fabric-intro-part-2#animation}
|
|
17926
|
-
* @
|
|
18161
|
+
* @return {fabric.AnimationContext | fabric.AnimationContext[]} animation context (or an array if passed multiple properties)
|
|
17927
18162
|
*
|
|
17928
18163
|
* As object — multiple properties
|
|
17929
18164
|
*
|
|
@@ -17936,22 +18171,22 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
17936
18171
|
* object.animate('left', { duration: ... });
|
|
17937
18172
|
*
|
|
17938
18173
|
*/
|
|
17939
|
-
animate: function() {
|
|
18174
|
+
animate: function () {
|
|
17940
18175
|
if (arguments[0] && typeof arguments[0] === 'object') {
|
|
17941
|
-
var propsToAnimate = [], prop, skipCallbacks;
|
|
18176
|
+
var propsToAnimate = [], prop, skipCallbacks, out = [];
|
|
17942
18177
|
for (prop in arguments[0]) {
|
|
17943
18178
|
propsToAnimate.push(prop);
|
|
17944
18179
|
}
|
|
17945
18180
|
for (var i = 0, len = propsToAnimate.length; i < len; i++) {
|
|
17946
18181
|
prop = propsToAnimate[i];
|
|
17947
18182
|
skipCallbacks = i !== len - 1;
|
|
17948
|
-
this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks);
|
|
18183
|
+
out.push(this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks));
|
|
17949
18184
|
}
|
|
18185
|
+
return out;
|
|
17950
18186
|
}
|
|
17951
18187
|
else {
|
|
17952
|
-
this._animate.apply(this, arguments);
|
|
18188
|
+
return this._animate.apply(this, arguments);
|
|
17953
18189
|
}
|
|
17954
|
-
return this;
|
|
17955
18190
|
},
|
|
17956
18191
|
|
|
17957
18192
|
/**
|
|
@@ -17999,6 +18234,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
17999
18234
|
}
|
|
18000
18235
|
|
|
18001
18236
|
var _options = {
|
|
18237
|
+
target: this,
|
|
18002
18238
|
startValue: options.from,
|
|
18003
18239
|
endValue: to,
|
|
18004
18240
|
byValue: options.by,
|
|
@@ -18370,7 +18606,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
18370
18606
|
'use strict';
|
|
18371
18607
|
|
|
18372
18608
|
var fabric = global.fabric || (global.fabric = { }),
|
|
18373
|
-
|
|
18609
|
+
degreesToRadians = fabric.util.degreesToRadians;
|
|
18374
18610
|
|
|
18375
18611
|
if (fabric.Circle) {
|
|
18376
18612
|
fabric.warn('fabric.Circle is already defined.');
|
|
@@ -18400,22 +18636,20 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
18400
18636
|
radius: 0,
|
|
18401
18637
|
|
|
18402
18638
|
/**
|
|
18403
|
-
*
|
|
18404
|
-
* deprecated type, this should be in degree, this was an oversight.
|
|
18639
|
+
* degrees of start of the circle.
|
|
18405
18640
|
* probably will change to degrees in next major version
|
|
18406
|
-
* @type Number
|
|
18641
|
+
* @type Number 0 - 359
|
|
18407
18642
|
* @default 0
|
|
18408
18643
|
*/
|
|
18409
18644
|
startAngle: 0,
|
|
18410
18645
|
|
|
18411
18646
|
/**
|
|
18412
18647
|
* End angle of the circle
|
|
18413
|
-
* deprecated type, this should be in degree, this was an oversight.
|
|
18414
18648
|
* probably will change to degrees in next major version
|
|
18415
|
-
* @type Number
|
|
18416
|
-
* @default
|
|
18649
|
+
* @type Number 1 - 360
|
|
18650
|
+
* @default 360
|
|
18417
18651
|
*/
|
|
18418
|
-
endAngle:
|
|
18652
|
+
endAngle: 360,
|
|
18419
18653
|
|
|
18420
18654
|
cacheProperties: fabric.Object.prototype.cacheProperties.concat('radius', 'startAngle', 'endAngle'),
|
|
18421
18655
|
|
|
@@ -18453,7 +18687,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
18453
18687
|
*/
|
|
18454
18688
|
_toSVG: function() {
|
|
18455
18689
|
var svgString, x = 0, y = 0,
|
|
18456
|
-
angle = (this.endAngle - this.startAngle) %
|
|
18690
|
+
angle = (this.endAngle - this.startAngle) % 360;
|
|
18457
18691
|
|
|
18458
18692
|
if (angle === 0) {
|
|
18459
18693
|
svgString = [
|
|
@@ -18464,14 +18698,17 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
18464
18698
|
];
|
|
18465
18699
|
}
|
|
18466
18700
|
else {
|
|
18467
|
-
var
|
|
18468
|
-
|
|
18469
|
-
|
|
18470
|
-
|
|
18471
|
-
|
|
18701
|
+
var start = degreesToRadians(this.startAngle),
|
|
18702
|
+
end = degreesToRadians(this.endAngle),
|
|
18703
|
+
radius = this.radius,
|
|
18704
|
+
startX = fabric.util.cos(start) * radius,
|
|
18705
|
+
startY = fabric.util.sin(start) * radius,
|
|
18706
|
+
endX = fabric.util.cos(end) * radius,
|
|
18707
|
+
endY = fabric.util.sin(end) * radius,
|
|
18708
|
+
largeFlag = angle > 180 ? '1' : '0';
|
|
18472
18709
|
svgString = [
|
|
18473
18710
|
'<path d="M ' + startX + ' ' + startY,
|
|
18474
|
-
' A ' +
|
|
18711
|
+
' A ' + radius + ' ' + radius,
|
|
18475
18712
|
' 0 ', +largeFlag + ' 1', ' ' + endX + ' ' + endY,
|
|
18476
18713
|
'" ', 'COMMON_PARTS', ' />\n'
|
|
18477
18714
|
];
|
|
@@ -18490,8 +18727,10 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
18490
18727
|
0,
|
|
18491
18728
|
0,
|
|
18492
18729
|
this.radius,
|
|
18493
|
-
this.startAngle,
|
|
18494
|
-
this.endAngle,
|
|
18730
|
+
degreesToRadians(this.startAngle),
|
|
18731
|
+
degreesToRadians(this.endAngle),
|
|
18732
|
+
false
|
|
18733
|
+
);
|
|
18495
18734
|
this._renderPaintInOrder(ctx);
|
|
18496
18735
|
},
|
|
18497
18736
|
|
|
@@ -19049,7 +19288,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19049
19288
|
extend = fabric.util.object.extend,
|
|
19050
19289
|
min = fabric.util.array.min,
|
|
19051
19290
|
max = fabric.util.array.max,
|
|
19052
|
-
toFixed = fabric.util.toFixed
|
|
19291
|
+
toFixed = fabric.util.toFixed,
|
|
19292
|
+
projectStrokeOnPoints = fabric.util.projectStrokeOnPoints;
|
|
19053
19293
|
|
|
19054
19294
|
if (fabric.Polyline) {
|
|
19055
19295
|
fabric.warn('fabric.Polyline is already defined');
|
|
@@ -19078,6 +19318,17 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19078
19318
|
*/
|
|
19079
19319
|
points: null,
|
|
19080
19320
|
|
|
19321
|
+
/**
|
|
19322
|
+
* WARNING: Feature in progress
|
|
19323
|
+
* Calculate the exact bounding box taking in account strokeWidth on acute angles
|
|
19324
|
+
* this will be turned to true by default on fabric 6.0
|
|
19325
|
+
* maybe will be left in as an optimization since calculations may be slow
|
|
19326
|
+
* @deprecated
|
|
19327
|
+
* @type Boolean
|
|
19328
|
+
* @default false
|
|
19329
|
+
*/
|
|
19330
|
+
exactBoundingBox: false,
|
|
19331
|
+
|
|
19081
19332
|
cacheProperties: fabric.Object.prototype.cacheProperties.concat('points'),
|
|
19082
19333
|
|
|
19083
19334
|
/**
|
|
@@ -19106,13 +19357,25 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19106
19357
|
this._setPositionDimensions(options);
|
|
19107
19358
|
},
|
|
19108
19359
|
|
|
19360
|
+
/**
|
|
19361
|
+
* @private
|
|
19362
|
+
*/
|
|
19363
|
+
_projectStrokeOnPoints: function () {
|
|
19364
|
+
return projectStrokeOnPoints(this.points, this, true);
|
|
19365
|
+
},
|
|
19366
|
+
|
|
19109
19367
|
_setPositionDimensions: function(options) {
|
|
19110
|
-
var calcDim = this._calcDimensions(options), correctLeftTop
|
|
19111
|
-
|
|
19112
|
-
this.
|
|
19368
|
+
var calcDim = this._calcDimensions(options), correctLeftTop,
|
|
19369
|
+
correctSize = this.exactBoundingBox ? this.strokeWidth : 0;
|
|
19370
|
+
this.width = calcDim.width - correctSize;
|
|
19371
|
+
this.height = calcDim.height - correctSize;
|
|
19113
19372
|
if (!options.fromSVG) {
|
|
19114
19373
|
correctLeftTop = this.translateToGivenOrigin(
|
|
19115
|
-
{
|
|
19374
|
+
{
|
|
19375
|
+
// this looks bad, but is one way to keep it optional for now.
|
|
19376
|
+
x: calcDim.left - this.strokeWidth / 2 + correctSize / 2,
|
|
19377
|
+
y: calcDim.top - this.strokeWidth / 2 + correctSize / 2
|
|
19378
|
+
},
|
|
19116
19379
|
'left',
|
|
19117
19380
|
'top',
|
|
19118
19381
|
this.originX,
|
|
@@ -19126,8 +19389,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19126
19389
|
this.top = options.fromSVG ? calcDim.top : correctLeftTop.y;
|
|
19127
19390
|
}
|
|
19128
19391
|
this.pathOffset = {
|
|
19129
|
-
x: calcDim.left + this.width / 2,
|
|
19130
|
-
y: calcDim.top + this.height / 2
|
|
19392
|
+
x: calcDim.left + this.width / 2 + correctSize / 2,
|
|
19393
|
+
y: calcDim.top + this.height / 2 + correctSize / 2
|
|
19131
19394
|
};
|
|
19132
19395
|
},
|
|
19133
19396
|
|
|
@@ -19143,7 +19406,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19143
19406
|
*/
|
|
19144
19407
|
_calcDimensions: function() {
|
|
19145
19408
|
|
|
19146
|
-
var points = this.points,
|
|
19409
|
+
var points = this.exactBoundingBox ? this._projectStrokeOnPoints() : this.points,
|
|
19147
19410
|
minX = min(points, 'x') || 0,
|
|
19148
19411
|
minY = min(points, 'y') || 0,
|
|
19149
19412
|
maxX = max(points, 'x') || 0,
|
|
@@ -19155,7 +19418,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19155
19418
|
left: minX,
|
|
19156
19419
|
top: minY,
|
|
19157
19420
|
width: width,
|
|
19158
|
-
height: height
|
|
19421
|
+
height: height,
|
|
19159
19422
|
};
|
|
19160
19423
|
},
|
|
19161
19424
|
|
|
@@ -19291,7 +19554,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19291
19554
|
|
|
19292
19555
|
'use strict';
|
|
19293
19556
|
|
|
19294
|
-
var fabric = global.fabric || (global.fabric = {
|
|
19557
|
+
var fabric = global.fabric || (global.fabric = {}),
|
|
19558
|
+
projectStrokeOnPoints = fabric.util.projectStrokeOnPoints;
|
|
19295
19559
|
|
|
19296
19560
|
if (fabric.Polygon) {
|
|
19297
19561
|
fabric.warn('fabric.Polygon is already defined');
|
|
@@ -19313,6 +19577,13 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19313
19577
|
*/
|
|
19314
19578
|
type: 'polygon',
|
|
19315
19579
|
|
|
19580
|
+
/**
|
|
19581
|
+
* @private
|
|
19582
|
+
*/
|
|
19583
|
+
_projectStrokeOnPoints: function () {
|
|
19584
|
+
return projectStrokeOnPoints(this.points, this);
|
|
19585
|
+
},
|
|
19586
|
+
|
|
19316
19587
|
/**
|
|
19317
19588
|
* @private
|
|
19318
19589
|
* @param {CanvasRenderingContext2D} ctx Context to render on
|
|
@@ -19370,6 +19641,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19370
19641
|
min = fabric.util.array.min,
|
|
19371
19642
|
max = fabric.util.array.max,
|
|
19372
19643
|
extend = fabric.util.object.extend,
|
|
19644
|
+
clone = fabric.util.object.clone,
|
|
19373
19645
|
_toString = Object.prototype.toString,
|
|
19374
19646
|
toFixed = fabric.util.toFixed;
|
|
19375
19647
|
|
|
@@ -19411,23 +19683,26 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19411
19683
|
* @param {Object} [options] Options object
|
|
19412
19684
|
* @return {fabric.Path} thisArg
|
|
19413
19685
|
*/
|
|
19414
|
-
initialize: function(path, options) {
|
|
19415
|
-
options = options || {
|
|
19686
|
+
initialize: function (path, options) {
|
|
19687
|
+
options = clone(options || {});
|
|
19688
|
+
delete options.path;
|
|
19416
19689
|
this.callSuper('initialize', options);
|
|
19417
|
-
|
|
19418
|
-
|
|
19419
|
-
}
|
|
19690
|
+
this._setPath(path || [], options);
|
|
19691
|
+
},
|
|
19420
19692
|
|
|
19693
|
+
/**
|
|
19694
|
+
* @private
|
|
19695
|
+
* @param {Array|String} path Path data (sequence of coordinates and corresponding "command" tokens)
|
|
19696
|
+
* @param {Object} [options] Options object
|
|
19697
|
+
*/
|
|
19698
|
+
_setPath: function (path, options) {
|
|
19421
19699
|
var fromArray = _toString.call(path) === '[object Array]';
|
|
19422
19700
|
|
|
19423
19701
|
this.path = fabric.util.makePathSimpler(
|
|
19424
19702
|
fromArray ? path : fabric.util.parsePath(path)
|
|
19425
19703
|
);
|
|
19426
19704
|
|
|
19427
|
-
|
|
19428
|
-
return;
|
|
19429
|
-
}
|
|
19430
|
-
fabric.Polyline.prototype._setPositionDimensions.call(this, options);
|
|
19705
|
+
fabric.Polyline.prototype._setPositionDimensions.call(this, options || {});
|
|
19431
19706
|
},
|
|
19432
19707
|
|
|
19433
19708
|
/**
|
|
@@ -20084,7 +20359,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
20084
20359
|
for (var i = 0, len = this._objects.length; i < len; i++) {
|
|
20085
20360
|
this._objects[i].render(ctx);
|
|
20086
20361
|
}
|
|
20087
|
-
this._drawClipPath(ctx);
|
|
20362
|
+
this._drawClipPath(ctx, this.clipPath);
|
|
20088
20363
|
},
|
|
20089
20364
|
|
|
20090
20365
|
/**
|
|
@@ -20130,25 +20405,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
20130
20405
|
return this;
|
|
20131
20406
|
},
|
|
20132
20407
|
|
|
20133
|
-
/**
|
|
20134
|
-
* Realises the transform from this group onto the supplied object
|
|
20135
|
-
* i.e. it tells you what would happen if the supplied object was in
|
|
20136
|
-
* the group, and then the group was destroyed. It mutates the supplied
|
|
20137
|
-
* object.
|
|
20138
|
-
* Warning: this method is not useful anymore, it has been kept to no break the api.
|
|
20139
|
-
* is not used in the fabricJS codebase
|
|
20140
|
-
* this method will be reduced to using the utility.
|
|
20141
|
-
* @private
|
|
20142
|
-
* @deprecated
|
|
20143
|
-
* @param {fabric.Object} object
|
|
20144
|
-
* @param {Array} parentMatrix parent transformation
|
|
20145
|
-
* @return {fabric.Object} transformedObject
|
|
20146
|
-
*/
|
|
20147
|
-
realizeTransform: function(object, parentMatrix) {
|
|
20148
|
-
fabric.util.addTransformToObject(object, parentMatrix);
|
|
20149
|
-
return object;
|
|
20150
|
-
},
|
|
20151
|
-
|
|
20152
20408
|
/**
|
|
20153
20409
|
* Destroys a group (restoring state of its objects)
|
|
20154
20410
|
* @return {fabric.Group} thisArg
|
|
@@ -20163,6 +20419,14 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
20163
20419
|
return this._restoreObjectsState();
|
|
20164
20420
|
},
|
|
20165
20421
|
|
|
20422
|
+
dispose: function () {
|
|
20423
|
+
this.callSuper('dispose');
|
|
20424
|
+
this.forEachObject(function (object) {
|
|
20425
|
+
object.dispose && object.dispose();
|
|
20426
|
+
});
|
|
20427
|
+
this._objects = [];
|
|
20428
|
+
},
|
|
20429
|
+
|
|
20166
20430
|
/**
|
|
20167
20431
|
* make a group an active selection, remove the group from canvas
|
|
20168
20432
|
* the group has to be on canvas for this to work.
|
|
@@ -20326,11 +20590,10 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
20326
20590
|
});
|
|
20327
20591
|
return;
|
|
20328
20592
|
}
|
|
20329
|
-
fabric.util.enlivenObjects(objects, function(enlivenedObjects) {
|
|
20330
|
-
fabric.util.
|
|
20331
|
-
|
|
20332
|
-
|
|
20333
|
-
delete options.objects;
|
|
20593
|
+
fabric.util.enlivenObjects(objects, function (enlivenedObjects) {
|
|
20594
|
+
var options = fabric.util.object.clone(object, true);
|
|
20595
|
+
delete options.objects;
|
|
20596
|
+
fabric.util.enlivenObjectEnlivables(object, options, function () {
|
|
20334
20597
|
callback && callback(new fabric.Group(enlivenedObjects, options, true));
|
|
20335
20598
|
});
|
|
20336
20599
|
});
|
|
@@ -20700,7 +20963,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
20700
20963
|
/**
|
|
20701
20964
|
* Delete textures, reference to elements and eventually JSDOM cleanup
|
|
20702
20965
|
*/
|
|
20703
|
-
dispose: function() {
|
|
20966
|
+
dispose: function () {
|
|
20967
|
+
this.callSuper('dispose');
|
|
20704
20968
|
this.removeTexture(this.cacheKey);
|
|
20705
20969
|
this.removeTexture(this.cacheKey + '_filtered');
|
|
20706
20970
|
this._cacheContext = undefined;
|
|
@@ -21210,8 +21474,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
21210
21474
|
object.filters = filters || [];
|
|
21211
21475
|
fabric.Image.prototype._initFilters.call(object, [object.resizeFilter], function(resizeFilters) {
|
|
21212
21476
|
object.resizeFilter = resizeFilters[0];
|
|
21213
|
-
fabric.util.
|
|
21214
|
-
object.clipPath = enlivedProps[0];
|
|
21477
|
+
fabric.util.enlivenObjectEnlivables(object, object, function () {
|
|
21215
21478
|
var image = new fabric.Image(img, object);
|
|
21216
21479
|
callback(image, false);
|
|
21217
21480
|
});
|
|
@@ -21282,8 +21545,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
21282
21545
|
* @chainable
|
|
21283
21546
|
*/
|
|
21284
21547
|
straighten: function() {
|
|
21285
|
-
this.rotate(this._getAngleValueForStraighten());
|
|
21286
|
-
return this;
|
|
21548
|
+
return this.rotate(this._getAngleValueForStraighten());
|
|
21287
21549
|
},
|
|
21288
21550
|
|
|
21289
21551
|
/**
|
|
@@ -21292,7 +21554,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
21292
21554
|
* @param {Function} [callbacks.onComplete] Invoked on completion
|
|
21293
21555
|
* @param {Function} [callbacks.onChange] Invoked on every step of animation
|
|
21294
21556
|
* @return {fabric.Object} thisArg
|
|
21295
|
-
* @chainable
|
|
21296
21557
|
*/
|
|
21297
21558
|
fxStraighten: function(callbacks) {
|
|
21298
21559
|
callbacks = callbacks || { };
|
|
@@ -21302,7 +21563,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
21302
21563
|
onChange = callbacks.onChange || empty,
|
|
21303
21564
|
_this = this;
|
|
21304
21565
|
|
|
21305
|
-
fabric.util.animate({
|
|
21566
|
+
return fabric.util.animate({
|
|
21567
|
+
target: this,
|
|
21306
21568
|
startValue: this.get('angle'),
|
|
21307
21569
|
endValue: this._getAngleValueForStraighten(),
|
|
21308
21570
|
duration: this.FX_DURATION,
|
|
@@ -21315,8 +21577,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
21315
21577
|
onComplete();
|
|
21316
21578
|
},
|
|
21317
21579
|
});
|
|
21318
|
-
|
|
21319
|
-
return this;
|
|
21320
21580
|
}
|
|
21321
21581
|
});
|
|
21322
21582
|
|
|
@@ -21338,13 +21598,11 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
21338
21598
|
* Same as {@link fabric.Canvas.prototype.straightenObject}, but animated
|
|
21339
21599
|
* @param {fabric.Object} object Object to straighten
|
|
21340
21600
|
* @return {fabric.Canvas} thisArg
|
|
21341
|
-
* @chainable
|
|
21342
21601
|
*/
|
|
21343
21602
|
fxStraightenObject: function (object) {
|
|
21344
|
-
object.fxStraighten({
|
|
21603
|
+
return object.fxStraighten({
|
|
21345
21604
|
onChange: this.requestRenderAllBound
|
|
21346
21605
|
});
|
|
21347
|
-
return this;
|
|
21348
21606
|
}
|
|
21349
21607
|
});
|
|
21350
21608
|
|
|
@@ -22245,8 +22503,10 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
22245
22503
|
mainParameter: 'matrix',
|
|
22246
22504
|
|
|
22247
22505
|
/**
|
|
22248
|
-
* Lock the colormatrix on the color part, skipping alpha,
|
|
22506
|
+
* Lock the colormatrix on the color part, skipping alpha, mainly for non webgl scenario
|
|
22249
22507
|
* to save some calculation
|
|
22508
|
+
* @type Boolean
|
|
22509
|
+
* @default true
|
|
22250
22510
|
*/
|
|
22251
22511
|
colorsOnly: true,
|
|
22252
22512
|
|
|
@@ -23645,17 +23905,23 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
23645
23905
|
/**
|
|
23646
23906
|
* Color to make the blend operation with. default to a reddish color since black or white
|
|
23647
23907
|
* gives always strong result.
|
|
23908
|
+
* @type String
|
|
23909
|
+
* @default
|
|
23648
23910
|
**/
|
|
23649
23911
|
color: '#F95C63',
|
|
23650
23912
|
|
|
23651
23913
|
/**
|
|
23652
23914
|
* Blend mode for the filter: one of multiply, add, diff, screen, subtract,
|
|
23653
23915
|
* darken, lighten, overlay, exclusion, tint.
|
|
23916
|
+
* @type String
|
|
23917
|
+
* @default
|
|
23654
23918
|
**/
|
|
23655
23919
|
mode: 'multiply',
|
|
23656
23920
|
|
|
23657
23921
|
/**
|
|
23658
23922
|
* alpha value. represent the strength of the blend color operation.
|
|
23923
|
+
* @type Number
|
|
23924
|
+
* @default
|
|
23659
23925
|
**/
|
|
23660
23926
|
alpha: 1,
|
|
23661
23927
|
|
|
@@ -23896,8 +24162,9 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
23896
24162
|
image: null,
|
|
23897
24163
|
|
|
23898
24164
|
/**
|
|
23899
|
-
* Blend mode for the filter
|
|
23900
|
-
*
|
|
24165
|
+
* Blend mode for the filter (one of "multiply", "mask")
|
|
24166
|
+
* @type String
|
|
24167
|
+
* @default
|
|
23901
24168
|
**/
|
|
23902
24169
|
mode: 'multiply',
|
|
23903
24170
|
|
|
@@ -25033,6 +25300,8 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
25033
25300
|
* blur value, in percentage of image dimensions.
|
|
25034
25301
|
* specific to keep the image blur constant at different resolutions
|
|
25035
25302
|
* range between 0 and 1.
|
|
25303
|
+
* @type Number
|
|
25304
|
+
* @default
|
|
25036
25305
|
*/
|
|
25037
25306
|
blur: 0,
|
|
25038
25307
|
|
|
@@ -25511,7 +25780,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
25511
25780
|
var additionalProps =
|
|
25512
25781
|
('fontFamily fontWeight fontSize text underline overline linethrough' +
|
|
25513
25782
|
' textAlign fontStyle lineHeight textBackgroundColor charSpacing styles' +
|
|
25514
|
-
' direction path pathStartOffset pathSide').split(' ');
|
|
25783
|
+
' direction path pathStartOffset pathSide pathAlign').split(' ');
|
|
25515
25784
|
|
|
25516
25785
|
/**
|
|
25517
25786
|
* Text class
|
|
@@ -25540,7 +25809,8 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
25540
25809
|
'styles',
|
|
25541
25810
|
'path',
|
|
25542
25811
|
'pathStartOffset',
|
|
25543
|
-
'pathSide'
|
|
25812
|
+
'pathSide',
|
|
25813
|
+
'pathAlign'
|
|
25544
25814
|
],
|
|
25545
25815
|
|
|
25546
25816
|
/**
|
|
@@ -25737,6 +26007,16 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
25737
26007
|
*/
|
|
25738
26008
|
pathSide: 'left',
|
|
25739
26009
|
|
|
26010
|
+
/**
|
|
26011
|
+
* How text is aligned to the path. This property determines
|
|
26012
|
+
* the perpendicular position of each character relative to the path.
|
|
26013
|
+
* (one of "baseline", "center", "ascender", "descender")
|
|
26014
|
+
* This feature is in BETA, and its behavior may change
|
|
26015
|
+
* @type String
|
|
26016
|
+
* @default
|
|
26017
|
+
*/
|
|
26018
|
+
pathAlign: 'baseline',
|
|
26019
|
+
|
|
25740
26020
|
/**
|
|
25741
26021
|
* @private
|
|
25742
26022
|
*/
|
|
@@ -25880,6 +26160,8 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
25880
26160
|
/**
|
|
25881
26161
|
* Return a context for measurement of text string.
|
|
25882
26162
|
* if created it gets stored for reuse
|
|
26163
|
+
* this is for internal use, please do not use it
|
|
26164
|
+
* @private
|
|
25883
26165
|
* @param {String} text Text string
|
|
25884
26166
|
* @param {Object} [options] Options object
|
|
25885
26167
|
* @return {fabric.Text} thisArg
|
|
@@ -26051,7 +26333,20 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
26051
26333
|
* @param {String} [charStyle.fontStyle] Font style (italic|normal)
|
|
26052
26334
|
*/
|
|
26053
26335
|
_setTextStyles: function(ctx, charStyle, forMeasuring) {
|
|
26054
|
-
ctx.textBaseline = '
|
|
26336
|
+
ctx.textBaseline = 'alphabetical';
|
|
26337
|
+
if (this.path) {
|
|
26338
|
+
switch (this.pathAlign) {
|
|
26339
|
+
case 'center':
|
|
26340
|
+
ctx.textBaseline = 'middle';
|
|
26341
|
+
break;
|
|
26342
|
+
case 'ascender':
|
|
26343
|
+
ctx.textBaseline = 'top';
|
|
26344
|
+
break;
|
|
26345
|
+
case 'descender':
|
|
26346
|
+
ctx.textBaseline = 'bottom';
|
|
26347
|
+
break;
|
|
26348
|
+
}
|
|
26349
|
+
}
|
|
26055
26350
|
ctx.font = this._getFontDeclaration(charStyle, forMeasuring);
|
|
26056
26351
|
},
|
|
26057
26352
|
|
|
@@ -26516,16 +26811,17 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
26516
26811
|
path = this.path,
|
|
26517
26812
|
shortCut = !isJustify && this.charSpacing === 0 && this.isEmptyStyles(lineIndex) && !path,
|
|
26518
26813
|
isLtr = this.direction === 'ltr', sign = this.direction === 'ltr' ? 1 : -1,
|
|
26519
|
-
drawingLeft;
|
|
26520
|
-
|
|
26814
|
+
drawingLeft, currentDirection = ctx.canvas.getAttribute('dir');
|
|
26521
26815
|
ctx.save();
|
|
26816
|
+
if (currentDirection !== this.direction) {
|
|
26817
|
+
ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');
|
|
26818
|
+
ctx.direction = isLtr ? 'ltr' : 'rtl';
|
|
26819
|
+
ctx.textAlign = isLtr ? 'left' : 'right';
|
|
26820
|
+
}
|
|
26522
26821
|
top -= lineHeight * this._fontSizeFraction / this.lineHeight;
|
|
26523
26822
|
if (shortCut) {
|
|
26524
26823
|
// render all the line in one pass without checking
|
|
26525
26824
|
// drawingLeft = isLtr ? left : left - this.getLineWidth(lineIndex);
|
|
26526
|
-
ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');
|
|
26527
|
-
ctx.direction = isLtr ? 'ltr' : 'rtl';
|
|
26528
|
-
ctx.textAlign = isLtr ? 'left' : 'right';
|
|
26529
26825
|
this._renderChar(method, ctx, lineIndex, 0, line.join(''), left, top, lineHeight);
|
|
26530
26826
|
ctx.restore();
|
|
26531
26827
|
return;
|
|
@@ -26562,9 +26858,6 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
26562
26858
|
}
|
|
26563
26859
|
else {
|
|
26564
26860
|
drawingLeft = left;
|
|
26565
|
-
ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');
|
|
26566
|
-
ctx.direction = isLtr ? 'ltr' : 'rtl';
|
|
26567
|
-
ctx.textAlign = isLtr ? 'left' : 'right';
|
|
26568
26861
|
this._renderChar(method, ctx, lineIndex, i, charsToRender, drawingLeft, top, lineHeight);
|
|
26569
26862
|
}
|
|
26570
26863
|
charsToRender = '';
|
|
@@ -26815,19 +27108,12 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
26815
27108
|
* @return {Number} Line width
|
|
26816
27109
|
*/
|
|
26817
27110
|
getLineWidth: function(lineIndex) {
|
|
26818
|
-
if (this.__lineWidths[lineIndex]) {
|
|
27111
|
+
if (this.__lineWidths[lineIndex] !== undefined) {
|
|
26819
27112
|
return this.__lineWidths[lineIndex];
|
|
26820
27113
|
}
|
|
26821
27114
|
|
|
26822
|
-
var
|
|
26823
|
-
|
|
26824
|
-
if (line === '') {
|
|
26825
|
-
width = 0;
|
|
26826
|
-
}
|
|
26827
|
-
else {
|
|
26828
|
-
lineInfo = this.measureLine(lineIndex);
|
|
26829
|
-
width = lineInfo.width;
|
|
26830
|
-
}
|
|
27115
|
+
var lineInfo = this.measureLine(lineIndex);
|
|
27116
|
+
var width = lineInfo.width;
|
|
26831
27117
|
this.__lineWidths[lineIndex] = width;
|
|
26832
27118
|
return width;
|
|
26833
27119
|
},
|
|
@@ -28924,7 +29210,13 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
28924
29210
|
this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle);
|
|
28925
29211
|
}
|
|
28926
29212
|
else if (copiedStyle) {
|
|
28927
|
-
this
|
|
29213
|
+
// this test is required in order to close #6841
|
|
29214
|
+
// when a pasted buffer begins with a newline then
|
|
29215
|
+
// this.styles[cursorLoc.lineIndex + i] and copiedStyle[0]
|
|
29216
|
+
// may be undefined for some reason
|
|
29217
|
+
if (this.styles[cursorLoc.lineIndex + i] && copiedStyle[0]) {
|
|
29218
|
+
this.styles[cursorLoc.lineIndex + i][0] = copiedStyle[0];
|
|
29219
|
+
}
|
|
28928
29220
|
}
|
|
28929
29221
|
copiedStyle = copiedStyle && copiedStyle.slice(addedLines[i] + 1);
|
|
28930
29222
|
}
|