fabric 4.5.1-browser → 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.
Files changed (49) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/CONTRIBUTING.md +14 -0
  3. package/HEADER.js +1 -1
  4. package/README.md +3 -6
  5. package/SECURITY.md +5 -0
  6. package/build.js +1 -0
  7. package/dist/fabric.js +1160 -668
  8. package/dist/fabric.min.js +1 -1
  9. package/lib/event.js +7 -3
  10. package/package.json +9 -3
  11. package/publish-next.js +15 -0
  12. package/publish.js +3 -0
  13. package/src/brushes/base_brush.class.js +3 -5
  14. package/src/brushes/pattern_brush.class.js +7 -5
  15. package/src/brushes/pencil_brush.class.js +49 -37
  16. package/src/canvas.class.js +27 -57
  17. package/src/filters/saturate_filter.class.js +9 -1
  18. package/src/filters/vibrance_filter.class.js +122 -0
  19. package/src/mixins/animation.mixin.js +20 -25
  20. package/src/mixins/canvas_events.mixin.js +30 -59
  21. package/src/mixins/canvas_grouping.mixin.js +4 -4
  22. package/src/mixins/collection.mixin.js +11 -2
  23. package/src/mixins/eraser_brush.mixin.js +495 -452
  24. package/src/mixins/itext_behavior.mixin.js +7 -1
  25. package/src/mixins/itext_key_behavior.mixin.js +7 -1
  26. package/src/mixins/object_geometry.mixin.js +5 -35
  27. package/src/mixins/object_interactivity.mixin.js +18 -7
  28. package/src/mixins/object_straightening.mixin.js +4 -9
  29. package/src/mixins/observable.mixin.js +22 -0
  30. package/src/parser.js +13 -9
  31. package/src/shapes/circle.class.js +22 -19
  32. package/src/shapes/ellipse.class.js +2 -2
  33. package/src/shapes/group.class.js +24 -32
  34. package/src/shapes/image.class.js +3 -25
  35. package/src/shapes/itext.class.js +10 -0
  36. package/src/shapes/line.class.js +5 -21
  37. package/src/shapes/object.class.js +67 -32
  38. package/src/shapes/path.class.js +17 -18
  39. package/src/shapes/polygon.class.js +11 -10
  40. package/src/shapes/polyline.class.js +33 -24
  41. package/src/shapes/rect.class.js +0 -18
  42. package/src/shapes/text.class.js +120 -58
  43. package/src/shapes/triangle.class.js +0 -15
  44. package/src/static_canvas.class.js +43 -20
  45. package/src/util/animate.js +149 -16
  46. package/src/util/animate_color.js +2 -1
  47. package/src/util/lang_object.js +5 -1
  48. package/src/util/misc.js +193 -42
  49. package/src/util/path.js +89 -52
@@ -13,8 +13,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
13
13
  * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
14
14
  * @param {Function} [callbacks.onComplete] Invoked on completion
15
15
  * @param {Function} [callbacks.onChange] Invoked on every step of animation
16
- * @return {fabric.Canvas} thisArg
17
- * @chainable
16
+ * @return {fabric.AnimationContext} context
18
17
  */
19
18
  fxCenterObjectH: function (object, callbacks) {
20
19
  callbacks = callbacks || { };
@@ -24,7 +23,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
24
23
  onChange = callbacks.onChange || empty,
25
24
  _this = this;
26
25
 
27
- fabric.util.animate({
26
+ return fabric.util.animate({
27
+ target: this,
28
28
  startValue: object.left,
29
29
  endValue: this.getCenter().left,
30
30
  duration: this.FX_DURATION,
@@ -38,8 +38,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
38
38
  onComplete();
39
39
  }
40
40
  });
41
-
42
- return this;
43
41
  },
44
42
 
45
43
  /**
@@ -48,8 +46,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
48
46
  * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
49
47
  * @param {Function} [callbacks.onComplete] Invoked on completion
50
48
  * @param {Function} [callbacks.onChange] Invoked on every step of animation
51
- * @return {fabric.Canvas} thisArg
52
- * @chainable
49
+ * @return {fabric.AnimationContext} context
53
50
  */
54
51
  fxCenterObjectV: function (object, callbacks) {
55
52
  callbacks = callbacks || { };
@@ -59,7 +56,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
59
56
  onChange = callbacks.onChange || empty,
60
57
  _this = this;
61
58
 
62
- fabric.util.animate({
59
+ return fabric.util.animate({
60
+ target: this,
63
61
  startValue: object.top,
64
62
  endValue: this.getCenter().top,
65
63
  duration: this.FX_DURATION,
@@ -73,8 +71,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
73
71
  onComplete();
74
72
  }
75
73
  });
76
-
77
- return this;
78
74
  },
79
75
 
80
76
  /**
@@ -83,8 +79,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
83
79
  * @param {Object} [callbacks] Callbacks object with optional "onComplete" and/or "onChange" properties
84
80
  * @param {Function} [callbacks.onComplete] Invoked on completion
85
81
  * @param {Function} [callbacks.onChange] Invoked on every step of animation
86
- * @return {fabric.Canvas} thisArg
87
- * @chainable
82
+ * @return {fabric.AnimationContext} context
88
83
  */
89
84
  fxRemove: function (object, callbacks) {
90
85
  callbacks = callbacks || { };
@@ -94,7 +89,8 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
94
89
  onChange = callbacks.onChange || empty,
95
90
  _this = this;
96
91
 
97
- fabric.util.animate({
92
+ return fabric.util.animate({
93
+ target: this,
98
94
  startValue: object.opacity,
99
95
  endValue: 0,
100
96
  duration: this.FX_DURATION,
@@ -108,8 +104,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
108
104
  onComplete();
109
105
  }
110
106
  });
111
-
112
- return this;
113
107
  }
114
108
  });
115
109
 
@@ -120,7 +114,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
120
114
  * @param {Number|Object} value Value to animate property to (if string was given first) or options object
121
115
  * @return {fabric.Object} thisArg
122
116
  * @tutorial {@link http://fabricjs.com/fabric-intro-part-2#animation}
123
- * @chainable
117
+ * @return {fabric.AnimationContext | fabric.AnimationContext[]} animation context (or an array if passed multiple properties)
124
118
  *
125
119
  * As object — multiple properties
126
120
  *
@@ -133,22 +127,22 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
133
127
  * object.animate('left', { duration: ... });
134
128
  *
135
129
  */
136
- animate: function() {
130
+ animate: function () {
137
131
  if (arguments[0] && typeof arguments[0] === 'object') {
138
- var propsToAnimate = [], prop, skipCallbacks;
132
+ var propsToAnimate = [], prop, skipCallbacks, out = [];
139
133
  for (prop in arguments[0]) {
140
134
  propsToAnimate.push(prop);
141
135
  }
142
136
  for (var i = 0, len = propsToAnimate.length; i < len; i++) {
143
137
  prop = propsToAnimate[i];
144
138
  skipCallbacks = i !== len - 1;
145
- this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks);
139
+ out.push(this._animate(prop, arguments[0][prop], arguments[1], skipCallbacks));
146
140
  }
141
+ return out;
147
142
  }
148
143
  else {
149
- this._animate.apply(this, arguments);
144
+ return this._animate.apply(this, arguments);
150
145
  }
151
- return this;
152
146
  },
153
147
 
154
148
  /**
@@ -196,13 +190,14 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
196
190
  }
197
191
 
198
192
  var _options = {
193
+ target: this,
199
194
  startValue: options.from,
200
195
  endValue: to,
201
196
  byValue: options.by,
202
197
  easing: options.easing,
203
198
  duration: options.duration,
204
- abort: options.abort && function () {
205
- return options.abort.call(_this);
199
+ abort: options.abort && function(value, valueProgress, timeProgress) {
200
+ return options.abort.call(_this, value, valueProgress, timeProgress);
206
201
  },
207
202
  onChange: function (value, valueProgress, timeProgress) {
208
203
  if (propPair) {
@@ -227,10 +222,10 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
227
222
  };
228
223
 
229
224
  if (propIsColor) {
230
- fabric.util.animateColor(_options.startValue, _options.endValue, _options.duration, _options);
225
+ return fabric.util.animateColor(_options.startValue, _options.endValue, _options.duration, _options);
231
226
  }
232
227
  else {
233
- fabric.util.animate(_options);
228
+ return fabric.util.animate(_options);
234
229
  }
235
230
  }
236
231
  });
@@ -106,7 +106,7 @@
106
106
  this._onDragOver = this._onDragOver.bind(this);
107
107
  this._onDragEnter = this._simpleEventHandler.bind(this, 'dragenter');
108
108
  this._onDragLeave = this._simpleEventHandler.bind(this, 'dragleave');
109
- this._onDrop = this._simpleEventHandler.bind(this, 'drop');
109
+ this._onDrop = this._onDrop.bind(this);
110
110
  this.eventsBound = true;
111
111
  },
112
112
 
@@ -218,6 +218,18 @@
218
218
  this._fireEnterLeaveEvents(target, e);
219
219
  },
220
220
 
221
+ /**
222
+ * `drop:before` is a an event that allow you to schedule logic
223
+ * before the `drop` event. Prefer `drop` event always, but if you need
224
+ * to run some drop-disabling logic on an event, since there is no way
225
+ * to handle event handlers ordering, use `drop:before`
226
+ * @param {Event} e
227
+ */
228
+ _onDrop: function (e) {
229
+ this._simpleEventHandler('drop:before', e);
230
+ return this._simpleEventHandler('drop', e);
231
+ },
232
+
221
233
  /**
222
234
  * @private
223
235
  * @param {Event} e Event object fired on mousedown
@@ -450,25 +462,34 @@
450
462
  );
451
463
  }
452
464
  }
465
+ var corner, pointer;
453
466
  if (target) {
467
+ corner = target._findTargetCorner(
468
+ this.getPointer(e, true),
469
+ fabric.util.isTouchEvent(e)
470
+ );
454
471
  if (target.selectable && target !== this._activeObject && target.activeOn === 'up') {
455
472
  this.setActiveObject(target, e);
456
473
  shouldRender = true;
457
474
  }
458
475
  else {
459
- var corner = target._findTargetCorner(
460
- this.getPointer(e, true),
461
- fabric.util.isTouchEvent(e)
462
- );
463
476
  var control = target.controls[corner],
464
477
  mouseUpHandler = control && control.getMouseUpHandler(e, target, control);
465
478
  if (mouseUpHandler) {
466
- var pointer = this.getPointer(e);
479
+ pointer = this.getPointer(e);
467
480
  mouseUpHandler(e, transform, pointer.x, pointer.y);
468
481
  }
469
482
  }
470
483
  target.isMoving = false;
471
484
  }
485
+ // if we are ending up a transform on a different control or a new object
486
+ // fire the original mouse up from the corner that started the transform
487
+ if (transform && (transform.target !== target || transform.corner !== corner)) {
488
+ var originalControl = transform.target && transform.target.controls[transform.corner],
489
+ originalMouseUpHandler = originalControl && originalControl.getMouseUpHandler(e, target, control);
490
+ pointer = pointer || this.getPointer(e);
491
+ originalMouseUpHandler && originalMouseUpHandler(e, transform, pointer.x, pointer.y);
492
+ }
472
493
  this._setCursorFromEvent(e, target);
473
494
  this._handleEvent(e, 'up', LEFT_CLICK, isClick);
474
495
  this._groupSelector = null;
@@ -550,7 +571,6 @@
550
571
 
551
572
  var transform = this._currentTransform,
552
573
  target = transform.target,
553
- eventName,
554
574
  options = {
555
575
  e: e,
556
576
  target: target,
@@ -565,59 +585,10 @@
565
585
  target.setCoords();
566
586
 
567
587
  if (transform.actionPerformed || (this.stateful && target.hasStateChanged())) {
568
- if (transform.actionPerformed) {
569
- // this is not friendly to the new control api.
570
- // is deprecated.
571
- eventName = this._addEventOptions(options, transform);
572
- this._fire(eventName, options);
573
- }
574
588
  this._fire('modified', options);
575
589
  }
576
590
  },
577
591
 
578
- /**
579
- * Mutate option object in order to add by property and give back the event name.
580
- * @private
581
- * @deprecated since 4.2.0
582
- * @param {Object} options to mutate
583
- * @param {Object} transform to inspect action from
584
- */
585
- _addEventOptions: function(options, transform) {
586
- // we can probably add more details at low cost
587
- // scale change, rotation changes, translation changes
588
- var eventName, by;
589
- switch (transform.action) {
590
- case 'scaleX':
591
- eventName = 'scaled';
592
- by = 'x';
593
- break;
594
- case 'scaleY':
595
- eventName = 'scaled';
596
- by = 'y';
597
- break;
598
- case 'skewX':
599
- eventName = 'skewed';
600
- by = 'x';
601
- break;
602
- case 'skewY':
603
- eventName = 'skewed';
604
- by = 'y';
605
- break;
606
- case 'scale':
607
- eventName = 'scaled';
608
- by = 'equally';
609
- break;
610
- case 'rotate':
611
- eventName = 'rotated';
612
- break;
613
- case 'drag':
614
- eventName = 'moved';
615
- break;
616
- }
617
- options.by = by;
618
- return eventName;
619
- },
620
-
621
592
  /**
622
593
  * @private
623
594
  * @param {Event} e Event object fired on mousedown
@@ -712,8 +683,8 @@
712
683
  if (this.selection && (!target ||
713
684
  (!target.selectable && !target.isEditing && target !== this._activeObject))) {
714
685
  this._groupSelector = {
715
- ex: pointer.x,
716
- ey: pointer.y,
686
+ ex: this._absolutePointer.x,
687
+ ey: this._absolutePointer.y,
717
688
  top: 0,
718
689
  left: 0
719
690
  };
@@ -806,7 +777,7 @@
806
777
 
807
778
  // We initially clicked in an empty area, so we draw a box for multiple selection
808
779
  if (groupSelector) {
809
- pointer = this._pointer;
780
+ pointer = this._absolutePointer;
810
781
 
811
782
  groupSelector.left = pointer.x - groupSelector.ex;
812
783
  groupSelector.top = pointer.y - groupSelector.ey;
@@ -139,10 +139,10 @@
139
139
  continue;
140
140
  }
141
141
 
142
- if ((allowIntersect && currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2)) ||
143
- currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) ||
144
- (allowIntersect && currentObject.containsPoint(selectionX1Y1)) ||
145
- (allowIntersect && currentObject.containsPoint(selectionX2Y2))
142
+ if ((allowIntersect && currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2, true)) ||
143
+ currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2, true) ||
144
+ (allowIntersect && currentObject.containsPoint(selectionX1Y1, null, true)) ||
145
+ (allowIntersect && currentObject.containsPoint(selectionX2Y2, null, true))
146
146
  ) {
147
147
  group.push(currentObject);
148
148
  // only add one object if it's a click
@@ -142,10 +142,19 @@ fabric.Collection = {
142
142
  /**
143
143
  * Returns true if collection contains an object
144
144
  * @param {Object} object Object to check against
145
+ * @param {Boolean} [deep=false] `true` to check all descendants, `false` to check only `_objects`
145
146
  * @return {Boolean} `true` if collection contains an object
146
147
  */
147
- contains: function(object) {
148
- return this._objects.indexOf(object) > -1;
148
+ contains: function (object, deep) {
149
+ if (this._objects.indexOf(object) > -1) {
150
+ return true;
151
+ }
152
+ else if (deep) {
153
+ return this._objects.some(function (obj) {
154
+ return typeof obj.contains === 'function' && obj.contains(object, true);
155
+ });
156
+ }
157
+ return false;
149
158
  },
150
159
 
151
160
  /**