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/src/shapes/text.class.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
var additionalProps =
|
|
14
14
|
('fontFamily fontWeight fontSize text underline overline linethrough' +
|
|
15
15
|
' textAlign fontStyle lineHeight textBackgroundColor charSpacing styles' +
|
|
16
|
-
' direction path pathStartOffset pathSide').split(' ');
|
|
16
|
+
' direction path pathStartOffset pathSide pathAlign').split(' ');
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Text class
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
'styles',
|
|
43
43
|
'path',
|
|
44
44
|
'pathStartOffset',
|
|
45
|
-
'pathSide'
|
|
45
|
+
'pathSide',
|
|
46
|
+
'pathAlign'
|
|
46
47
|
],
|
|
47
48
|
|
|
48
49
|
/**
|
|
@@ -239,6 +240,16 @@
|
|
|
239
240
|
*/
|
|
240
241
|
pathSide: 'left',
|
|
241
242
|
|
|
243
|
+
/**
|
|
244
|
+
* How text is aligned to the path. This property determines
|
|
245
|
+
* the perpendicular position of each character relative to the path.
|
|
246
|
+
* (one of "baseline", "center", "ascender", "descender")
|
|
247
|
+
* This feature is in BETA, and its behavior may change
|
|
248
|
+
* @type String
|
|
249
|
+
* @default
|
|
250
|
+
*/
|
|
251
|
+
pathAlign: 'baseline',
|
|
252
|
+
|
|
242
253
|
/**
|
|
243
254
|
* @private
|
|
244
255
|
*/
|
|
@@ -382,6 +393,8 @@
|
|
|
382
393
|
/**
|
|
383
394
|
* Return a context for measurement of text string.
|
|
384
395
|
* if created it gets stored for reuse
|
|
396
|
+
* this is for internal use, please do not use it
|
|
397
|
+
* @private
|
|
385
398
|
* @param {String} text Text string
|
|
386
399
|
* @param {Object} [options] Options object
|
|
387
400
|
* @return {fabric.Text} thisArg
|
|
@@ -553,7 +566,20 @@
|
|
|
553
566
|
* @param {String} [charStyle.fontStyle] Font style (italic|normal)
|
|
554
567
|
*/
|
|
555
568
|
_setTextStyles: function(ctx, charStyle, forMeasuring) {
|
|
556
|
-
ctx.textBaseline = '
|
|
569
|
+
ctx.textBaseline = 'alphabetical';
|
|
570
|
+
if (this.path) {
|
|
571
|
+
switch (this.pathAlign) {
|
|
572
|
+
case 'center':
|
|
573
|
+
ctx.textBaseline = 'middle';
|
|
574
|
+
break;
|
|
575
|
+
case 'ascender':
|
|
576
|
+
ctx.textBaseline = 'top';
|
|
577
|
+
break;
|
|
578
|
+
case 'descender':
|
|
579
|
+
ctx.textBaseline = 'bottom';
|
|
580
|
+
break;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
557
583
|
ctx.font = this._getFontDeclaration(charStyle, forMeasuring);
|
|
558
584
|
},
|
|
559
585
|
|
|
@@ -1018,16 +1044,17 @@
|
|
|
1018
1044
|
path = this.path,
|
|
1019
1045
|
shortCut = !isJustify && this.charSpacing === 0 && this.isEmptyStyles(lineIndex) && !path,
|
|
1020
1046
|
isLtr = this.direction === 'ltr', sign = this.direction === 'ltr' ? 1 : -1,
|
|
1021
|
-
drawingLeft;
|
|
1022
|
-
|
|
1047
|
+
drawingLeft, currentDirection = ctx.canvas.getAttribute('dir');
|
|
1023
1048
|
ctx.save();
|
|
1049
|
+
if (currentDirection !== this.direction) {
|
|
1050
|
+
ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');
|
|
1051
|
+
ctx.direction = isLtr ? 'ltr' : 'rtl';
|
|
1052
|
+
ctx.textAlign = isLtr ? 'left' : 'right';
|
|
1053
|
+
}
|
|
1024
1054
|
top -= lineHeight * this._fontSizeFraction / this.lineHeight;
|
|
1025
1055
|
if (shortCut) {
|
|
1026
1056
|
// render all the line in one pass without checking
|
|
1027
1057
|
// drawingLeft = isLtr ? left : left - this.getLineWidth(lineIndex);
|
|
1028
|
-
ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');
|
|
1029
|
-
ctx.direction = isLtr ? 'ltr' : 'rtl';
|
|
1030
|
-
ctx.textAlign = isLtr ? 'left' : 'right';
|
|
1031
1058
|
this._renderChar(method, ctx, lineIndex, 0, line.join(''), left, top, lineHeight);
|
|
1032
1059
|
ctx.restore();
|
|
1033
1060
|
return;
|
|
@@ -1064,9 +1091,6 @@
|
|
|
1064
1091
|
}
|
|
1065
1092
|
else {
|
|
1066
1093
|
drawingLeft = left;
|
|
1067
|
-
ctx.canvas.setAttribute('dir', isLtr ? 'ltr' : 'rtl');
|
|
1068
|
-
ctx.direction = isLtr ? 'ltr' : 'rtl';
|
|
1069
|
-
ctx.textAlign = isLtr ? 'left' : 'right';
|
|
1070
1094
|
this._renderChar(method, ctx, lineIndex, i, charsToRender, drawingLeft, top, lineHeight);
|
|
1071
1095
|
}
|
|
1072
1096
|
charsToRender = '';
|
|
@@ -1317,19 +1341,12 @@
|
|
|
1317
1341
|
* @return {Number} Line width
|
|
1318
1342
|
*/
|
|
1319
1343
|
getLineWidth: function(lineIndex) {
|
|
1320
|
-
if (this.__lineWidths[lineIndex]) {
|
|
1344
|
+
if (this.__lineWidths[lineIndex] !== undefined) {
|
|
1321
1345
|
return this.__lineWidths[lineIndex];
|
|
1322
1346
|
}
|
|
1323
1347
|
|
|
1324
|
-
var
|
|
1325
|
-
|
|
1326
|
-
if (line === '') {
|
|
1327
|
-
width = 0;
|
|
1328
|
-
}
|
|
1329
|
-
else {
|
|
1330
|
-
lineInfo = this.measureLine(lineIndex);
|
|
1331
|
-
width = lineInfo.width;
|
|
1332
|
-
}
|
|
1348
|
+
var lineInfo = this.measureLine(lineIndex);
|
|
1349
|
+
var width = lineInfo.width;
|
|
1333
1350
|
this.__lineWidths[lineIndex] = width;
|
|
1334
1351
|
return width;
|
|
1335
1352
|
},
|
|
@@ -133,8 +133,12 @@
|
|
|
133
133
|
imageSmoothingEnabled: true,
|
|
134
134
|
|
|
135
135
|
/**
|
|
136
|
-
* The transformation (
|
|
136
|
+
* The transformation (a Canvas 2D API transform matrix) which focuses the viewport
|
|
137
137
|
* @type Array
|
|
138
|
+
* @example <caption>Default transform</caption>
|
|
139
|
+
* canvas.viewportTransform = [1, 0, 0, 1, 0, 0];
|
|
140
|
+
* @example <caption>Scale by 70% and translate toward bottom-right by 50, without skewing</caption>
|
|
141
|
+
* canvas.viewportTransform = [0.7, 0, 0, 0.7, 50, 50];
|
|
138
142
|
* @default
|
|
139
143
|
*/
|
|
140
144
|
viewportTransform: fabric.iMatrix.concat(),
|
|
@@ -228,7 +232,7 @@
|
|
|
228
232
|
* @private
|
|
229
233
|
*/
|
|
230
234
|
_isRetinaScaling: function() {
|
|
231
|
-
return (fabric.devicePixelRatio
|
|
235
|
+
return (fabric.devicePixelRatio > 1 && this.enableRetinaScaling);
|
|
232
236
|
},
|
|
233
237
|
|
|
234
238
|
/**
|
|
@@ -236,7 +240,7 @@
|
|
|
236
240
|
* @return {Number} retinaScaling if applied, otherwise 1;
|
|
237
241
|
*/
|
|
238
242
|
getRetinaScaling: function() {
|
|
239
|
-
return this._isRetinaScaling() ? fabric.devicePixelRatio : 1;
|
|
243
|
+
return this._isRetinaScaling() ? Math.max(1, fabric.devicePixelRatio) : 1;
|
|
240
244
|
},
|
|
241
245
|
|
|
242
246
|
/**
|
|
@@ -603,7 +607,7 @@
|
|
|
603
607
|
}
|
|
604
608
|
}
|
|
605
609
|
if (this._isCurrentlyDrawing) {
|
|
606
|
-
this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles();
|
|
610
|
+
this.freeDrawingBrush && this.freeDrawingBrush._setBrushStyles(this.contextTop);
|
|
607
611
|
}
|
|
608
612
|
this._initRetinaScaling();
|
|
609
613
|
this.calcOffset();
|
|
@@ -670,8 +674,8 @@
|
|
|
670
674
|
},
|
|
671
675
|
|
|
672
676
|
/**
|
|
673
|
-
* Sets viewport
|
|
674
|
-
* @param {Array} vpt
|
|
677
|
+
* Sets viewport transformation of this canvas instance
|
|
678
|
+
* @param {Array} vpt a Canvas 2D API transform matrix
|
|
675
679
|
* @return {fabric.Canvas} instance
|
|
676
680
|
* @chainable true
|
|
677
681
|
*/
|
|
@@ -1772,7 +1776,7 @@
|
|
|
1772
1776
|
this.contextContainer = null;
|
|
1773
1777
|
// restore canvas style
|
|
1774
1778
|
this.lowerCanvasEl.classList.remove('lower-canvas');
|
|
1775
|
-
this.lowerCanvasEl
|
|
1779
|
+
fabric.util.setStyle(this.lowerCanvasEl, this._originalCanvasStyle);
|
|
1776
1780
|
delete this._originalCanvasStyle;
|
|
1777
1781
|
// restore canvas size to original size in case retina scaling was applied
|
|
1778
1782
|
this.lowerCanvasEl.setAttribute('width', this.width);
|
package/src/util/animate.js
CHANGED
|
@@ -1,4 +1,129 @@
|
|
|
1
|
-
(function() {
|
|
1
|
+
(function () {
|
|
2
|
+
|
|
3
|
+
var extend = fabric.util.object.extend,
|
|
4
|
+
clone = fabric.util.object.clone;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Object} AnimationOptions
|
|
8
|
+
* Animation of a value or list of values.
|
|
9
|
+
* When using lists, think of something like this:
|
|
10
|
+
* fabric.util.animate({
|
|
11
|
+
* startValue: [1, 2, 3],
|
|
12
|
+
* endValue: [2, 4, 6],
|
|
13
|
+
* onChange: function([a, b, c]) {
|
|
14
|
+
* canvas.zoomToPoint({x: b, y: c}, a)
|
|
15
|
+
* canvas.renderAll()
|
|
16
|
+
* }
|
|
17
|
+
* });
|
|
18
|
+
* @example
|
|
19
|
+
* @property {Function} [onChange] Callback; invoked on every value change
|
|
20
|
+
* @property {Function} [onComplete] Callback; invoked when value change is completed
|
|
21
|
+
* @example
|
|
22
|
+
* // Note: startValue, endValue, and byValue must match the type
|
|
23
|
+
* var animationOptions = { startValue: 0, endValue: 1, byValue: 0.25 }
|
|
24
|
+
* var animationOptions = { startValue: [0, 1], endValue: [1, 2], byValue: [0.25, 0.25] }
|
|
25
|
+
* @property {number | number[]} [startValue=0] Starting value
|
|
26
|
+
* @property {number | number[]} [endValue=100] Ending value
|
|
27
|
+
* @property {number | number[]} [byValue=100] Value to modify the property by
|
|
28
|
+
* @property {Function} [easing] Easing function
|
|
29
|
+
* @property {Number} [duration=500] Duration of change (in ms)
|
|
30
|
+
* @property {Function} [abort] Additional function with logic. If returns true, animation aborts.
|
|
31
|
+
*
|
|
32
|
+
* @typedef {() => void} CancelFunction
|
|
33
|
+
*
|
|
34
|
+
* @typedef {Object} AnimationCurrentState
|
|
35
|
+
* @property {number | number[]} currentValue value in range [`startValue`, `endValue`]
|
|
36
|
+
* @property {number} completionRate value in range [0, 1]
|
|
37
|
+
* @property {number} durationRate value in range [0, 1]
|
|
38
|
+
*
|
|
39
|
+
* @typedef {(AnimationOptions & AnimationCurrentState & { cancel: CancelFunction }} AnimationContext
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Array holding all running animations
|
|
44
|
+
* @memberof fabric
|
|
45
|
+
* @type {AnimationContext[]}
|
|
46
|
+
*/
|
|
47
|
+
var RUNNING_ANIMATIONS = [];
|
|
48
|
+
fabric.util.object.extend(RUNNING_ANIMATIONS, {
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* cancel all running animations at the next requestAnimFrame
|
|
52
|
+
* @returns {AnimationContext[]}
|
|
53
|
+
*/
|
|
54
|
+
cancelAll: function () {
|
|
55
|
+
var animations = this.splice(0);
|
|
56
|
+
animations.forEach(function (animation) {
|
|
57
|
+
animation.cancel();
|
|
58
|
+
});
|
|
59
|
+
return animations;
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* cancel all running animations attached to canvas at the next requestAnimFrame
|
|
64
|
+
* @param {fabric.Canvas} canvas
|
|
65
|
+
* @returns {AnimationContext[]}
|
|
66
|
+
*/
|
|
67
|
+
cancelByCanvas: function (canvas) {
|
|
68
|
+
if (!canvas) {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
var cancelled = this.filter(function (animation) {
|
|
72
|
+
return typeof animation.target === 'object' && animation.target.canvas === canvas;
|
|
73
|
+
});
|
|
74
|
+
cancelled.forEach(function (animation) {
|
|
75
|
+
animation.cancel();
|
|
76
|
+
});
|
|
77
|
+
return cancelled;
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* cancel all running animations for target at the next requestAnimFrame
|
|
82
|
+
* @param {*} target
|
|
83
|
+
* @returns {AnimationContext[]}
|
|
84
|
+
*/
|
|
85
|
+
cancelByTarget: function (target) {
|
|
86
|
+
var cancelled = this.findAnimationsByTarget(target);
|
|
87
|
+
cancelled.forEach(function (animation) {
|
|
88
|
+
animation.cancel();
|
|
89
|
+
});
|
|
90
|
+
return cancelled;
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
*
|
|
95
|
+
* @param {CancelFunction} cancelFunc the function returned by animate
|
|
96
|
+
* @returns {number}
|
|
97
|
+
*/
|
|
98
|
+
findAnimationIndex: function (cancelFunc) {
|
|
99
|
+
return this.indexOf(this.findAnimation(cancelFunc));
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
*
|
|
104
|
+
* @param {CancelFunction} cancelFunc the function returned by animate
|
|
105
|
+
* @returns {AnimationContext | undefined} animation's options object
|
|
106
|
+
*/
|
|
107
|
+
findAnimation: function (cancelFunc) {
|
|
108
|
+
return this.find(function (animation) {
|
|
109
|
+
return animation.cancel === cancelFunc;
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
*
|
|
115
|
+
* @param {*} target the object that is assigned to the target property of the animation context
|
|
116
|
+
* @returns {AnimationContext[]} array of animation options object associated with target
|
|
117
|
+
*/
|
|
118
|
+
findAnimationsByTarget: function (target) {
|
|
119
|
+
if (!target) {
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
return this.filter(function (animation) {
|
|
123
|
+
return animation.target === target;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
});
|
|
2
127
|
|
|
3
128
|
function noop() {
|
|
4
129
|
return false;
|
|
@@ -11,22 +136,34 @@
|
|
|
11
136
|
/**
|
|
12
137
|
* Changes value from one to another within certain period of time, invoking callbacks as value is being changed.
|
|
13
138
|
* @memberOf fabric.util
|
|
14
|
-
* @param {
|
|
15
|
-
* @
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* @
|
|
20
|
-
* @param {Function} [options.easing] Easing function
|
|
21
|
-
* @param {Number} [options.duration=500] Duration of change (in ms)
|
|
22
|
-
* @param {Function} [options.abort] Additional function with logic. If returns true, onComplete is called.
|
|
23
|
-
* @returns {Function} abort function
|
|
139
|
+
* @param {AnimationOptions} [options] Animation options
|
|
140
|
+
* @example
|
|
141
|
+
* // Note: startValue, endValue, and byValue must match the type
|
|
142
|
+
* fabric.util.animate({ startValue: 0, endValue: 1, byValue: 0.25 })
|
|
143
|
+
* fabric.util.animate({ startValue: [0, 1], endValue: [1, 2], byValue: [0.25, 0.25] })
|
|
144
|
+
* @returns {CancelFunction} cancel function
|
|
24
145
|
*/
|
|
25
146
|
function animate(options) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
147
|
+
options || (options = {});
|
|
148
|
+
var cancel = false,
|
|
149
|
+
context,
|
|
150
|
+
removeFromRegistry = function () {
|
|
151
|
+
var index = fabric.runningAnimations.indexOf(context);
|
|
152
|
+
return index > -1 && fabric.runningAnimations.splice(index, 1)[0];
|
|
153
|
+
};
|
|
29
154
|
|
|
155
|
+
context = extend(clone(options), {
|
|
156
|
+
cancel: function () {
|
|
157
|
+
cancel = true;
|
|
158
|
+
return removeFromRegistry();
|
|
159
|
+
},
|
|
160
|
+
currentValue: 'startValue' in options ? options.startValue : 0,
|
|
161
|
+
completionRate: 0,
|
|
162
|
+
durationRate: 0
|
|
163
|
+
});
|
|
164
|
+
fabric.runningAnimations.push(context);
|
|
165
|
+
|
|
166
|
+
requestAnimFrame(function(timestamp) {
|
|
30
167
|
var start = timestamp || +new Date(),
|
|
31
168
|
duration = options.duration || 500,
|
|
32
169
|
finish = start + duration, time,
|
|
@@ -34,32 +171,44 @@
|
|
|
34
171
|
abort = options.abort || noop,
|
|
35
172
|
onComplete = options.onComplete || noop,
|
|
36
173
|
easing = options.easing || defaultEasing,
|
|
174
|
+
isMany = 'startValue' in options ? options.startValue.length > 0 : false,
|
|
37
175
|
startValue = 'startValue' in options ? options.startValue : 0,
|
|
38
176
|
endValue = 'endValue' in options ? options.endValue : 100,
|
|
39
|
-
byValue = options.byValue ||
|
|
177
|
+
byValue = options.byValue || (isMany ? startValue.map(function(value, i) {
|
|
178
|
+
return endValue[i] - startValue[i];
|
|
179
|
+
}) : endValue - startValue);
|
|
40
180
|
|
|
41
181
|
options.onStart && options.onStart();
|
|
42
182
|
|
|
43
183
|
(function tick(ticktime) {
|
|
44
|
-
// TODO: move abort call after calculation
|
|
45
|
-
// and pass (current,valuePerc, timePerc) as arguments
|
|
46
184
|
time = ticktime || +new Date();
|
|
47
185
|
var currentTime = time > finish ? duration : (time - start),
|
|
48
186
|
timePerc = currentTime / duration,
|
|
49
|
-
current =
|
|
50
|
-
|
|
187
|
+
current = isMany ? startValue.map(function(_value, i) {
|
|
188
|
+
return easing(currentTime, startValue[i], byValue[i], duration);
|
|
189
|
+
}) : easing(currentTime, startValue, byValue, duration),
|
|
190
|
+
valuePerc = isMany ? Math.abs((current[0] - startValue[0]) / byValue[0])
|
|
191
|
+
: Math.abs((current - startValue) / byValue);
|
|
192
|
+
// update context
|
|
193
|
+
context.currentValue = isMany ? current.slice() : current;
|
|
194
|
+
context.completionRate = valuePerc;
|
|
195
|
+
context.durationRate = timePerc;
|
|
51
196
|
if (cancel) {
|
|
52
197
|
return;
|
|
53
198
|
}
|
|
54
199
|
if (abort(current, valuePerc, timePerc)) {
|
|
55
|
-
|
|
56
|
-
// does to even make sense to abort and run onComplete?
|
|
57
|
-
onComplete(endValue, 1, 1);
|
|
200
|
+
removeFromRegistry();
|
|
58
201
|
return;
|
|
59
202
|
}
|
|
60
203
|
if (time > finish) {
|
|
61
|
-
|
|
204
|
+
// update context
|
|
205
|
+
context.currentValue = isMany ? endValue.slice() : endValue;
|
|
206
|
+
context.completionRate = 1;
|
|
207
|
+
context.durationRate = 1;
|
|
208
|
+
// execute callbacks
|
|
209
|
+
onChange(isMany ? endValue.slice() : endValue, 1, 1);
|
|
62
210
|
onComplete(endValue, 1, 1);
|
|
211
|
+
removeFromRegistry();
|
|
63
212
|
return;
|
|
64
213
|
}
|
|
65
214
|
else {
|
|
@@ -68,9 +217,8 @@
|
|
|
68
217
|
}
|
|
69
218
|
})(start);
|
|
70
219
|
});
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
};
|
|
220
|
+
|
|
221
|
+
return context.cancel;
|
|
74
222
|
}
|
|
75
223
|
|
|
76
224
|
var _requestAnimFrame = fabric.window.requestAnimationFrame ||
|
|
@@ -102,4 +250,5 @@
|
|
|
102
250
|
fabric.util.animate = animate;
|
|
103
251
|
fabric.util.requestAnimFrame = requestAnimFrame;
|
|
104
252
|
fabric.util.cancelAnimFrame = cancelAnimFrame;
|
|
253
|
+
fabric.runningAnimations = RUNNING_ANIMATIONS;
|
|
105
254
|
})();
|