fabric 4.6.0 → 5.0.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 +42 -0
- package/HEADER.js +1 -1
- package/README.md +1 -6
- package/SECURITY.md +5 -0
- package/dist/fabric.js +652 -393
- package/dist/fabric.min.js +1 -1
- package/lib/event.js +7 -3
- package/package.json +87 -88
- 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/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 +45 -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 +15 -7
- package/src/util/animate.js +146 -22
- 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.0.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,117 @@ 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
|
+
* @property {Function} [options.onChange] Callback; invoked on every value change
|
|
3581
|
+
* @property {Function} [options.onComplete] Callback; invoked when value change is completed
|
|
3582
|
+
* @property {Number} [options.startValue=0] Starting value
|
|
3583
|
+
* @property {Number} [options.endValue=100] Ending value
|
|
3584
|
+
* @property {Number} [options.byValue=100] Value to modify the property by
|
|
3585
|
+
* @property {Function} [options.easing] Easing function
|
|
3586
|
+
* @property {Number} [options.duration=500] Duration of change (in ms)
|
|
3587
|
+
* @property {Function} [options.abort] Additional function with logic. If returns true, animation aborts.
|
|
3588
|
+
*
|
|
3589
|
+
* @typedef {() => void} CancelFunction
|
|
3590
|
+
*
|
|
3591
|
+
* @typedef {Object} AnimationCurrentState
|
|
3592
|
+
* @property {number} currentValue value in range [`startValue`, `endValue`]
|
|
3593
|
+
* @property {number} completionRate value in range [0, 1]
|
|
3594
|
+
* @property {number} durationRate value in range [0, 1]
|
|
3595
|
+
*
|
|
3596
|
+
* @typedef {(AnimationOptions & AnimationCurrentState & { cancel: CancelFunction }} AnimationContext
|
|
3597
|
+
*/
|
|
3598
|
+
|
|
3599
|
+
/**
|
|
3600
|
+
* Array holding all running animations
|
|
3601
|
+
* @memberof fabric
|
|
3602
|
+
* @type {AnimationContext[]}
|
|
3603
|
+
*/
|
|
3604
|
+
var RUNNING_ANIMATIONS = [];
|
|
3605
|
+
fabric.util.object.extend(RUNNING_ANIMATIONS, {
|
|
3606
|
+
|
|
3607
|
+
/**
|
|
3608
|
+
* cancel all running animations at the next requestAnimFrame
|
|
3609
|
+
* @returns {AnimationContext[]}
|
|
3610
|
+
*/
|
|
3611
|
+
cancelAll: function () {
|
|
3612
|
+
var animations = this.splice(0);
|
|
3613
|
+
animations.forEach(function (animation) {
|
|
3614
|
+
animation.cancel();
|
|
3615
|
+
});
|
|
3616
|
+
return animations;
|
|
3617
|
+
},
|
|
3618
|
+
|
|
3619
|
+
/**
|
|
3620
|
+
* cancel all running animations attached to canvas at the next requestAnimFrame
|
|
3621
|
+
* @param {fabric.Canvas} canvas
|
|
3622
|
+
* @returns {AnimationContext[]}
|
|
3623
|
+
*/
|
|
3624
|
+
cancelByCanvas: function (canvas) {
|
|
3625
|
+
if (!canvas) {
|
|
3626
|
+
return [];
|
|
3627
|
+
}
|
|
3628
|
+
var cancelled = this.filter(function (animation) {
|
|
3629
|
+
return typeof animation.target === 'object' && animation.target.canvas === canvas;
|
|
3630
|
+
});
|
|
3631
|
+
cancelled.forEach(function (animation) {
|
|
3632
|
+
animation.cancel();
|
|
3633
|
+
});
|
|
3634
|
+
return cancelled;
|
|
3635
|
+
},
|
|
3636
|
+
|
|
3637
|
+
/**
|
|
3638
|
+
* cancel all running animations for target at the next requestAnimFrame
|
|
3639
|
+
* @param {*} target
|
|
3640
|
+
* @returns {AnimationContext[]}
|
|
3641
|
+
*/
|
|
3642
|
+
cancelByTarget: function (target) {
|
|
3643
|
+
var cancelled = this.findAnimationsByTarget(target);
|
|
3644
|
+
cancelled.forEach(function (animation) {
|
|
3645
|
+
animation.cancel();
|
|
3646
|
+
});
|
|
3647
|
+
return cancelled;
|
|
3648
|
+
},
|
|
3649
|
+
|
|
3650
|
+
/**
|
|
3651
|
+
*
|
|
3652
|
+
* @param {CancelFunction} cancelFunc the function returned by animate
|
|
3653
|
+
* @returns {number}
|
|
3654
|
+
*/
|
|
3655
|
+
findAnimationIndex: function (cancelFunc) {
|
|
3656
|
+
return this.indexOf(this.findAnimation(cancelFunc));
|
|
3657
|
+
},
|
|
3658
|
+
|
|
3659
|
+
/**
|
|
3660
|
+
*
|
|
3661
|
+
* @param {CancelFunction} cancelFunc the function returned by animate
|
|
3662
|
+
* @returns {AnimationContext | undefined} animation's options object
|
|
3663
|
+
*/
|
|
3664
|
+
findAnimation: function (cancelFunc) {
|
|
3665
|
+
return this.find(function (animation) {
|
|
3666
|
+
return animation.cancel === cancelFunc;
|
|
3667
|
+
});
|
|
3668
|
+
},
|
|
3669
|
+
|
|
3670
|
+
/**
|
|
3671
|
+
*
|
|
3672
|
+
* @param {*} target the object that is assigned to the target property of the animation context
|
|
3673
|
+
* @returns {AnimationContext[]} array of animation options object associated with target
|
|
3674
|
+
*/
|
|
3675
|
+
findAnimationsByTarget: function (target) {
|
|
3676
|
+
if (!target) {
|
|
3677
|
+
return [];
|
|
3678
|
+
}
|
|
3679
|
+
return this.filter(function (animation) {
|
|
3680
|
+
return animation.target === target;
|
|
3681
|
+
});
|
|
3682
|
+
}
|
|
3683
|
+
});
|
|
3480
3684
|
|
|
3481
3685
|
function noop() {
|
|
3482
3686
|
return false;
|
|
@@ -3489,22 +3693,30 @@ fabric.warn = console.warn;
|
|
|
3489
3693
|
/**
|
|
3490
3694
|
* Changes value from one to another within certain period of time, invoking callbacks as value is being changed.
|
|
3491
3695
|
* @memberOf fabric.util
|
|
3492
|
-
* @param {
|
|
3493
|
-
* @
|
|
3494
|
-
* @param {Function} [options.onComplete] Callback; invoked when value change is completed
|
|
3495
|
-
* @param {Number} [options.startValue=0] Starting value
|
|
3496
|
-
* @param {Number} [options.endValue=100] Ending value
|
|
3497
|
-
* @param {Number} [options.byValue=100] Value to modify the property by
|
|
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
|
|
3696
|
+
* @param {AnimationOptions} [options] Animation options
|
|
3697
|
+
* @returns {CancelFunction} cancel function
|
|
3502
3698
|
*/
|
|
3503
3699
|
function animate(options) {
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3700
|
+
options || (options = {});
|
|
3701
|
+
var cancel = false,
|
|
3702
|
+
context,
|
|
3703
|
+
removeFromRegistry = function () {
|
|
3704
|
+
var index = fabric.runningAnimations.indexOf(context);
|
|
3705
|
+
return index > -1 && fabric.runningAnimations.splice(index, 1)[0];
|
|
3706
|
+
};
|
|
3707
|
+
|
|
3708
|
+
context = extend(clone(options), {
|
|
3709
|
+
cancel: function () {
|
|
3710
|
+
cancel = true;
|
|
3711
|
+
return removeFromRegistry();
|
|
3712
|
+
},
|
|
3713
|
+
currentValue: 'startValue' in options ? options.startValue : 0,
|
|
3714
|
+
completionRate: 0,
|
|
3715
|
+
durationRate: 0
|
|
3716
|
+
});
|
|
3717
|
+
fabric.runningAnimations.push(context);
|
|
3507
3718
|
|
|
3719
|
+
requestAnimFrame(function(timestamp) {
|
|
3508
3720
|
var start = timestamp || +new Date(),
|
|
3509
3721
|
duration = options.duration || 500,
|
|
3510
3722
|
finish = start + duration, time,
|
|
@@ -3519,25 +3731,31 @@ fabric.warn = console.warn;
|
|
|
3519
3731
|
options.onStart && options.onStart();
|
|
3520
3732
|
|
|
3521
3733
|
(function tick(ticktime) {
|
|
3522
|
-
// TODO: move abort call after calculation
|
|
3523
|
-
// and pass (current,valuePerc, timePerc) as arguments
|
|
3524
3734
|
time = ticktime || +new Date();
|
|
3525
3735
|
var currentTime = time > finish ? duration : (time - start),
|
|
3526
3736
|
timePerc = currentTime / duration,
|
|
3527
3737
|
current = easing(currentTime, startValue, byValue, duration),
|
|
3528
3738
|
valuePerc = Math.abs((current - startValue) / byValue);
|
|
3739
|
+
// update context
|
|
3740
|
+
context.currentValue = current;
|
|
3741
|
+
context.completionRate = valuePerc;
|
|
3742
|
+
context.durationRate = timePerc;
|
|
3529
3743
|
if (cancel) {
|
|
3530
3744
|
return;
|
|
3531
3745
|
}
|
|
3532
3746
|
if (abort(current, valuePerc, timePerc)) {
|
|
3533
|
-
|
|
3534
|
-
// does to even make sense to abort and run onComplete?
|
|
3535
|
-
onComplete(endValue, 1, 1);
|
|
3747
|
+
removeFromRegistry();
|
|
3536
3748
|
return;
|
|
3537
3749
|
}
|
|
3538
3750
|
if (time > finish) {
|
|
3751
|
+
// update context
|
|
3752
|
+
context.currentValue = endValue;
|
|
3753
|
+
context.completionRate = 1;
|
|
3754
|
+
context.durationRate = 1;
|
|
3755
|
+
// execute callbacks
|
|
3539
3756
|
onChange(endValue, 1, 1);
|
|
3540
3757
|
onComplete(endValue, 1, 1);
|
|
3758
|
+
removeFromRegistry();
|
|
3541
3759
|
return;
|
|
3542
3760
|
}
|
|
3543
3761
|
else {
|
|
@@ -3546,9 +3764,8 @@ fabric.warn = console.warn;
|
|
|
3546
3764
|
}
|
|
3547
3765
|
})(start);
|
|
3548
3766
|
});
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
};
|
|
3767
|
+
|
|
3768
|
+
return context.cancel;
|
|
3552
3769
|
}
|
|
3553
3770
|
|
|
3554
3771
|
var _requestAnimFrame = fabric.window.requestAnimationFrame ||
|
|
@@ -3580,6 +3797,7 @@ fabric.warn = console.warn;
|
|
|
3580
3797
|
fabric.util.animate = animate;
|
|
3581
3798
|
fabric.util.requestAnimFrame = requestAnimFrame;
|
|
3582
3799
|
fabric.util.cancelAnimFrame = cancelAnimFrame;
|
|
3800
|
+
fabric.runningAnimations = RUNNING_ANIMATIONS;
|
|
3583
3801
|
})();
|
|
3584
3802
|
|
|
3585
3803
|
|
|
@@ -5062,22 +5280,26 @@ fabric.warn = console.warn;
|
|
|
5062
5280
|
if (styleContents.trim() === '') {
|
|
5063
5281
|
continue;
|
|
5064
5282
|
}
|
|
5065
|
-
|
|
5066
|
-
rules =
|
|
5283
|
+
// recovers all the rule in this form `body { style code... }`
|
|
5284
|
+
// rules = styleContents.match(/[^{]*\{[\s\S]*?\}/g);
|
|
5285
|
+
rules = styleContents.split('}');
|
|
5286
|
+
// remove empty rules.
|
|
5287
|
+
rules = rules.filter(function(rule) { return rule.trim(); });
|
|
5288
|
+
// at this point we have hopefully an array of rules `body { style code... `
|
|
5067
5289
|
// eslint-disable-next-line no-loop-func
|
|
5068
5290
|
rules.forEach(function(rule) {
|
|
5069
5291
|
|
|
5070
|
-
var match = rule.
|
|
5071
|
-
ruleObj = { }, declaration = match[
|
|
5072
|
-
propertyValuePairs = declaration.
|
|
5292
|
+
var match = rule.split('{'),
|
|
5293
|
+
ruleObj = { }, declaration = match[1].trim(),
|
|
5294
|
+
propertyValuePairs = declaration.split(';').filter(function(pair) { return pair.trim(); });
|
|
5073
5295
|
|
|
5074
5296
|
for (i = 0, len = propertyValuePairs.length; i < len; i++) {
|
|
5075
|
-
var pair = propertyValuePairs[i].split(
|
|
5076
|
-
property = pair[0],
|
|
5077
|
-
value = pair[1];
|
|
5297
|
+
var pair = propertyValuePairs[i].split(':'),
|
|
5298
|
+
property = pair[0].trim(),
|
|
5299
|
+
value = pair[1].trim();
|
|
5078
5300
|
ruleObj[property] = value;
|
|
5079
5301
|
}
|
|
5080
|
-
rule = match[
|
|
5302
|
+
rule = match[0].trim();
|
|
5081
5303
|
rule.split(',').forEach(function(_rule) {
|
|
5082
5304
|
_rule = _rule.replace(/^svg/i, '').trim();
|
|
5083
5305
|
if (_rule === '') {
|
|
@@ -8652,8 +8874,12 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
8652
8874
|
imageSmoothingEnabled: true,
|
|
8653
8875
|
|
|
8654
8876
|
/**
|
|
8655
|
-
* The transformation (
|
|
8877
|
+
* The transformation (a Canvas 2D API transform matrix) which focuses the viewport
|
|
8656
8878
|
* @type Array
|
|
8879
|
+
* @example <caption>Default transform</caption>
|
|
8880
|
+
* canvas.viewportTransform = [1, 0, 0, 1, 0, 0];
|
|
8881
|
+
* @example <caption>Scale by 70% and translate toward bottom-right by 50, without skewing</caption>
|
|
8882
|
+
* canvas.viewportTransform = [0.7, 0, 0, 0.7, 50, 50];
|
|
8657
8883
|
* @default
|
|
8658
8884
|
*/
|
|
8659
8885
|
viewportTransform: fabric.iMatrix.concat(),
|
|
@@ -8747,7 +8973,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
8747
8973
|
* @private
|
|
8748
8974
|
*/
|
|
8749
8975
|
_isRetinaScaling: function() {
|
|
8750
|
-
return (fabric.devicePixelRatio
|
|
8976
|
+
return (fabric.devicePixelRatio > 1 && this.enableRetinaScaling);
|
|
8751
8977
|
},
|
|
8752
8978
|
|
|
8753
8979
|
/**
|
|
@@ -8755,7 +8981,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
8755
8981
|
* @return {Number} retinaScaling if applied, otherwise 1;
|
|
8756
8982
|
*/
|
|
8757
8983
|
getRetinaScaling: function() {
|
|
8758
|
-
return this._isRetinaScaling() ? fabric.devicePixelRatio : 1;
|
|
8984
|
+
return this._isRetinaScaling() ? Math.max(1, fabric.devicePixelRatio) : 1;
|
|
8759
8985
|
},
|
|
8760
8986
|
|
|
8761
8987
|
/**
|
|
@@ -9122,7 +9348,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
9122
9348
|
}
|
|
9123
9349
|
}
|
|
9124
9350
|
if (this._isCurrentlyDrawing) {
|
|
9125
|
-
this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles();
|
|
9351
|
+
this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles(this.contextTop);
|
|
9126
9352
|
}
|
|
9127
9353
|
this._initRetinaScaling();
|
|
9128
9354
|
this.calcOffset();
|
|
@@ -9189,8 +9415,8 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
9189
9415
|
},
|
|
9190
9416
|
|
|
9191
9417
|
/**
|
|
9192
|
-
* Sets viewport
|
|
9193
|
-
* @param {Array} vpt
|
|
9418
|
+
* Sets viewport transformation of this canvas instance
|
|
9419
|
+
* @param {Array} vpt a Canvas 2D API transform matrix
|
|
9194
9420
|
* @return {fabric.Canvas} instance
|
|
9195
9421
|
* @chainable true
|
|
9196
9422
|
*/
|
|
@@ -10277,6 +10503,10 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
10277
10503
|
}
|
|
10278
10504
|
this.forEachObject(function(object) {
|
|
10279
10505
|
object.dispose && object.dispose();
|
|
10506
|
+
// animation module is still optional
|
|
10507
|
+
if (fabric.runningAnimations) {
|
|
10508
|
+
fabric.runningAnimations.cancelByTarget(object);
|
|
10509
|
+
}
|
|
10280
10510
|
});
|
|
10281
10511
|
this._objects = [];
|
|
10282
10512
|
if (this.backgroundImage && this.backgroundImage.dispose) {
|
|
@@ -10291,7 +10521,7 @@ fabric.ElementsParser = function(elements, callback, options, reviver, parsingOp
|
|
|
10291
10521
|
this.contextContainer = null;
|
|
10292
10522
|
// restore canvas style
|
|
10293
10523
|
this.lowerCanvasEl.classList.remove('lower-canvas');
|
|
10294
|
-
this.lowerCanvasEl
|
|
10524
|
+
fabric.util.setStyle(this.lowerCanvasEl, this._originalCanvasStyle);
|
|
10295
10525
|
delete this._originalCanvasStyle;
|
|
10296
10526
|
// restore canvas size to original size in case retina scaling was applied
|
|
10297
10527
|
this.lowerCanvasEl.setAttribute('width', this.width);
|
|
@@ -10459,9 +10689,9 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10459
10689
|
/**
|
|
10460
10690
|
* Sets brush styles
|
|
10461
10691
|
* @private
|
|
10692
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
10462
10693
|
*/
|
|
10463
|
-
_setBrushStyles: function() {
|
|
10464
|
-
var ctx = this.canvas.contextTop;
|
|
10694
|
+
_setBrushStyles: function (ctx) {
|
|
10465
10695
|
ctx.strokeStyle = this.color;
|
|
10466
10696
|
ctx.lineWidth = this.width;
|
|
10467
10697
|
ctx.lineCap = this.strokeLineCap;
|
|
@@ -10546,6 +10776,22 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10546
10776
|
*/
|
|
10547
10777
|
decimate: 0.4,
|
|
10548
10778
|
|
|
10779
|
+
/**
|
|
10780
|
+
* Draws a straight line between last recorded point to current pointer
|
|
10781
|
+
* Used for `shift` functionality
|
|
10782
|
+
*
|
|
10783
|
+
* @type boolean
|
|
10784
|
+
* @default false
|
|
10785
|
+
*/
|
|
10786
|
+
drawStraightLine: false,
|
|
10787
|
+
|
|
10788
|
+
/**
|
|
10789
|
+
* The event modifier key that makes the brush draw a straight line.
|
|
10790
|
+
* If `null` or 'none' or any other string that is not a modifier key the feature is disabled.
|
|
10791
|
+
* @type {'altKey' | 'shiftKey' | 'ctrlKey' | 'none' | undefined | null}
|
|
10792
|
+
*/
|
|
10793
|
+
straightLineKey: 'shiftKey',
|
|
10794
|
+
|
|
10549
10795
|
/**
|
|
10550
10796
|
* Constructor
|
|
10551
10797
|
* @param {fabric.Canvas} canvas
|
|
@@ -10556,6 +10802,10 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10556
10802
|
this._points = [];
|
|
10557
10803
|
},
|
|
10558
10804
|
|
|
10805
|
+
needsFullRender: function () {
|
|
10806
|
+
return this.callSuper('needsFullRender') || this._hasStraightLine;
|
|
10807
|
+
},
|
|
10808
|
+
|
|
10559
10809
|
/**
|
|
10560
10810
|
* Invoked inside on mouse down and mouse move
|
|
10561
10811
|
* @param {Object} pointer
|
|
@@ -10574,6 +10824,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10574
10824
|
if (!this.canvas._isMainEvent(options.e)) {
|
|
10575
10825
|
return;
|
|
10576
10826
|
}
|
|
10827
|
+
this.drawStraightLine = options.e[this.straightLineKey];
|
|
10577
10828
|
this._prepareForDrawing(pointer);
|
|
10578
10829
|
// capture coordinates immediately
|
|
10579
10830
|
// this allows to draw dots (when movement never occurs)
|
|
@@ -10589,6 +10840,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10589
10840
|
if (!this.canvas._isMainEvent(options.e)) {
|
|
10590
10841
|
return;
|
|
10591
10842
|
}
|
|
10843
|
+
this.drawStraightLine = options.e[this.straightLineKey];
|
|
10592
10844
|
if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) {
|
|
10593
10845
|
return;
|
|
10594
10846
|
}
|
|
@@ -10621,6 +10873,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10621
10873
|
if (!this.canvas._isMainEvent(options.e)) {
|
|
10622
10874
|
return true;
|
|
10623
10875
|
}
|
|
10876
|
+
this.drawStraightLine = false;
|
|
10624
10877
|
this.oldEnd = undefined;
|
|
10625
10878
|
this._finalizeAndAddPath();
|
|
10626
10879
|
return false;
|
|
@@ -10647,6 +10900,10 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10647
10900
|
if (this._points.length > 1 && point.eq(this._points[this._points.length - 1])) {
|
|
10648
10901
|
return false;
|
|
10649
10902
|
}
|
|
10903
|
+
if (this.drawStraightLine && this._points.length > 1) {
|
|
10904
|
+
this._hasStraightLine = true;
|
|
10905
|
+
this._points.pop();
|
|
10906
|
+
}
|
|
10650
10907
|
this._points.push(point);
|
|
10651
10908
|
return true;
|
|
10652
10909
|
},
|
|
@@ -10657,8 +10914,9 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10657
10914
|
*/
|
|
10658
10915
|
_reset: function() {
|
|
10659
10916
|
this._points = [];
|
|
10660
|
-
this._setBrushStyles();
|
|
10917
|
+
this._setBrushStyles(this.canvas.contextTop);
|
|
10661
10918
|
this._setShadow();
|
|
10919
|
+
this._hasStraightLine = false;
|
|
10662
10920
|
},
|
|
10663
10921
|
|
|
10664
10922
|
/**
|
|
@@ -10673,12 +10931,13 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
|
|
|
10673
10931
|
/**
|
|
10674
10932
|
* Draw a smooth path on the topCanvas using quadraticCurveTo
|
|
10675
10933
|
* @private
|
|
10934
|
+
* @param {CanvasRenderingContext2D} [ctx]
|
|
10676
10935
|
*/
|
|
10677
|
-
_render: function() {
|
|
10678
|
-
var
|
|
10936
|
+
_render: function(ctx) {
|
|
10937
|
+
var i, len,
|
|
10679
10938
|
p1 = this._points[0],
|
|
10680
10939
|
p2 = this._points[1];
|
|
10681
|
-
|
|
10940
|
+
ctx = ctx || this.canvas.contextTop;
|
|
10682
10941
|
this._saveAndTransform(ctx);
|
|
10683
10942
|
ctx.beginPath();
|
|
10684
10943
|
//if we only have 2 points in the path and they are the same
|
|
@@ -11212,17 +11471,19 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
11212
11471
|
|
|
11213
11472
|
/**
|
|
11214
11473
|
* Creates "pattern" instance property
|
|
11474
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
11215
11475
|
*/
|
|
11216
|
-
getPattern: function() {
|
|
11217
|
-
return
|
|
11476
|
+
getPattern: function(ctx) {
|
|
11477
|
+
return ctx.createPattern(this.source || this.getPatternSrc(), 'repeat');
|
|
11218
11478
|
},
|
|
11219
11479
|
|
|
11220
11480
|
/**
|
|
11221
11481
|
* Sets brush styles
|
|
11482
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
11222
11483
|
*/
|
|
11223
|
-
_setBrushStyles: function() {
|
|
11224
|
-
this.callSuper('_setBrushStyles');
|
|
11225
|
-
|
|
11484
|
+
_setBrushStyles: function(ctx) {
|
|
11485
|
+
this.callSuper('_setBrushStyles', ctx);
|
|
11486
|
+
ctx.strokeStyle = this.getPattern(ctx);
|
|
11226
11487
|
},
|
|
11227
11488
|
|
|
11228
11489
|
/**
|
|
@@ -11281,15 +11542,11 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
11281
11542
|
* @fires dragover
|
|
11282
11543
|
* @fires dragenter
|
|
11283
11544
|
* @fires dragleave
|
|
11545
|
+
* @fires drop:before before drop event. same native event. This is added to handle edge cases
|
|
11284
11546
|
* @fires drop
|
|
11285
11547
|
* @fires after:render at the end of the render process, receives the context in the callback
|
|
11286
11548
|
* @fires before:render at start the render process, receives the context in the callback
|
|
11287
11549
|
*
|
|
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
11550
|
*/
|
|
11294
11551
|
fabric.Canvas = fabric.util.createClass(fabric.StaticCanvas, /** @lends fabric.Canvas.prototype */ {
|
|
11295
11552
|
|
|
@@ -11474,13 +11731,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
11474
11731
|
*/
|
|
11475
11732
|
freeDrawingCursor: 'crosshair',
|
|
11476
11733
|
|
|
11477
|
-
/**
|
|
11478
|
-
* Cursor value used for rotation point
|
|
11479
|
-
* @type String
|
|
11480
|
-
* @default
|
|
11481
|
-
*/
|
|
11482
|
-
rotationCursor: 'crosshair',
|
|
11483
|
-
|
|
11484
11734
|
/**
|
|
11485
11735
|
* Cursor value used for disabled elements ( corners with disabled action )
|
|
11486
11736
|
* @type String
|
|
@@ -11586,6 +11836,13 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
11586
11836
|
*/
|
|
11587
11837
|
targets: [],
|
|
11588
11838
|
|
|
11839
|
+
/**
|
|
11840
|
+
* When the option is enabled, PointerEvent is used instead of MouseEvent.
|
|
11841
|
+
* @type Boolean
|
|
11842
|
+
* @default
|
|
11843
|
+
*/
|
|
11844
|
+
enablePointerEvents: false,
|
|
11845
|
+
|
|
11589
11846
|
/**
|
|
11590
11847
|
* Keep track of the hovered target
|
|
11591
11848
|
* @type fabric.Object
|
|
@@ -11661,6 +11918,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
11661
11918
|
}
|
|
11662
11919
|
if (this.hasLostContext) {
|
|
11663
11920
|
this.renderTopLayer(this.contextTop);
|
|
11921
|
+
this.hasLostContext = false;
|
|
11664
11922
|
}
|
|
11665
11923
|
var canvasToDrawOn = this.contextContainer;
|
|
11666
11924
|
this.renderCanvas(canvasToDrawOn, this._chooseObjectsToRender());
|
|
@@ -12330,17 +12588,12 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
12330
12588
|
e: e,
|
|
12331
12589
|
selected: added,
|
|
12332
12590
|
deselected: removed,
|
|
12333
|
-
// added for backward compatibility
|
|
12334
|
-
// deprecated
|
|
12335
|
-
updated: added[0] || removed[0],
|
|
12336
|
-
target: this._activeObject,
|
|
12337
12591
|
});
|
|
12338
12592
|
}
|
|
12339
12593
|
else if (objects.length > 0) {
|
|
12340
12594
|
this.fire('selection:created', {
|
|
12341
12595
|
e: e,
|
|
12342
12596
|
selected: added,
|
|
12343
|
-
target: this._activeObject,
|
|
12344
12597
|
});
|
|
12345
12598
|
}
|
|
12346
12599
|
else if (oldObjects.length > 0) {
|
|
@@ -12664,7 +12917,7 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
12664
12917
|
this._onDragOver = this._onDragOver.bind(this);
|
|
12665
12918
|
this._onDragEnter = this._simpleEventHandler.bind(this, 'dragenter');
|
|
12666
12919
|
this._onDragLeave = this._simpleEventHandler.bind(this, 'dragleave');
|
|
12667
|
-
this._onDrop = this.
|
|
12920
|
+
this._onDrop = this._onDrop.bind(this);
|
|
12668
12921
|
this.eventsBound = true;
|
|
12669
12922
|
},
|
|
12670
12923
|
|
|
@@ -12776,6 +13029,18 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
12776
13029
|
this._fireEnterLeaveEvents(target, e);
|
|
12777
13030
|
},
|
|
12778
13031
|
|
|
13032
|
+
/**
|
|
13033
|
+
* `drop:before` is a an event that allow you to schedule logic
|
|
13034
|
+
* before the `drop` event. Prefer `drop` event always, but if you need
|
|
13035
|
+
* to run some drop-disabling logic on an event, since there is no way
|
|
13036
|
+
* to handle event handlers ordering, use `drop:before`
|
|
13037
|
+
* @param {Event} e
|
|
13038
|
+
*/
|
|
13039
|
+
_onDrop: function (e) {
|
|
13040
|
+
this._simpleEventHandler('drop:before', e);
|
|
13041
|
+
return this._simpleEventHandler('drop', e);
|
|
13042
|
+
},
|
|
13043
|
+
|
|
12779
13044
|
/**
|
|
12780
13045
|
* @private
|
|
12781
13046
|
* @param {Event} e Event object fired on mousedown
|
|
@@ -13008,25 +13273,34 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
13008
13273
|
);
|
|
13009
13274
|
}
|
|
13010
13275
|
}
|
|
13276
|
+
var corner, pointer;
|
|
13011
13277
|
if (target) {
|
|
13278
|
+
corner = target._findTargetCorner(
|
|
13279
|
+
this.getPointer(e, true),
|
|
13280
|
+
fabric.util.isTouchEvent(e)
|
|
13281
|
+
);
|
|
13012
13282
|
if (target.selectable && target !== this._activeObject && target.activeOn === 'up') {
|
|
13013
13283
|
this.setActiveObject(target, e);
|
|
13014
13284
|
shouldRender = true;
|
|
13015
13285
|
}
|
|
13016
13286
|
else {
|
|
13017
|
-
var corner = target._findTargetCorner(
|
|
13018
|
-
this.getPointer(e, true),
|
|
13019
|
-
fabric.util.isTouchEvent(e)
|
|
13020
|
-
);
|
|
13021
13287
|
var control = target.controls[corner],
|
|
13022
13288
|
mouseUpHandler = control && control.getMouseUpHandler(e, target, control);
|
|
13023
13289
|
if (mouseUpHandler) {
|
|
13024
|
-
|
|
13290
|
+
pointer = this.getPointer(e);
|
|
13025
13291
|
mouseUpHandler(e, transform, pointer.x, pointer.y);
|
|
13026
13292
|
}
|
|
13027
13293
|
}
|
|
13028
13294
|
target.isMoving = false;
|
|
13029
13295
|
}
|
|
13296
|
+
// if we are ending up a transform on a different control or a new object
|
|
13297
|
+
// fire the original mouse up from the corner that started the transform
|
|
13298
|
+
if (transform && (transform.target !== target || transform.corner !== corner)) {
|
|
13299
|
+
var originalControl = transform.target && transform.target.controls[transform.corner],
|
|
13300
|
+
originalMouseUpHandler = originalControl && originalControl.getMouseUpHandler(e, target, control);
|
|
13301
|
+
pointer = pointer || this.getPointer(e);
|
|
13302
|
+
originalMouseUpHandler && originalMouseUpHandler(e, transform, pointer.x, pointer.y);
|
|
13303
|
+
}
|
|
13030
13304
|
this._setCursorFromEvent(e, target);
|
|
13031
13305
|
this._handleEvent(e, 'up', LEFT_CLICK, isClick);
|
|
13032
13306
|
this._groupSelector = null;
|
|
@@ -13108,7 +13382,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
13108
13382
|
|
|
13109
13383
|
var transform = this._currentTransform,
|
|
13110
13384
|
target = transform.target,
|
|
13111
|
-
eventName,
|
|
13112
13385
|
options = {
|
|
13113
13386
|
e: e,
|
|
13114
13387
|
target: target,
|
|
@@ -13123,59 +13396,10 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
|
|
|
13123
13396
|
target.setCoords();
|
|
13124
13397
|
|
|
13125
13398
|
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
13399
|
this._fire('modified', options);
|
|
13133
13400
|
}
|
|
13134
13401
|
},
|
|
13135
13402
|
|
|
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
13403
|
/**
|
|
13180
13404
|
* @private
|
|
13181
13405
|
* @param {Event} e Event object fired on mousedown
|
|
@@ -14615,6 +14839,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
14615
14839
|
/**
|
|
14616
14840
|
* When `false`, the stoke width will scale with the object.
|
|
14617
14841
|
* When `true`, the stroke will always match the exact pixel size entered for stroke width.
|
|
14842
|
+
* this Property does not work on Text classes or drawing call that uses strokeText,fillText methods
|
|
14618
14843
|
* default to false
|
|
14619
14844
|
* @since 2.6.0
|
|
14620
14845
|
* @type Boolean
|
|
@@ -15265,26 +15490,26 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
15265
15490
|
/**
|
|
15266
15491
|
* Execute the drawing operation for an object clipPath
|
|
15267
15492
|
* @param {CanvasRenderingContext2D} ctx Context to render on
|
|
15493
|
+
* @param {fabric.Object} clipPath
|
|
15268
15494
|
*/
|
|
15269
|
-
drawClipPathOnCache: function(ctx) {
|
|
15270
|
-
var path = this.clipPath;
|
|
15495
|
+
drawClipPathOnCache: function(ctx, clipPath) {
|
|
15271
15496
|
ctx.save();
|
|
15272
15497
|
// DEBUG: uncomment this line, comment the following
|
|
15273
15498
|
// ctx.globalAlpha = 0.4
|
|
15274
|
-
if (
|
|
15499
|
+
if (clipPath.inverted) {
|
|
15275
15500
|
ctx.globalCompositeOperation = 'destination-out';
|
|
15276
15501
|
}
|
|
15277
15502
|
else {
|
|
15278
15503
|
ctx.globalCompositeOperation = 'destination-in';
|
|
15279
15504
|
}
|
|
15280
15505
|
//ctx.scale(1 / 2, 1 / 2);
|
|
15281
|
-
if (
|
|
15506
|
+
if (clipPath.absolutePositioned) {
|
|
15282
15507
|
var m = fabric.util.invertTransform(this.calcTransformMatrix());
|
|
15283
15508
|
ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
|
15284
15509
|
}
|
|
15285
|
-
|
|
15286
|
-
ctx.scale(1 /
|
|
15287
|
-
ctx.drawImage(
|
|
15510
|
+
clipPath.transform(ctx);
|
|
15511
|
+
ctx.scale(1 / clipPath.zoomX, 1 / clipPath.zoomY);
|
|
15512
|
+
ctx.drawImage(clipPath._cacheCanvas, -clipPath.cacheTranslationX, -clipPath.cacheTranslationY);
|
|
15288
15513
|
ctx.restore();
|
|
15289
15514
|
},
|
|
15290
15515
|
|
|
@@ -15303,22 +15528,26 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
15303
15528
|
this._renderBackground(ctx);
|
|
15304
15529
|
}
|
|
15305
15530
|
this._render(ctx);
|
|
15306
|
-
this._drawClipPath(ctx);
|
|
15531
|
+
this._drawClipPath(ctx, this.clipPath);
|
|
15307
15532
|
this.fill = originalFill;
|
|
15308
15533
|
this.stroke = originalStroke;
|
|
15309
15534
|
},
|
|
15310
15535
|
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
15536
|
+
/**
|
|
15537
|
+
* Prepare clipPath state and cache and draw it on instance's cache
|
|
15538
|
+
* @param {CanvasRenderingContext2D} ctx
|
|
15539
|
+
* @param {fabric.Object} clipPath
|
|
15540
|
+
*/
|
|
15541
|
+
_drawClipPath: function (ctx, clipPath) {
|
|
15542
|
+
if (!clipPath) { return; }
|
|
15314
15543
|
// needed to setup a couple of variables
|
|
15315
15544
|
// path canvas gets overridden with this one.
|
|
15316
15545
|
// TODO find a better solution?
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15321
|
-
this.drawClipPathOnCache(ctx);
|
|
15546
|
+
clipPath.canvas = this.canvas;
|
|
15547
|
+
clipPath.shouldCache();
|
|
15548
|
+
clipPath._transformDone = true;
|
|
15549
|
+
clipPath.renderCache({ forClipping: true });
|
|
15550
|
+
this.drawClipPathOnCache(ctx, clipPath);
|
|
15322
15551
|
},
|
|
15323
15552
|
|
|
15324
15553
|
/**
|
|
@@ -15462,6 +15691,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
15462
15691
|
|
|
15463
15692
|
/**
|
|
15464
15693
|
* Renders controls and borders for the object
|
|
15694
|
+
* the context here is not transformed
|
|
15465
15695
|
* @param {CanvasRenderingContext2D} ctx Context to render on
|
|
15466
15696
|
* @param {Object} [styleOverride] properties to override the object style
|
|
15467
15697
|
*/
|
|
@@ -15480,7 +15710,10 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
15480
15710
|
if (!this.group) {
|
|
15481
15711
|
ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
|
|
15482
15712
|
}
|
|
15483
|
-
|
|
15713
|
+
if (this.flipX) {
|
|
15714
|
+
options.angle -= 180;
|
|
15715
|
+
}
|
|
15716
|
+
ctx.rotate(degreesToRadians(this.group ? options.angle : this.angle));
|
|
15484
15717
|
if (styleOverride.forActiveSelection || this.group) {
|
|
15485
15718
|
drawBorders && this.drawBordersInGroup(ctx, options, styleOverride);
|
|
15486
15719
|
}
|
|
@@ -16016,6 +16249,15 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16016
16249
|
if (this.globalCompositeOperation) {
|
|
16017
16250
|
ctx.globalCompositeOperation = this.globalCompositeOperation;
|
|
16018
16251
|
}
|
|
16252
|
+
},
|
|
16253
|
+
|
|
16254
|
+
/**
|
|
16255
|
+
* cancel instance's running animations
|
|
16256
|
+
*/
|
|
16257
|
+
dispose: function () {
|
|
16258
|
+
if (fabric.runningAnimations) {
|
|
16259
|
+
fabric.runningAnimations.cancelByTarget(this);
|
|
16260
|
+
}
|
|
16019
16261
|
}
|
|
16020
16262
|
});
|
|
16021
16263
|
|
|
@@ -16033,6 +16275,15 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16033
16275
|
*/
|
|
16034
16276
|
fabric.Object.NUM_FRACTION_DIGITS = 2;
|
|
16035
16277
|
|
|
16278
|
+
/**
|
|
16279
|
+
* Defines which properties should be enlivened from the object passed to {@link fabric.Object._fromObject}
|
|
16280
|
+
* @static
|
|
16281
|
+
* @memberOf fabric.Object
|
|
16282
|
+
* @constant
|
|
16283
|
+
* @type string[]
|
|
16284
|
+
*/
|
|
16285
|
+
fabric.Object.ENLIVEN_PROPS = ['clipPath'];
|
|
16286
|
+
|
|
16036
16287
|
fabric.Object._fromObject = function(className, object, callback, extraParam) {
|
|
16037
16288
|
var klass = fabric[className];
|
|
16038
16289
|
object = clone(object, true);
|
|
@@ -16043,8 +16294,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16043
16294
|
if (typeof patterns[1] !== 'undefined') {
|
|
16044
16295
|
object.stroke = patterns[1];
|
|
16045
16296
|
}
|
|
16046
|
-
fabric.util.
|
|
16047
|
-
object.clipPath = enlivedProps[0];
|
|
16297
|
+
fabric.util.enlivenObjectEnlivables(object, object, function () {
|
|
16048
16298
|
var instance = extraParam ? new klass(object[extraParam], object) : new klass(object);
|
|
16049
16299
|
callback && callback(instance);
|
|
16050
16300
|
});
|
|
@@ -16365,7 +16615,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16365
16615
|
/**
|
|
16366
16616
|
* Describe object's corner position in canvas element coordinates.
|
|
16367
16617
|
* includes padding. Used of object detection.
|
|
16368
|
-
* set and refreshed with setCoords
|
|
16618
|
+
* set and refreshed with setCoords.
|
|
16369
16619
|
* @memberOf fabric.Object.prototype
|
|
16370
16620
|
*/
|
|
16371
16621
|
lineCoords: null,
|
|
@@ -16749,21 +16999,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16749
16999
|
return this.scale(value / this.height / boundingRectFactor);
|
|
16750
17000
|
},
|
|
16751
17001
|
|
|
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
17002
|
calcLineCoords: function() {
|
|
16768
17003
|
var vpt = this.getViewportTransform(),
|
|
16769
17004
|
padding = this.padding, angle = degreesToRadians(this.angle),
|
|
@@ -16838,7 +17073,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16838
17073
|
* oCoords are used to find the corners
|
|
16839
17074
|
* aCoords are used to quickly find an object on the canvas
|
|
16840
17075
|
* lineCoords are used to quickly find object during pointer events.
|
|
16841
|
-
* See {@link https://github.com/
|
|
17076
|
+
* See {@link https://github.com/fabricjs/fabric.js/wiki/When-to-call-setCoords} and {@link http://fabricjs.com/fabric-gotchas}
|
|
17077
|
+
*
|
|
16842
17078
|
* @param {Boolean} [skipCorners] skip calculation of oCoords.
|
|
16843
17079
|
* @return {fabric.Object} thisArg
|
|
16844
17080
|
* @chainable
|
|
@@ -16935,23 +17171,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
16935
17171
|
return cache.value;
|
|
16936
17172
|
},
|
|
16937
17173
|
|
|
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
17174
|
/*
|
|
16956
17175
|
* Calculate object dimensions from its properties
|
|
16957
17176
|
* @private
|
|
@@ -17816,8 +18035,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17816
18035
|
* @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
|
|
17817
18036
|
* @param {Function} [callbacks.onComplete] Invoked on completion
|
|
17818
18037
|
* @param {Function} [callbacks.onChange] Invoked on every step of animation
|
|
17819
|
-
* @return {fabric.
|
|
17820
|
-
* @chainable
|
|
18038
|
+
* @return {fabric.AnimationContext} context
|
|
17821
18039
|
*/
|
|
17822
18040
|
fxCenterObjectH: function (object, callbacks) {
|
|
17823
18041
|
callbacks = callbacks || { };
|
|
@@ -17827,7 +18045,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17827
18045
|
onChange = callbacks.onChange || empty,
|
|
17828
18046
|
_this = this;
|
|
17829
18047
|
|
|
17830
|
-
fabric.util.animate({
|
|
18048
|
+
return fabric.util.animate({
|
|
18049
|
+
target: this,
|
|
17831
18050
|
startValue: object.left,
|
|
17832
18051
|
endValue: this.getCenter().left,
|
|
17833
18052
|
duration: this.FX_DURATION,
|
|
@@ -17841,8 +18060,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17841
18060
|
onComplete();
|
|
17842
18061
|
}
|
|
17843
18062
|
});
|
|
17844
|
-
|
|
17845
|
-
return this;
|
|
17846
18063
|
},
|
|
17847
18064
|
|
|
17848
18065
|
/**
|
|
@@ -17851,8 +18068,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17851
18068
|
* @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
|
|
17852
18069
|
* @param {Function} [callbacks.onComplete] Invoked on completion
|
|
17853
18070
|
* @param {Function} [callbacks.onChange] Invoked on every step of animation
|
|
17854
|
-
* @return {fabric.
|
|
17855
|
-
* @chainable
|
|
18071
|
+
* @return {fabric.AnimationContext} context
|
|
17856
18072
|
*/
|
|
17857
18073
|
fxCenterObjectV: function (object, callbacks) {
|
|
17858
18074
|
callbacks = callbacks || { };
|
|
@@ -17862,7 +18078,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17862
18078
|
onChange = callbacks.onChange || empty,
|
|
17863
18079
|
_this = this;
|
|
17864
18080
|
|
|
17865
|
-
fabric.util.animate({
|
|
18081
|
+
return fabric.util.animate({
|
|
18082
|
+
target: this,
|
|
17866
18083
|
startValue: object.top,
|
|
17867
18084
|
endValue: this.getCenter().top,
|
|
17868
18085
|
duration: this.FX_DURATION,
|
|
@@ -17876,8 +18093,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17876
18093
|
onComplete();
|
|
17877
18094
|
}
|
|
17878
18095
|
});
|
|
17879
|
-
|
|
17880
|
-
return this;
|
|
17881
18096
|
},
|
|
17882
18097
|
|
|
17883
18098
|
/**
|
|
@@ -17886,8 +18101,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17886
18101
|
* @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
|
|
17887
18102
|
* @param {Function} [callbacks.onComplete] Invoked on completion
|
|
17888
18103
|
* @param {Function} [callbacks.onChange] Invoked on every step of animation
|
|
17889
|
-
* @return {fabric.
|
|
17890
|
-
* @chainable
|
|
18104
|
+
* @return {fabric.AnimationContext} context
|
|
17891
18105
|
*/
|
|
17892
18106
|
fxRemove: function (object, callbacks) {
|
|
17893
18107
|
callbacks = callbacks || { };
|
|
@@ -17897,7 +18111,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17897
18111
|
onChange = callbacks.onChange || empty,
|
|
17898
18112
|
_this = this;
|
|
17899
18113
|
|
|
17900
|
-
fabric.util.animate({
|
|
18114
|
+
return fabric.util.animate({
|
|
18115
|
+
target: this,
|
|
17901
18116
|
startValue: object.opacity,
|
|
17902
18117
|
endValue: 0,
|
|
17903
18118
|
duration: this.FX_DURATION,
|
|
@@ -17911,8 +18126,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
17911
18126
|
onComplete();
|
|
17912
18127
|
}
|
|
17913
18128
|
});
|
|
17914
|
-
|
|
17915
|
-
return this;
|
|
17916
18129
|
}
|
|
17917
18130
|
});
|
|
17918
18131
|
|
|
@@ -17923,7 +18136,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
17923
18136
|
* @param {Number|Object} value Value to animate property to (if string was given first) or options object
|
|
17924
18137
|
* @return {fabric.Object} thisArg
|
|
17925
18138
|
* @tutorial {@link http://fabricjs.com/fabric-intro-part-2#animation}
|
|
17926
|
-
* @
|
|
18139
|
+
* @return {fabric.AnimationContext | fabric.AnimationContext[]} animation context (or an array if passed multiple properties)
|
|
17927
18140
|
*
|
|
17928
18141
|
* As object — multiple properties
|
|
17929
18142
|
*
|
|
@@ -17936,22 +18149,22 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
17936
18149
|
* object.animate('left', { duration: ... });
|
|
17937
18150
|
*
|
|
17938
18151
|
*/
|
|
17939
|
-
animate: function() {
|
|
18152
|
+
animate: function () {
|
|
17940
18153
|
if (arguments[0] && typeof arguments[0] === 'object') {
|
|
17941
|
-
var propsToAnimate = [], prop, skipCallbacks;
|
|
18154
|
+
var propsToAnimate = [], prop, skipCallbacks, out = [];
|
|
17942
18155
|
for (prop in arguments[0]) {
|
|
17943
18156
|
propsToAnimate.push(prop);
|
|
17944
18157
|
}
|
|
17945
18158
|
for (var i = 0, len = propsToAnimate.length; i < len; i++) {
|
|
17946
18159
|
prop = propsToAnimate[i];
|
|
17947
18160
|
skipCallbacks = i !== len - 1;
|
|
17948
|
-
this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks);
|
|
18161
|
+
out.push(this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks));
|
|
17949
18162
|
}
|
|
18163
|
+
return out;
|
|
17950
18164
|
}
|
|
17951
18165
|
else {
|
|
17952
|
-
this._animate.apply(this, arguments);
|
|
18166
|
+
return this._animate.apply(this, arguments);
|
|
17953
18167
|
}
|
|
17954
|
-
return this;
|
|
17955
18168
|
},
|
|
17956
18169
|
|
|
17957
18170
|
/**
|
|
@@ -17999,6 +18212,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
17999
18212
|
}
|
|
18000
18213
|
|
|
18001
18214
|
var _options = {
|
|
18215
|
+
target: this,
|
|
18002
18216
|
startValue: options.from,
|
|
18003
18217
|
endValue: to,
|
|
18004
18218
|
byValue: options.by,
|
|
@@ -18370,7 +18584,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
18370
18584
|
'use strict';
|
|
18371
18585
|
|
|
18372
18586
|
var fabric = global.fabric || (global.fabric = { }),
|
|
18373
|
-
|
|
18587
|
+
degreesToRadians = fabric.util.degreesToRadians;
|
|
18374
18588
|
|
|
18375
18589
|
if (fabric.Circle) {
|
|
18376
18590
|
fabric.warn('fabric.Circle is already defined.');
|
|
@@ -18400,22 +18614,20 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
18400
18614
|
radius: 0,
|
|
18401
18615
|
|
|
18402
18616
|
/**
|
|
18403
|
-
*
|
|
18404
|
-
* deprecated type, this should be in degree, this was an oversight.
|
|
18617
|
+
* degrees of start of the circle.
|
|
18405
18618
|
* probably will change to degrees in next major version
|
|
18406
|
-
* @type Number
|
|
18619
|
+
* @type Number 0 - 359
|
|
18407
18620
|
* @default 0
|
|
18408
18621
|
*/
|
|
18409
18622
|
startAngle: 0,
|
|
18410
18623
|
|
|
18411
18624
|
/**
|
|
18412
18625
|
* End angle of the circle
|
|
18413
|
-
* deprecated type, this should be in degree, this was an oversight.
|
|
18414
18626
|
* probably will change to degrees in next major version
|
|
18415
|
-
* @type Number
|
|
18416
|
-
* @default
|
|
18627
|
+
* @type Number 1 - 360
|
|
18628
|
+
* @default 360
|
|
18417
18629
|
*/
|
|
18418
|
-
endAngle:
|
|
18630
|
+
endAngle: 360,
|
|
18419
18631
|
|
|
18420
18632
|
cacheProperties: fabric.Object.prototype.cacheProperties.concat('radius', 'startAngle', 'endAngle'),
|
|
18421
18633
|
|
|
@@ -18453,7 +18665,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
18453
18665
|
*/
|
|
18454
18666
|
_toSVG: function() {
|
|
18455
18667
|
var svgString, x = 0, y = 0,
|
|
18456
|
-
angle = (this.endAngle - this.startAngle) %
|
|
18668
|
+
angle = (this.endAngle - this.startAngle) % 360;
|
|
18457
18669
|
|
|
18458
18670
|
if (angle === 0) {
|
|
18459
18671
|
svgString = [
|
|
@@ -18464,14 +18676,17 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
18464
18676
|
];
|
|
18465
18677
|
}
|
|
18466
18678
|
else {
|
|
18467
|
-
var
|
|
18468
|
-
|
|
18469
|
-
|
|
18470
|
-
|
|
18471
|
-
|
|
18679
|
+
var start = degreesToRadians(this.startAngle),
|
|
18680
|
+
end = degreesToRadians(this.endAngle),
|
|
18681
|
+
radius = this.radius,
|
|
18682
|
+
startX = fabric.util.cos(start) * radius,
|
|
18683
|
+
startY = fabric.util.sin(start) * radius,
|
|
18684
|
+
endX = fabric.util.cos(end) * radius,
|
|
18685
|
+
endY = fabric.util.sin(end) * radius,
|
|
18686
|
+
largeFlag = angle > 180 ? '1' : '0';
|
|
18472
18687
|
svgString = [
|
|
18473
18688
|
'<path d="M ' + startX + ' ' + startY,
|
|
18474
|
-
' A ' +
|
|
18689
|
+
' A ' + radius + ' ' + radius,
|
|
18475
18690
|
' 0 ', +largeFlag + ' 1', ' ' + endX + ' ' + endY,
|
|
18476
18691
|
'" ', 'COMMON_PARTS', ' />\n'
|
|
18477
18692
|
];
|
|
@@ -18490,8 +18705,10 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
18490
18705
|
0,
|
|
18491
18706
|
0,
|
|
18492
18707
|
this.radius,
|
|
18493
|
-
this.startAngle,
|
|
18494
|
-
this.endAngle,
|
|
18708
|
+
degreesToRadians(this.startAngle),
|
|
18709
|
+
degreesToRadians(this.endAngle),
|
|
18710
|
+
false
|
|
18711
|
+
);
|
|
18495
18712
|
this._renderPaintInOrder(ctx);
|
|
18496
18713
|
},
|
|
18497
18714
|
|
|
@@ -19049,7 +19266,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19049
19266
|
extend = fabric.util.object.extend,
|
|
19050
19267
|
min = fabric.util.array.min,
|
|
19051
19268
|
max = fabric.util.array.max,
|
|
19052
|
-
toFixed = fabric.util.toFixed
|
|
19269
|
+
toFixed = fabric.util.toFixed,
|
|
19270
|
+
projectStrokeOnPoints = fabric.util.projectStrokeOnPoints;
|
|
19053
19271
|
|
|
19054
19272
|
if (fabric.Polyline) {
|
|
19055
19273
|
fabric.warn('fabric.Polyline is already defined');
|
|
@@ -19078,6 +19296,17 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19078
19296
|
*/
|
|
19079
19297
|
points: null,
|
|
19080
19298
|
|
|
19299
|
+
/**
|
|
19300
|
+
* WARNING: Feature in progress
|
|
19301
|
+
* Calculate the exact bounding box taking in account strokeWidth on acute angles
|
|
19302
|
+
* this will be turned to true by default on fabric 6.0
|
|
19303
|
+
* maybe will be left in as an optimization since calculations may be slow
|
|
19304
|
+
* @deprecated
|
|
19305
|
+
* @type Boolean
|
|
19306
|
+
* @default false
|
|
19307
|
+
*/
|
|
19308
|
+
exactBoundingBox: false,
|
|
19309
|
+
|
|
19081
19310
|
cacheProperties: fabric.Object.prototype.cacheProperties.concat('points'),
|
|
19082
19311
|
|
|
19083
19312
|
/**
|
|
@@ -19106,13 +19335,25 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19106
19335
|
this._setPositionDimensions(options);
|
|
19107
19336
|
},
|
|
19108
19337
|
|
|
19338
|
+
/**
|
|
19339
|
+
* @private
|
|
19340
|
+
*/
|
|
19341
|
+
_projectStrokeOnPoints: function () {
|
|
19342
|
+
return projectStrokeOnPoints(this.points, this, true);
|
|
19343
|
+
},
|
|
19344
|
+
|
|
19109
19345
|
_setPositionDimensions: function(options) {
|
|
19110
|
-
var calcDim = this._calcDimensions(options), correctLeftTop
|
|
19111
|
-
|
|
19112
|
-
this.
|
|
19346
|
+
var calcDim = this._calcDimensions(options), correctLeftTop,
|
|
19347
|
+
correctSize = this.exactBoundingBox ? this.strokeWidth : 0;
|
|
19348
|
+
this.width = calcDim.width - correctSize;
|
|
19349
|
+
this.height = calcDim.height - correctSize;
|
|
19113
19350
|
if (!options.fromSVG) {
|
|
19114
19351
|
correctLeftTop = this.translateToGivenOrigin(
|
|
19115
|
-
{
|
|
19352
|
+
{
|
|
19353
|
+
// this looks bad, but is one way to keep it optional for now.
|
|
19354
|
+
x: calcDim.left - this.strokeWidth / 2 + correctSize / 2,
|
|
19355
|
+
y: calcDim.top - this.strokeWidth / 2 + correctSize / 2
|
|
19356
|
+
},
|
|
19116
19357
|
'left',
|
|
19117
19358
|
'top',
|
|
19118
19359
|
this.originX,
|
|
@@ -19126,8 +19367,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19126
19367
|
this.top = options.fromSVG ? calcDim.top : correctLeftTop.y;
|
|
19127
19368
|
}
|
|
19128
19369
|
this.pathOffset = {
|
|
19129
|
-
x: calcDim.left + this.width / 2,
|
|
19130
|
-
y: calcDim.top + this.height / 2
|
|
19370
|
+
x: calcDim.left + this.width / 2 + correctSize / 2,
|
|
19371
|
+
y: calcDim.top + this.height / 2 + correctSize / 2
|
|
19131
19372
|
};
|
|
19132
19373
|
},
|
|
19133
19374
|
|
|
@@ -19143,7 +19384,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19143
19384
|
*/
|
|
19144
19385
|
_calcDimensions: function() {
|
|
19145
19386
|
|
|
19146
|
-
var points = this.points,
|
|
19387
|
+
var points = this.exactBoundingBox ? this._projectStrokeOnPoints() : this.points,
|
|
19147
19388
|
minX = min(points, 'x') || 0,
|
|
19148
19389
|
minY = min(points, 'y') || 0,
|
|
19149
19390
|
maxX = max(points, 'x') || 0,
|
|
@@ -19155,7 +19396,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19155
19396
|
left: minX,
|
|
19156
19397
|
top: minY,
|
|
19157
19398
|
width: width,
|
|
19158
|
-
height: height
|
|
19399
|
+
height: height,
|
|
19159
19400
|
};
|
|
19160
19401
|
},
|
|
19161
19402
|
|
|
@@ -19291,7 +19532,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19291
19532
|
|
|
19292
19533
|
'use strict';
|
|
19293
19534
|
|
|
19294
|
-
var fabric = global.fabric || (global.fabric = {
|
|
19535
|
+
var fabric = global.fabric || (global.fabric = {}),
|
|
19536
|
+
projectStrokeOnPoints = fabric.util.projectStrokeOnPoints;
|
|
19295
19537
|
|
|
19296
19538
|
if (fabric.Polygon) {
|
|
19297
19539
|
fabric.warn('fabric.Polygon is already defined');
|
|
@@ -19313,6 +19555,13 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19313
19555
|
*/
|
|
19314
19556
|
type: 'polygon',
|
|
19315
19557
|
|
|
19558
|
+
/**
|
|
19559
|
+
* @private
|
|
19560
|
+
*/
|
|
19561
|
+
_projectStrokeOnPoints: function () {
|
|
19562
|
+
return projectStrokeOnPoints(this.points, this);
|
|
19563
|
+
},
|
|
19564
|
+
|
|
19316
19565
|
/**
|
|
19317
19566
|
* @private
|
|
19318
19567
|
* @param {CanvasRenderingContext2D} ctx Context to render on
|
|
@@ -19370,6 +19619,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19370
19619
|
min = fabric.util.array.min,
|
|
19371
19620
|
max = fabric.util.array.max,
|
|
19372
19621
|
extend = fabric.util.object.extend,
|
|
19622
|
+
clone = fabric.util.object.clone,
|
|
19373
19623
|
_toString = Object.prototype.toString,
|
|
19374
19624
|
toFixed = fabric.util.toFixed;
|
|
19375
19625
|
|
|
@@ -19411,23 +19661,26 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
19411
19661
|
* @param {Object} [options] Options object
|
|
19412
19662
|
* @return {fabric.Path} thisArg
|
|
19413
19663
|
*/
|
|
19414
|
-
initialize: function(path, options) {
|
|
19415
|
-
options = options || {
|
|
19664
|
+
initialize: function (path, options) {
|
|
19665
|
+
options = clone(options || {});
|
|
19666
|
+
delete options.path;
|
|
19416
19667
|
this.callSuper('initialize', options);
|
|
19417
|
-
|
|
19418
|
-
|
|
19419
|
-
}
|
|
19668
|
+
this._setPath(path || [], options);
|
|
19669
|
+
},
|
|
19420
19670
|
|
|
19671
|
+
/**
|
|
19672
|
+
* @private
|
|
19673
|
+
* @param {Array|String} path Path data (sequence of coordinates and corresponding "command" tokens)
|
|
19674
|
+
* @param {Object} [options] Options object
|
|
19675
|
+
*/
|
|
19676
|
+
_setPath: function (path, options) {
|
|
19421
19677
|
var fromArray = _toString.call(path) === '[object Array]';
|
|
19422
19678
|
|
|
19423
19679
|
this.path = fabric.util.makePathSimpler(
|
|
19424
19680
|
fromArray ? path : fabric.util.parsePath(path)
|
|
19425
19681
|
);
|
|
19426
19682
|
|
|
19427
|
-
|
|
19428
|
-
return;
|
|
19429
|
-
}
|
|
19430
|
-
fabric.Polyline.prototype._setPositionDimensions.call(this, options);
|
|
19683
|
+
fabric.Polyline.prototype._setPositionDimensions.call(this, options || {});
|
|
19431
19684
|
},
|
|
19432
19685
|
|
|
19433
19686
|
/**
|
|
@@ -20084,7 +20337,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
20084
20337
|
for (var i = 0, len = this._objects.length; i < len; i++) {
|
|
20085
20338
|
this._objects[i].render(ctx);
|
|
20086
20339
|
}
|
|
20087
|
-
this._drawClipPath(ctx);
|
|
20340
|
+
this._drawClipPath(ctx, this.clipPath);
|
|
20088
20341
|
},
|
|
20089
20342
|
|
|
20090
20343
|
/**
|
|
@@ -20130,25 +20383,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
20130
20383
|
return this;
|
|
20131
20384
|
},
|
|
20132
20385
|
|
|
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
20386
|
/**
|
|
20153
20387
|
* Destroys a group (restoring state of its objects)
|
|
20154
20388
|
* @return {fabric.Group} thisArg
|
|
@@ -20163,6 +20397,14 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
20163
20397
|
return this._restoreObjectsState();
|
|
20164
20398
|
},
|
|
20165
20399
|
|
|
20400
|
+
dispose: function () {
|
|
20401
|
+
this.callSuper('dispose');
|
|
20402
|
+
this.forEachObject(function (object) {
|
|
20403
|
+
object.dispose && object.dispose();
|
|
20404
|
+
});
|
|
20405
|
+
this._objects = [];
|
|
20406
|
+
},
|
|
20407
|
+
|
|
20166
20408
|
/**
|
|
20167
20409
|
* make a group an active selection, remove the group from canvas
|
|
20168
20410
|
* the group has to be on canvas for this to work.
|
|
@@ -20326,11 +20568,10 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
20326
20568
|
});
|
|
20327
20569
|
return;
|
|
20328
20570
|
}
|
|
20329
|
-
fabric.util.enlivenObjects(objects, function(enlivenedObjects) {
|
|
20330
|
-
fabric.util.
|
|
20331
|
-
|
|
20332
|
-
|
|
20333
|
-
delete options.objects;
|
|
20571
|
+
fabric.util.enlivenObjects(objects, function (enlivenedObjects) {
|
|
20572
|
+
var options = fabric.util.object.clone(object, true);
|
|
20573
|
+
delete options.objects;
|
|
20574
|
+
fabric.util.enlivenObjectEnlivables(object, options, function () {
|
|
20334
20575
|
callback && callback(new fabric.Group(enlivenedObjects, options, true));
|
|
20335
20576
|
});
|
|
20336
20577
|
});
|
|
@@ -20700,7 +20941,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
20700
20941
|
/**
|
|
20701
20942
|
* Delete textures, reference to elements and eventually JSDOM cleanup
|
|
20702
20943
|
*/
|
|
20703
|
-
dispose: function() {
|
|
20944
|
+
dispose: function () {
|
|
20945
|
+
this.callSuper('dispose');
|
|
20704
20946
|
this.removeTexture(this.cacheKey);
|
|
20705
20947
|
this.removeTexture(this.cacheKey + '_filtered');
|
|
20706
20948
|
this._cacheContext = undefined;
|
|
@@ -21210,8 +21452,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
21210
21452
|
object.filters = filters || [];
|
|
21211
21453
|
fabric.Image.prototype._initFilters.call(object, [object.resizeFilter], function(resizeFilters) {
|
|
21212
21454
|
object.resizeFilter = resizeFilters[0];
|
|
21213
|
-
fabric.util.
|
|
21214
|
-
object.clipPath = enlivedProps[0];
|
|
21455
|
+
fabric.util.enlivenObjectEnlivables(object, object, function () {
|
|
21215
21456
|
var image = new fabric.Image(img, object);
|
|
21216
21457
|
callback(image, false);
|
|
21217
21458
|
});
|
|
@@ -21282,8 +21523,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
21282
21523
|
* @chainable
|
|
21283
21524
|
*/
|
|
21284
21525
|
straighten: function() {
|
|
21285
|
-
this.rotate(this._getAngleValueForStraighten());
|
|
21286
|
-
return this;
|
|
21526
|
+
return this.rotate(this._getAngleValueForStraighten());
|
|
21287
21527
|
},
|
|
21288
21528
|
|
|
21289
21529
|
/**
|
|
@@ -21292,7 +21532,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
21292
21532
|
* @param {Function} [callbacks.onComplete] Invoked on completion
|
|
21293
21533
|
* @param {Function} [callbacks.onChange] Invoked on every step of animation
|
|
21294
21534
|
* @return {fabric.Object} thisArg
|
|
21295
|
-
* @chainable
|
|
21296
21535
|
*/
|
|
21297
21536
|
fxStraighten: function(callbacks) {
|
|
21298
21537
|
callbacks = callbacks || { };
|
|
@@ -21302,7 +21541,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
21302
21541
|
onChange = callbacks.onChange || empty,
|
|
21303
21542
|
_this = this;
|
|
21304
21543
|
|
|
21305
|
-
fabric.util.animate({
|
|
21544
|
+
return fabric.util.animate({
|
|
21545
|
+
target: this,
|
|
21306
21546
|
startValue: this.get('angle'),
|
|
21307
21547
|
endValue: this._getAngleValueForStraighten(),
|
|
21308
21548
|
duration: this.FX_DURATION,
|
|
@@ -21315,8 +21555,6 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
|
|
|
21315
21555
|
onComplete();
|
|
21316
21556
|
},
|
|
21317
21557
|
});
|
|
21318
|
-
|
|
21319
|
-
return this;
|
|
21320
21558
|
}
|
|
21321
21559
|
});
|
|
21322
21560
|
|
|
@@ -21338,13 +21576,11 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|
|
21338
21576
|
* Same as {@link fabric.Canvas.prototype.straightenObject}, but animated
|
|
21339
21577
|
* @param {fabric.Object} object Object to straighten
|
|
21340
21578
|
* @return {fabric.Canvas} thisArg
|
|
21341
|
-
* @chainable
|
|
21342
21579
|
*/
|
|
21343
21580
|
fxStraightenObject: function (object) {
|
|
21344
|
-
object.fxStraighten({
|
|
21581
|
+
return object.fxStraighten({
|
|
21345
21582
|
onChange: this.requestRenderAllBound
|
|
21346
21583
|
});
|
|
21347
|
-
return this;
|
|
21348
21584
|
}
|
|
21349
21585
|
});
|
|
21350
21586
|
|
|
@@ -25511,7 +25747,7 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
25511
25747
|
var additionalProps =
|
|
25512
25748
|
('fontFamily fontWeight fontSize text underline overline linethrough' +
|
|
25513
25749
|
' textAlign fontStyle lineHeight textBackgroundColor charSpacing styles' +
|
|
25514
|
-
' direction path pathStartOffset pathSide').split(' ');
|
|
25750
|
+
' direction path pathStartOffset pathSide pathAlign').split(' ');
|
|
25515
25751
|
|
|
25516
25752
|
/**
|
|
25517
25753
|
* Text class
|
|
@@ -25540,7 +25776,8 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
25540
25776
|
'styles',
|
|
25541
25777
|
'path',
|
|
25542
25778
|
'pathStartOffset',
|
|
25543
|
-
'pathSide'
|
|
25779
|
+
'pathSide',
|
|
25780
|
+
'pathAlign'
|
|
25544
25781
|
],
|
|
25545
25782
|
|
|
25546
25783
|
/**
|
|
@@ -25737,6 +25974,16 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
25737
25974
|
*/
|
|
25738
25975
|
pathSide: 'left',
|
|
25739
25976
|
|
|
25977
|
+
/**
|
|
25978
|
+
* How text is aligned to the path. This property determines
|
|
25979
|
+
* the perpendicular position of each character relative to the path.
|
|
25980
|
+
* (one of "baseline", "center", "ascender", "descender")
|
|
25981
|
+
* This feature is in BETA, and its behavior may change
|
|
25982
|
+
* @type String
|
|
25983
|
+
* @default
|
|
25984
|
+
*/
|
|
25985
|
+
pathAlign: 'baseline',
|
|
25986
|
+
|
|
25740
25987
|
/**
|
|
25741
25988
|
* @private
|
|
25742
25989
|
*/
|
|
@@ -25880,6 +26127,8 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
25880
26127
|
/**
|
|
25881
26128
|
* Return a context for measurement of text string.
|
|
25882
26129
|
* if created it gets stored for reuse
|
|
26130
|
+
* this is for internal use, please do not use it
|
|
26131
|
+
* @private
|
|
25883
26132
|
* @param {String} text Text string
|
|
25884
26133
|
* @param {Object} [options] Options object
|
|
25885
26134
|
* @return {fabric.Text} thisArg
|
|
@@ -26051,7 +26300,20 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
26051
26300
|
* @param {String} [charStyle.fontStyle] Font style (italic|normal)
|
|
26052
26301
|
*/
|
|
26053
26302
|
_setTextStyles: function(ctx, charStyle, forMeasuring) {
|
|
26054
|
-
ctx.textBaseline = '
|
|
26303
|
+
ctx.textBaseline = 'alphabetical';
|
|
26304
|
+
if (this.path) {
|
|
26305
|
+
switch (this.pathAlign) {
|
|
26306
|
+
case 'center':
|
|
26307
|
+
ctx.textBaseline = 'middle';
|
|
26308
|
+
break;
|
|
26309
|
+
case 'ascender':
|
|
26310
|
+
ctx.textBaseline = 'top';
|
|
26311
|
+
break;
|
|
26312
|
+
case 'descender':
|
|
26313
|
+
ctx.textBaseline = 'bottom';
|
|
26314
|
+
break;
|
|
26315
|
+
}
|
|
26316
|
+
}
|
|
26055
26317
|
ctx.font = this._getFontDeclaration(charStyle, forMeasuring);
|
|
26056
26318
|
},
|
|
26057
26319
|
|
|
@@ -26516,16 +26778,17 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
26516
26778
|
path = this.path,
|
|
26517
26779
|
shortCut = !isJustify && this.charSpacing === 0 && this.isEmptyStyles(lineIndex) && !path,
|
|
26518
26780
|
isLtr = this.direction === 'ltr', sign = this.direction === 'ltr' ? 1 : -1,
|
|
26519
|
-
drawingLeft;
|
|
26520
|
-
|
|
26781
|
+
drawingLeft, currentDirection = ctx.canvas.getAttribute('dir');
|
|
26521
26782
|
ctx.save();
|
|
26783
|
+
if (currentDirection !== this.direction) {
|
|
26784
|
+
ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');
|
|
26785
|
+
ctx.direction = isLtr ? 'ltr' : 'rtl';
|
|
26786
|
+
ctx.textAlign = isLtr ? 'left' : 'right';
|
|
26787
|
+
}
|
|
26522
26788
|
top -= lineHeight * this._fontSizeFraction / this.lineHeight;
|
|
26523
26789
|
if (shortCut) {
|
|
26524
26790
|
// render all the line in one pass without checking
|
|
26525
26791
|
// 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
26792
|
this._renderChar(method, ctx, lineIndex, 0, line.join(''), left, top, lineHeight);
|
|
26530
26793
|
ctx.restore();
|
|
26531
26794
|
return;
|
|
@@ -26562,9 +26825,6 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
26562
26825
|
}
|
|
26563
26826
|
else {
|
|
26564
26827
|
drawingLeft = left;
|
|
26565
|
-
ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');
|
|
26566
|
-
ctx.direction = isLtr ? 'ltr' : 'rtl';
|
|
26567
|
-
ctx.textAlign = isLtr ? 'left' : 'right';
|
|
26568
26828
|
this._renderChar(method, ctx, lineIndex, i, charsToRender, drawingLeft, top, lineHeight);
|
|
26569
26829
|
}
|
|
26570
26830
|
charsToRender = '';
|
|
@@ -26815,19 +27075,12 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
26815
27075
|
* @return {Number} Line width
|
|
26816
27076
|
*/
|
|
26817
27077
|
getLineWidth: function(lineIndex) {
|
|
26818
|
-
if (this.__lineWidths[lineIndex]) {
|
|
27078
|
+
if (this.__lineWidths[lineIndex] !== undefined) {
|
|
26819
27079
|
return this.__lineWidths[lineIndex];
|
|
26820
27080
|
}
|
|
26821
27081
|
|
|
26822
|
-
var
|
|
26823
|
-
|
|
26824
|
-
if (line === '') {
|
|
26825
|
-
width = 0;
|
|
26826
|
-
}
|
|
26827
|
-
else {
|
|
26828
|
-
lineInfo = this.measureLine(lineIndex);
|
|
26829
|
-
width = lineInfo.width;
|
|
26830
|
-
}
|
|
27082
|
+
var lineInfo = this.measureLine(lineIndex);
|
|
27083
|
+
var width = lineInfo.width;
|
|
26831
27084
|
this.__lineWidths[lineIndex] = width;
|
|
26832
27085
|
return width;
|
|
26833
27086
|
},
|
|
@@ -28924,7 +29177,13 @@ fabric.Image.filters.BaseFilter.fromObject = function(object, callback) {
|
|
|
28924
29177
|
this.insertCharStyleObject(cursorLoc.lineIndex + i, 0, addedLines[i], copiedStyle);
|
|
28925
29178
|
}
|
|
28926
29179
|
else if (copiedStyle) {
|
|
28927
|
-
this
|
|
29180
|
+
// this test is required in order to close #6841
|
|
29181
|
+
// when a pasted buffer begins with a newline then
|
|
29182
|
+
// this.styles[cursorLoc.lineIndex + i] and copiedStyle[0]
|
|
29183
|
+
// may be undefined for some reason
|
|
29184
|
+
if (this.styles[cursorLoc.lineIndex + i] && copiedStyle[0]) {
|
|
29185
|
+
this.styles[cursorLoc.lineIndex + i][0] = copiedStyle[0];
|
|
29186
|
+
}
|
|
28928
29187
|
}
|
|
28929
29188
|
copiedStyle = copiedStyle && copiedStyle.slice(addedLines[i] + 1);
|
|
28930
29189
|
}
|