fabric-rails 1.0.12 → 1.0.12.1
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.
- data/CHANGELOG.md +16 -0
- data/README.md +1 -1
- data/lib/fabric/rails/version.rb +2 -2
- data/vendor/assets/javascripts/event.js +1909 -0
- data/vendor/assets/javascripts/fabric.js +64 -16464
- data/vendor/assets/javascripts/fabric/HEADER.js +31 -0
- data/vendor/assets/javascripts/fabric/canvas.class.js +1007 -0
- data/vendor/assets/javascripts/fabric/canvas_animation.mixin.js +113 -0
- data/vendor/assets/javascripts/fabric/canvas_events.mixin.js +482 -0
- data/vendor/assets/javascripts/fabric/canvas_gestures.mixin.js +79 -0
- data/vendor/assets/javascripts/fabric/canvas_serialization.mixin.js +311 -0
- data/vendor/assets/javascripts/fabric/circle.class.js +182 -0
- data/vendor/assets/javascripts/fabric/color.class.js +284 -0
- data/vendor/assets/javascripts/fabric/ellipse.class.js +169 -0
- data/vendor/assets/javascripts/fabric/freedrawing.class.js +256 -0
- data/vendor/assets/javascripts/fabric/gradient.class.js +211 -0
- data/vendor/assets/javascripts/fabric/group.class.js +556 -0
- data/vendor/assets/javascripts/fabric/image.class.js +418 -0
- data/vendor/assets/javascripts/fabric/image_filters.js +809 -0
- data/vendor/assets/javascripts/fabric/intersection.class.js +178 -0
- data/vendor/assets/javascripts/fabric/line.class.js +188 -0
- data/vendor/assets/javascripts/fabric/log.js +26 -0
- data/vendor/assets/javascripts/fabric/node.js +149 -0
- data/vendor/assets/javascripts/fabric/object.class.js +1068 -0
- data/vendor/assets/javascripts/fabric/object_geometry.mixin.js +308 -0
- data/vendor/assets/javascripts/fabric/object_interactivity.mixin.js +496 -0
- data/vendor/assets/javascripts/fabric/object_origin.mixin.js +207 -0
- data/vendor/assets/javascripts/fabric/object_straightening.mixin.js +94 -0
- data/vendor/assets/javascripts/fabric/observable.mixin.js +91 -0
- data/vendor/assets/javascripts/fabric/parser.js +750 -0
- data/vendor/assets/javascripts/fabric/path.class.js +794 -0
- data/vendor/assets/javascripts/fabric/path_group.class.js +240 -0
- data/vendor/assets/javascripts/fabric/pattern.class.js +69 -0
- data/vendor/assets/javascripts/fabric/point.class.js +327 -0
- data/vendor/assets/javascripts/fabric/polygon.class.js +184 -0
- data/vendor/assets/javascripts/fabric/polyline.class.js +157 -0
- data/vendor/assets/javascripts/fabric/rect.class.js +298 -0
- data/vendor/assets/javascripts/fabric/scout.js +45 -0
- data/vendor/assets/javascripts/fabric/shadow.class.js +70 -0
- data/vendor/assets/javascripts/fabric/stateful.js +88 -0
- data/vendor/assets/javascripts/fabric/static_canvas.class.js +1298 -0
- data/vendor/assets/javascripts/fabric/text.class.js +934 -0
- data/vendor/assets/javascripts/fabric/triangle.class.js +108 -0
- data/vendor/assets/javascripts/fabric/util/anim_ease.js +360 -0
- data/vendor/assets/javascripts/fabric/util/dom_event.js +237 -0
- data/vendor/assets/javascripts/fabric/util/dom_misc.js +245 -0
- data/vendor/assets/javascripts/fabric/util/dom_request.js +72 -0
- data/vendor/assets/javascripts/fabric/util/dom_style.js +71 -0
- data/vendor/assets/javascripts/fabric/util/lang_array.js +250 -0
- data/vendor/assets/javascripts/fabric/util/lang_class.js +97 -0
- data/vendor/assets/javascripts/fabric/util/lang_function.js +35 -0
- data/vendor/assets/javascripts/fabric/util/lang_object.js +34 -0
- data/vendor/assets/javascripts/fabric/util/lang_string.js +60 -0
- data/vendor/assets/javascripts/fabric/util/misc.js +406 -0
- data/vendor/assets/javascripts/json2.js +491 -0
- metadata +53 -2
@@ -0,0 +1,1068 @@
|
|
1
|
+
(function(global) {
|
2
|
+
|
3
|
+
"use strict";
|
4
|
+
|
5
|
+
var fabric = global.fabric || (global.fabric = { }),
|
6
|
+
extend = fabric.util.object.extend,
|
7
|
+
toFixed = fabric.util.toFixed,
|
8
|
+
capitalize = fabric.util.string.capitalize,
|
9
|
+
degreesToRadians = fabric.util.degreesToRadians;
|
10
|
+
|
11
|
+
if (fabric.Object) {
|
12
|
+
return;
|
13
|
+
}
|
14
|
+
|
15
|
+
var Image = global.Image;
|
16
|
+
try {
|
17
|
+
var NodeImage = (typeof require !== 'undefined') && require('canvas').Image;
|
18
|
+
if (NodeImage) {
|
19
|
+
Image = NodeImage;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
catch(err) {
|
23
|
+
fabric.log(err);
|
24
|
+
}
|
25
|
+
|
26
|
+
/**
|
27
|
+
* Root object class from which all 2d shape classes inherit from
|
28
|
+
* @class Object
|
29
|
+
* @memberOf fabric
|
30
|
+
*/
|
31
|
+
fabric.Object = fabric.util.createClass(/** @scope fabric.Object.prototype */ {
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Type of an object (rect, circle, path, etc.)
|
35
|
+
* @property
|
36
|
+
* @type String
|
37
|
+
*/
|
38
|
+
type: 'object',
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Horizontal origin of transformation of an object (one of "left", "right", "center")
|
42
|
+
* @property
|
43
|
+
* @type String
|
44
|
+
*/
|
45
|
+
originX: 'center',
|
46
|
+
|
47
|
+
/**
|
48
|
+
* Vertical origin of transformation of an object (one of "top", "bottom", "center")
|
49
|
+
* @property
|
50
|
+
* @type String
|
51
|
+
*/
|
52
|
+
originY: 'center',
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Top position of an object
|
56
|
+
* @property
|
57
|
+
* @type Number
|
58
|
+
*/
|
59
|
+
top: 0,
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Left position of an object
|
63
|
+
* @property
|
64
|
+
* @type Number
|
65
|
+
*/
|
66
|
+
left: 0,
|
67
|
+
|
68
|
+
/**
|
69
|
+
* Object width
|
70
|
+
* @property
|
71
|
+
* @type Number
|
72
|
+
*/
|
73
|
+
width: 0,
|
74
|
+
|
75
|
+
/**
|
76
|
+
* Object height
|
77
|
+
* @property
|
78
|
+
* @type Number
|
79
|
+
*/
|
80
|
+
height: 0,
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Object scale factor (horizontal)
|
84
|
+
* @property
|
85
|
+
* @type Number
|
86
|
+
*/
|
87
|
+
scaleX: 1,
|
88
|
+
|
89
|
+
/**
|
90
|
+
* Object scale factor (vertical)
|
91
|
+
* @property
|
92
|
+
* @type Number
|
93
|
+
*/
|
94
|
+
scaleY: 1,
|
95
|
+
|
96
|
+
/**
|
97
|
+
* When true, an object is rendered as flipped horizontally
|
98
|
+
* @property
|
99
|
+
* @type Boolean
|
100
|
+
*/
|
101
|
+
flipX: false,
|
102
|
+
|
103
|
+
/**
|
104
|
+
* When true, an object is rendered as flipped vertically
|
105
|
+
* @property
|
106
|
+
* @type Boolean
|
107
|
+
*/
|
108
|
+
flipY: false,
|
109
|
+
|
110
|
+
/**
|
111
|
+
* Opacity of an object
|
112
|
+
* @property
|
113
|
+
* @type Number
|
114
|
+
*/
|
115
|
+
opacity: 1,
|
116
|
+
|
117
|
+
/**
|
118
|
+
* Angle of rotation of an object (in degrees)
|
119
|
+
* @property
|
120
|
+
* @type Number
|
121
|
+
*/
|
122
|
+
angle: 0,
|
123
|
+
|
124
|
+
/**
|
125
|
+
* Size of object's corners (in pixels)
|
126
|
+
* @property
|
127
|
+
* @type Number
|
128
|
+
*/
|
129
|
+
cornerSize: 12,
|
130
|
+
|
131
|
+
/**
|
132
|
+
* When true, object's corners are rendered as transparent inside (i.e. stroke instead of fill)
|
133
|
+
* @property
|
134
|
+
* @type Boolean
|
135
|
+
*/
|
136
|
+
transparentCorners: true,
|
137
|
+
|
138
|
+
/**
|
139
|
+
* Padding between object and its borders (in pixels)
|
140
|
+
* @property
|
141
|
+
* @type Number
|
142
|
+
*/
|
143
|
+
padding: 0,
|
144
|
+
|
145
|
+
/**
|
146
|
+
* Border color of an object (when it's active)
|
147
|
+
* @property
|
148
|
+
* @type String
|
149
|
+
*/
|
150
|
+
borderColor: 'rgba(102,153,255,0.75)',
|
151
|
+
|
152
|
+
/**
|
153
|
+
* Corner color of an object (when it's active)
|
154
|
+
* @property
|
155
|
+
* @type String
|
156
|
+
*/
|
157
|
+
cornerColor: 'rgba(102,153,255,0.5)',
|
158
|
+
|
159
|
+
/**
|
160
|
+
* Color of object's fill
|
161
|
+
* @property
|
162
|
+
* @type String
|
163
|
+
*/
|
164
|
+
fill: 'rgb(0,0,0)',
|
165
|
+
|
166
|
+
/**
|
167
|
+
* Fill rule used to fill an object
|
168
|
+
* @property
|
169
|
+
* @type String
|
170
|
+
*/
|
171
|
+
fillRule: 'source-over',
|
172
|
+
|
173
|
+
/**
|
174
|
+
* Overlay fill (takes precedence over fill value)
|
175
|
+
* @property
|
176
|
+
* @type String
|
177
|
+
*/
|
178
|
+
overlayFill: null,
|
179
|
+
|
180
|
+
/**
|
181
|
+
* When `true`, an object is rendered via stroke and this property specifies its color
|
182
|
+
* @property
|
183
|
+
* @type String
|
184
|
+
*/
|
185
|
+
stroke: null,
|
186
|
+
|
187
|
+
/**
|
188
|
+
* Width of a stroke used to render this object
|
189
|
+
* @property
|
190
|
+
* @type Number
|
191
|
+
*/
|
192
|
+
strokeWidth: 1,
|
193
|
+
|
194
|
+
/**
|
195
|
+
* Array specifying dash pattern of an object's stroke
|
196
|
+
* @property
|
197
|
+
* @type Array
|
198
|
+
*/
|
199
|
+
strokeDashArray: null,
|
200
|
+
|
201
|
+
/**
|
202
|
+
* Shadow object representing shadow of this shape
|
203
|
+
* @property
|
204
|
+
* @type fabric.Shadow
|
205
|
+
*/
|
206
|
+
shadow: null,
|
207
|
+
|
208
|
+
/**
|
209
|
+
* Border opacity when object is active and moving
|
210
|
+
* @property
|
211
|
+
* @type Number
|
212
|
+
*/
|
213
|
+
borderOpacityWhenMoving: 0.4,
|
214
|
+
|
215
|
+
/**
|
216
|
+
* Border scale factor
|
217
|
+
* @property
|
218
|
+
* @type Number
|
219
|
+
*/
|
220
|
+
borderScaleFactor: 1,
|
221
|
+
|
222
|
+
/**
|
223
|
+
* Transform matrix (similar to SVG's transform matrix)
|
224
|
+
* @property
|
225
|
+
* @type Array
|
226
|
+
*/
|
227
|
+
transformMatrix: null,
|
228
|
+
|
229
|
+
/**
|
230
|
+
* Minimum allowed scale value of an object
|
231
|
+
* @property
|
232
|
+
* @type Number
|
233
|
+
*/
|
234
|
+
minScaleLimit: 0.01,
|
235
|
+
|
236
|
+
/**
|
237
|
+
* When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection)
|
238
|
+
* @property
|
239
|
+
* @type Boolean
|
240
|
+
*/
|
241
|
+
selectable: true,
|
242
|
+
|
243
|
+
/**
|
244
|
+
* When set to `false`, object's controls are not displayed and can not be used to manipulate object
|
245
|
+
* @property
|
246
|
+
* @type Boolean
|
247
|
+
*/
|
248
|
+
hasControls: true,
|
249
|
+
|
250
|
+
/**
|
251
|
+
* When set to `false`, object's borders are not rendered
|
252
|
+
* @property
|
253
|
+
* @type Boolean
|
254
|
+
*/
|
255
|
+
hasBorders: true,
|
256
|
+
|
257
|
+
/**
|
258
|
+
* When set to `false`, object's rotating point will not be visible or selectable
|
259
|
+
* @property
|
260
|
+
* @type Boolean
|
261
|
+
*/
|
262
|
+
hasRotatingPoint: true,
|
263
|
+
|
264
|
+
/**
|
265
|
+
* Offset for object's rotating point (when enabled via `hasRotatingPoint`)
|
266
|
+
* @property
|
267
|
+
* @type Number
|
268
|
+
*/
|
269
|
+
rotatingPointOffset: 40,
|
270
|
+
|
271
|
+
/**
|
272
|
+
* When set to `true`, objects are "found" on canvas on per-pixel basis rather than according to bounding box
|
273
|
+
* @property
|
274
|
+
* @type Boolean
|
275
|
+
*/
|
276
|
+
perPixelTargetFind: false,
|
277
|
+
|
278
|
+
/**
|
279
|
+
* When `false`, default object's values are not included in its serialization
|
280
|
+
* @property
|
281
|
+
* @type Boolean
|
282
|
+
*/
|
283
|
+
includeDefaultValues: true,
|
284
|
+
|
285
|
+
/**
|
286
|
+
* List of properties to consider when checking if state of an object is changed (fabric.Object#hasStateChanged);
|
287
|
+
* as well as for history (undo/redo) purposes
|
288
|
+
* @property
|
289
|
+
* @type Array
|
290
|
+
*/
|
291
|
+
stateProperties: (
|
292
|
+
'top left width height scaleX scaleY flipX flipY ' +
|
293
|
+
'angle opacity cornerSize fill overlayFill originX originY ' +
|
294
|
+
'stroke strokeWidth strokeDashArray fillRule ' +
|
295
|
+
'borderScaleFactor transformMatrix selectable shadow'
|
296
|
+
).split(' '),
|
297
|
+
|
298
|
+
/**
|
299
|
+
* Constructor
|
300
|
+
* @method initialize
|
301
|
+
* @param {Object} [options] Options object
|
302
|
+
*/
|
303
|
+
initialize: function(options) {
|
304
|
+
if (options) {
|
305
|
+
this.setOptions(options);
|
306
|
+
}
|
307
|
+
},
|
308
|
+
|
309
|
+
/**
|
310
|
+
* @private
|
311
|
+
* @method _initGradient
|
312
|
+
*/
|
313
|
+
_initGradient: function(options) {
|
314
|
+
if (options.fill && options.fill.colorStops && !(options.fill instanceof fabric.Gradient)) {
|
315
|
+
this.set('fill', new fabric.Gradient(options.fill));
|
316
|
+
}
|
317
|
+
},
|
318
|
+
|
319
|
+
/**
|
320
|
+
* @private
|
321
|
+
* @method _initPattern
|
322
|
+
*/
|
323
|
+
_initPattern: function(options) {
|
324
|
+
if (options.fill && options.fill.source && !(options.fill instanceof fabric.Pattern)) {
|
325
|
+
this.set('fill', new fabric.Pattern(options.fill));
|
326
|
+
}
|
327
|
+
if (options.stroke && options.stroke.source && !(options.stroke instanceof fabric.Pattern)) {
|
328
|
+
this.set('stroke', new fabric.Pattern(options.stroke));
|
329
|
+
}
|
330
|
+
},
|
331
|
+
|
332
|
+
/**
|
333
|
+
* @private
|
334
|
+
* @method _initShadow
|
335
|
+
*/
|
336
|
+
_initShadow: function(options) {
|
337
|
+
if (options.shadow && !(options.shadow instanceof fabric.Shadow)) {
|
338
|
+
this.setShadow(options.shadow);
|
339
|
+
}
|
340
|
+
},
|
341
|
+
|
342
|
+
/**
|
343
|
+
* Sets object's properties from options
|
344
|
+
* @method setOptions
|
345
|
+
* @param {Object} [options]
|
346
|
+
*/
|
347
|
+
setOptions: function(options) {
|
348
|
+
for (var prop in options) {
|
349
|
+
this.set(prop, options[prop]);
|
350
|
+
}
|
351
|
+
this._initGradient(options);
|
352
|
+
this._initPattern(options);
|
353
|
+
this._initShadow(options);
|
354
|
+
},
|
355
|
+
|
356
|
+
/**
|
357
|
+
* Transforms context when rendering an object
|
358
|
+
* @method transform
|
359
|
+
* @param {CanvasRenderingContext2D} ctx Context
|
360
|
+
*/
|
361
|
+
transform: function(ctx) {
|
362
|
+
ctx.globalAlpha = this.opacity;
|
363
|
+
|
364
|
+
var center = this.getCenterPoint();
|
365
|
+
ctx.translate(center.x, center.y);
|
366
|
+
ctx.rotate(degreesToRadians(this.angle));
|
367
|
+
ctx.scale(
|
368
|
+
this.scaleX * (this.flipX ? -1 : 1),
|
369
|
+
this.scaleY * (this.flipY ? -1 : 1)
|
370
|
+
);
|
371
|
+
},
|
372
|
+
|
373
|
+
/**
|
374
|
+
* Returns an object representation of an instance
|
375
|
+
* @method toObject
|
376
|
+
* @param {Array} propertiesToInclude
|
377
|
+
* @return {Object} object representation of an instance
|
378
|
+
*/
|
379
|
+
toObject: function(propertiesToInclude) {
|
380
|
+
|
381
|
+
var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;
|
382
|
+
|
383
|
+
var object = {
|
384
|
+
type: this.type,
|
385
|
+
originX: this.originX,
|
386
|
+
originY: this.originY,
|
387
|
+
left: toFixed(this.left, NUM_FRACTION_DIGITS),
|
388
|
+
top: toFixed(this.top, NUM_FRACTION_DIGITS),
|
389
|
+
width: toFixed(this.width, NUM_FRACTION_DIGITS),
|
390
|
+
height: toFixed(this.height, NUM_FRACTION_DIGITS),
|
391
|
+
fill: (this.fill && this.fill.toObject) ? this.fill.toObject() : this.fill,
|
392
|
+
overlayFill: this.overlayFill,
|
393
|
+
stroke: (this.stroke && this.stroke.toObject) ? this.stroke.toObject() : this.stroke,
|
394
|
+
strokeWidth: this.strokeWidth,
|
395
|
+
strokeDashArray: this.strokeDashArray,
|
396
|
+
scaleX: toFixed(this.scaleX, NUM_FRACTION_DIGITS),
|
397
|
+
scaleY: toFixed(this.scaleY, NUM_FRACTION_DIGITS),
|
398
|
+
angle: toFixed(this.getAngle(), NUM_FRACTION_DIGITS),
|
399
|
+
flipX: this.flipX,
|
400
|
+
flipY: this.flipY,
|
401
|
+
opacity: toFixed(this.opacity, NUM_FRACTION_DIGITS),
|
402
|
+
selectable: this.selectable,
|
403
|
+
hasControls: this.hasControls,
|
404
|
+
hasBorders: this.hasBorders,
|
405
|
+
hasRotatingPoint: this.hasRotatingPoint,
|
406
|
+
transparentCorners: this.transparentCorners,
|
407
|
+
perPixelTargetFind: this.perPixelTargetFind,
|
408
|
+
shadow: (this.shadow && this.shadow.toObject) ? this.shadow.toObject() : this.shadow
|
409
|
+
};
|
410
|
+
|
411
|
+
if (!this.includeDefaultValues) {
|
412
|
+
object = this._removeDefaultValues(object);
|
413
|
+
}
|
414
|
+
fabric.util.populateWithProperties(this, object, propertiesToInclude);
|
415
|
+
|
416
|
+
return object;
|
417
|
+
},
|
418
|
+
|
419
|
+
/**
|
420
|
+
* Returns (dataless) object representation of an instance
|
421
|
+
* @method toDatalessObject
|
422
|
+
* @param {Array} [propertiesToInclude]
|
423
|
+
* @return {Object} object representation of an instance
|
424
|
+
*/
|
425
|
+
toDatalessObject: function(propertiesToInclude) {
|
426
|
+
// will be overwritten by subclasses
|
427
|
+
return this.toObject(propertiesToInclude);
|
428
|
+
},
|
429
|
+
|
430
|
+
/**
|
431
|
+
* Returns styles-string for svg-export
|
432
|
+
* @method getSvgStyles
|
433
|
+
* @return {String}
|
434
|
+
*/
|
435
|
+
getSvgStyles: function() {
|
436
|
+
return [
|
437
|
+
"stroke: ", (this.stroke ? this.stroke : 'none'), "; ",
|
438
|
+
"stroke-width: ", (this.strokeWidth ? this.strokeWidth : '0'), "; ",
|
439
|
+
"stroke-dasharray: ", (this.strokeDashArray ? this.strokeDashArray.join(' ') : "; "),
|
440
|
+
"fill: ", (this.fill ? this.fill : 'none'), "; ",
|
441
|
+
"opacity: ", (this.opacity ? this.opacity : '1'), ";"
|
442
|
+
].join("");
|
443
|
+
},
|
444
|
+
|
445
|
+
/**
|
446
|
+
* Returns transform-string for svg-export
|
447
|
+
* @method getSvgTransform
|
448
|
+
* @return {String}
|
449
|
+
*/
|
450
|
+
getSvgTransform: function() {
|
451
|
+
var angle = this.getAngle();
|
452
|
+
var center = this.getCenterPoint();
|
453
|
+
|
454
|
+
var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS;
|
455
|
+
|
456
|
+
var translatePart = "translate(" +
|
457
|
+
toFixed(center.x, NUM_FRACTION_DIGITS) +
|
458
|
+
" " +
|
459
|
+
toFixed(center.y, NUM_FRACTION_DIGITS) +
|
460
|
+
")";
|
461
|
+
|
462
|
+
var anglePart = angle !== 0
|
463
|
+
? (" rotate(" + toFixed(angle, NUM_FRACTION_DIGITS) + ")")
|
464
|
+
: '';
|
465
|
+
|
466
|
+
var scalePart = (this.scaleX === 1 && this.scaleY === 1)
|
467
|
+
? '' :
|
468
|
+
(" scale(" +
|
469
|
+
toFixed(this.scaleX, NUM_FRACTION_DIGITS) +
|
470
|
+
" " +
|
471
|
+
toFixed(this.scaleY, NUM_FRACTION_DIGITS) +
|
472
|
+
")");
|
473
|
+
|
474
|
+
var flipXPart = this.flipX ? "matrix(-1 0 0 1 0 0) " : "";
|
475
|
+
var flipYPart = this.flipY ? "matrix(1 0 0 -1 0 0)" : "";
|
476
|
+
|
477
|
+
return [ translatePart, anglePart, scalePart, flipXPart, flipYPart ].join('');
|
478
|
+
},
|
479
|
+
|
480
|
+
/**
|
481
|
+
* @private
|
482
|
+
* @method _removeDefaultValues
|
483
|
+
*/
|
484
|
+
_removeDefaultValues: function(object) {
|
485
|
+
var defaultOptions = fabric.Object.prototype.options;
|
486
|
+
if (defaultOptions) {
|
487
|
+
this.stateProperties.forEach(function(prop) {
|
488
|
+
if (object[prop] === defaultOptions[prop]) {
|
489
|
+
delete object[prop];
|
490
|
+
}
|
491
|
+
});
|
492
|
+
}
|
493
|
+
return object;
|
494
|
+
},
|
495
|
+
|
496
|
+
/**
|
497
|
+
* Returns true if an object is in its active state
|
498
|
+
* @return {Boolean} true if an object is in its active state
|
499
|
+
*/
|
500
|
+
isActive: function() {
|
501
|
+
return !!this.active;
|
502
|
+
},
|
503
|
+
|
504
|
+
/**
|
505
|
+
* Sets state of an object - `true` makes it active, `false` - inactive
|
506
|
+
* @param {Boolean} active
|
507
|
+
* @return {fabric.Object} thisArg
|
508
|
+
* @chainable
|
509
|
+
*/
|
510
|
+
setActive: function(active) {
|
511
|
+
this.active = !!active;
|
512
|
+
return this;
|
513
|
+
},
|
514
|
+
|
515
|
+
/**
|
516
|
+
* Returns a string representation of an instance
|
517
|
+
* @return {String}
|
518
|
+
*/
|
519
|
+
toString: function() {
|
520
|
+
return "#<fabric." + capitalize(this.type) + ">";
|
521
|
+
},
|
522
|
+
|
523
|
+
/**
|
524
|
+
* Basic getter
|
525
|
+
* @method get
|
526
|
+
* @param {String} property
|
527
|
+
* @return {Any} value of a property
|
528
|
+
*/
|
529
|
+
get: function(property) {
|
530
|
+
return this[property];
|
531
|
+
},
|
532
|
+
|
533
|
+
/**
|
534
|
+
* Sets property to a given value
|
535
|
+
* @method set
|
536
|
+
* @param {String} name
|
537
|
+
* @param {Object|Function} value
|
538
|
+
* @return {fabric.Group} thisArg
|
539
|
+
* @chainable
|
540
|
+
*/
|
541
|
+
set: function(key, value) {
|
542
|
+
if (typeof key === 'object') {
|
543
|
+
for (var prop in key) {
|
544
|
+
this._set(prop, key[prop]);
|
545
|
+
}
|
546
|
+
}
|
547
|
+
else {
|
548
|
+
if (typeof value === 'function') {
|
549
|
+
this._set(key, value(this.get(key)));
|
550
|
+
}
|
551
|
+
else {
|
552
|
+
this._set(key, value);
|
553
|
+
}
|
554
|
+
}
|
555
|
+
return this;
|
556
|
+
},
|
557
|
+
|
558
|
+
/**
|
559
|
+
* @private
|
560
|
+
* @method _set
|
561
|
+
* @param key
|
562
|
+
* @param value
|
563
|
+
*/
|
564
|
+
_set: function(key, value) {
|
565
|
+
var shouldConstrainValue = (key === 'scaleX' || key === 'scaleY');
|
566
|
+
|
567
|
+
if (shouldConstrainValue) {
|
568
|
+
value = this._constrainScale(value);
|
569
|
+
}
|
570
|
+
if (key === 'scaleX' && value < 0) {
|
571
|
+
this.flipX = !this.flipX;
|
572
|
+
value *= -1;
|
573
|
+
}
|
574
|
+
else if (key === 'scaleY' && value < 0) {
|
575
|
+
this.flipY = !this.flipY;
|
576
|
+
value *= -1;
|
577
|
+
}
|
578
|
+
else if (key === 'width' || key === 'height') {
|
579
|
+
this.minScaleLimit = toFixed(Math.min(0.1, 1/Math.max(this.width, this.height)), 2);
|
580
|
+
}
|
581
|
+
|
582
|
+
this[key] = value;
|
583
|
+
|
584
|
+
return this;
|
585
|
+
},
|
586
|
+
|
587
|
+
/**
|
588
|
+
* Toggles specified property from `true` to `false` or from `false` to `true`
|
589
|
+
* @method toggle
|
590
|
+
* @param {String} property property to toggle
|
591
|
+
* @return {fabric.Object} thisArg
|
592
|
+
* @chainable
|
593
|
+
*/
|
594
|
+
toggle: function(property) {
|
595
|
+
var value = this.get(property);
|
596
|
+
if (typeof value === 'boolean') {
|
597
|
+
this.set(property, !value);
|
598
|
+
}
|
599
|
+
return this;
|
600
|
+
},
|
601
|
+
|
602
|
+
/**
|
603
|
+
* Sets sourcePath of an object
|
604
|
+
* @method setSourcePath
|
605
|
+
* @param {String} value
|
606
|
+
* @return {fabric.Object} thisArg
|
607
|
+
* @chainable
|
608
|
+
*/
|
609
|
+
setSourcePath: function(value) {
|
610
|
+
this.sourcePath = value;
|
611
|
+
return this;
|
612
|
+
},
|
613
|
+
|
614
|
+
/**
|
615
|
+
* Renders an object on a specified context
|
616
|
+
* @method render
|
617
|
+
* @param {CanvasRenderingContext2D} ctx context to render on
|
618
|
+
* @param {Boolean} noTransform
|
619
|
+
*/
|
620
|
+
render: function(ctx, noTransform) {
|
621
|
+
|
622
|
+
// do not render if width or height are zeros
|
623
|
+
if (this.width === 0 || this.height === 0) return;
|
624
|
+
|
625
|
+
ctx.save();
|
626
|
+
|
627
|
+
var m = this.transformMatrix;
|
628
|
+
if (m && !this.group) {
|
629
|
+
ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
630
|
+
}
|
631
|
+
|
632
|
+
if (!noTransform) {
|
633
|
+
this.transform(ctx);
|
634
|
+
}
|
635
|
+
|
636
|
+
if (this.stroke || this.strokeDashArray) {
|
637
|
+
ctx.lineWidth = this.strokeWidth;
|
638
|
+
if (this.stroke && this.stroke.toLive) {
|
639
|
+
ctx.strokeStyle = this.stroke.toLive(ctx);
|
640
|
+
}
|
641
|
+
else {
|
642
|
+
ctx.strokeStyle = this.stroke;
|
643
|
+
}
|
644
|
+
}
|
645
|
+
|
646
|
+
if (this.overlayFill) {
|
647
|
+
ctx.fillStyle = this.overlayFill;
|
648
|
+
}
|
649
|
+
else if (this.fill) {
|
650
|
+
ctx.fillStyle = this.fill.toLive
|
651
|
+
? this.fill.toLive(ctx)
|
652
|
+
: this.fill;
|
653
|
+
}
|
654
|
+
|
655
|
+
if (m && this.group) {
|
656
|
+
ctx.translate(-this.group.width/2, -this.group.height/2);
|
657
|
+
ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
658
|
+
}
|
659
|
+
|
660
|
+
this._setShadow(ctx);
|
661
|
+
this._render(ctx, noTransform);
|
662
|
+
this._removeShadow(ctx);
|
663
|
+
|
664
|
+
if (this.active && !noTransform) {
|
665
|
+
this.drawBorders(ctx);
|
666
|
+
this.drawControls(ctx);
|
667
|
+
}
|
668
|
+
ctx.restore();
|
669
|
+
},
|
670
|
+
|
671
|
+
/**
|
672
|
+
* @private
|
673
|
+
* @method _setShadow
|
674
|
+
*/
|
675
|
+
_setShadow: function(ctx) {
|
676
|
+
if (!this.shadow) return;
|
677
|
+
|
678
|
+
ctx.shadowColor = this.shadow.color;
|
679
|
+
ctx.shadowBlur = this.shadow.blur;
|
680
|
+
ctx.shadowOffsetX = this.shadow.offsetX;
|
681
|
+
ctx.shadowOffsetY = this.shadow.offsetY;
|
682
|
+
},
|
683
|
+
|
684
|
+
/**
|
685
|
+
* @private
|
686
|
+
* @method _removeShadow
|
687
|
+
*/
|
688
|
+
_removeShadow: function(ctx) {
|
689
|
+
ctx.shadowColor = '';
|
690
|
+
ctx.shadowBlur = ctx.shadowOffsetX = ctx.shadowOffsetY = 0;
|
691
|
+
},
|
692
|
+
|
693
|
+
/**
|
694
|
+
* Clones an instance
|
695
|
+
* @method clone
|
696
|
+
* @param {Function} callback Callback is invoked with a clone as a first argument
|
697
|
+
* @param {Array} propertiesToInclude
|
698
|
+
* @return {fabric.Object} clone of an instance
|
699
|
+
*/
|
700
|
+
clone: function(callback, propertiesToInclude) {
|
701
|
+
if (this.constructor.fromObject) {
|
702
|
+
return this.constructor.fromObject(this.toObject(propertiesToInclude), callback);
|
703
|
+
}
|
704
|
+
return new fabric.Object(this.toObject(propertiesToInclude));
|
705
|
+
},
|
706
|
+
|
707
|
+
/**
|
708
|
+
* Creates an instance of fabric.Image out of an object
|
709
|
+
* @method cloneAsImage
|
710
|
+
* @param callback {Function} callback, invoked with an instance as a first argument
|
711
|
+
* @return {fabric.Object} thisArg
|
712
|
+
* @chainable
|
713
|
+
*/
|
714
|
+
cloneAsImage: function(callback) {
|
715
|
+
if (fabric.Image) {
|
716
|
+
var i = new Image();
|
717
|
+
|
718
|
+
/** @ignore */
|
719
|
+
i.onload = function() {
|
720
|
+
if (callback) {
|
721
|
+
callback(new fabric.Image(i), orig);
|
722
|
+
}
|
723
|
+
i = i.onload = null;
|
724
|
+
};
|
725
|
+
|
726
|
+
var orig = {
|
727
|
+
angle: this.get('angle'),
|
728
|
+
flipX: this.get('flipX'),
|
729
|
+
flipY: this.get('flipY')
|
730
|
+
};
|
731
|
+
|
732
|
+
// normalize angle
|
733
|
+
this.set('angle', 0).set('flipX', false).set('flipY', false);
|
734
|
+
this.toDataURL(function(dataURL) {
|
735
|
+
i.src = dataURL;
|
736
|
+
});
|
737
|
+
}
|
738
|
+
return this;
|
739
|
+
},
|
740
|
+
|
741
|
+
/**
|
742
|
+
* Converts an object into a data-url-like string
|
743
|
+
* @method toDataURL
|
744
|
+
* @param callback {Function} callback that recieves resulting data-url string
|
745
|
+
*/
|
746
|
+
toDataURL: function(callback) {
|
747
|
+
var el = fabric.util.createCanvasElement();
|
748
|
+
|
749
|
+
el.width = this.getBoundingRectWidth();
|
750
|
+
el.height = this.getBoundingRectHeight();
|
751
|
+
|
752
|
+
fabric.util.wrapElement(el, 'div');
|
753
|
+
|
754
|
+
var canvas = new fabric.Canvas(el);
|
755
|
+
canvas.backgroundColor = 'transparent';
|
756
|
+
canvas.renderAll();
|
757
|
+
|
758
|
+
if (this.constructor.async) {
|
759
|
+
this.clone(proceed);
|
760
|
+
}
|
761
|
+
else {
|
762
|
+
proceed(this.clone());
|
763
|
+
}
|
764
|
+
|
765
|
+
function proceed(clone) {
|
766
|
+
clone.left = el.width / 2;
|
767
|
+
clone.top = el.height / 2;
|
768
|
+
|
769
|
+
clone.setActive(false);
|
770
|
+
|
771
|
+
canvas.add(clone);
|
772
|
+
var data = canvas.toDataURL('png');
|
773
|
+
|
774
|
+
canvas.dispose();
|
775
|
+
canvas = clone = null;
|
776
|
+
|
777
|
+
callback && callback(data);
|
778
|
+
}
|
779
|
+
},
|
780
|
+
|
781
|
+
/**
|
782
|
+
* Returns true if object state (one of its state properties) was changed
|
783
|
+
* @method hasStateChanged
|
784
|
+
* @return {Boolean} true if instance' state has changed
|
785
|
+
*/
|
786
|
+
hasStateChanged: function() {
|
787
|
+
return this.stateProperties.some(function(prop) {
|
788
|
+
return this[prop] !== this.originalState[prop];
|
789
|
+
}, this);
|
790
|
+
},
|
791
|
+
|
792
|
+
/**
|
793
|
+
* Saves state of an object
|
794
|
+
* @method saveState
|
795
|
+
* @return {fabric.Object} thisArg
|
796
|
+
* @chainable
|
797
|
+
*/
|
798
|
+
saveState: function() {
|
799
|
+
this.stateProperties.forEach(function(prop) {
|
800
|
+
this.originalState[prop] = this.get(prop);
|
801
|
+
}, this);
|
802
|
+
return this;
|
803
|
+
},
|
804
|
+
|
805
|
+
/**
|
806
|
+
* Setups state of an object
|
807
|
+
* @method setupState
|
808
|
+
*/
|
809
|
+
setupState: function() {
|
810
|
+
this.originalState = { };
|
811
|
+
this.saveState();
|
812
|
+
},
|
813
|
+
|
814
|
+
/**
|
815
|
+
* Returns true if specified type is identical to the type of an instance
|
816
|
+
* @method isType
|
817
|
+
* @param type {String} type to check against
|
818
|
+
* @return {Boolean}
|
819
|
+
*/
|
820
|
+
isType: function(type) {
|
821
|
+
return this.type === type;
|
822
|
+
},
|
823
|
+
|
824
|
+
/**
|
825
|
+
* Makes object's color grayscale
|
826
|
+
* @method toGrayscale
|
827
|
+
* @return {fabric.Object} thisArg
|
828
|
+
*/
|
829
|
+
toGrayscale: function() {
|
830
|
+
var fillValue = this.get('fill');
|
831
|
+
if (fillValue) {
|
832
|
+
this.set('overlayFill', new fabric.Color(fillValue).toGrayscale().toRgb());
|
833
|
+
}
|
834
|
+
return this;
|
835
|
+
},
|
836
|
+
|
837
|
+
/**
|
838
|
+
* Returns complexity of an instance
|
839
|
+
* @method complexity
|
840
|
+
* @return {Number} complexity
|
841
|
+
*/
|
842
|
+
complexity: function() {
|
843
|
+
return 0;
|
844
|
+
},
|
845
|
+
|
846
|
+
/**
|
847
|
+
* Returns a JSON representation of an instance
|
848
|
+
* @method toJSON
|
849
|
+
* @param {Array} propertiesToInclude
|
850
|
+
* @return {String} json
|
851
|
+
*/
|
852
|
+
toJSON: function(propertiesToInclude) {
|
853
|
+
// delegate, not alias
|
854
|
+
return this.toObject(propertiesToInclude);
|
855
|
+
},
|
856
|
+
|
857
|
+
/**
|
858
|
+
* Sets gradient fill of an object
|
859
|
+
* @method setGradientFill
|
860
|
+
*/
|
861
|
+
setGradientFill: function(options) {
|
862
|
+
this.set('fill', fabric.Gradient.forObject(this, options));
|
863
|
+
},
|
864
|
+
|
865
|
+
/**
|
866
|
+
* Sets pattern fill of an object
|
867
|
+
* @method setPatternFill
|
868
|
+
*/
|
869
|
+
setPatternFill: function(options) {
|
870
|
+
this.set('fill', new fabric.Pattern(options));
|
871
|
+
},
|
872
|
+
|
873
|
+
/**
|
874
|
+
* Sets shadow of an object
|
875
|
+
* @method setShadow
|
876
|
+
*/
|
877
|
+
setShadow: function(options) {
|
878
|
+
this.set('shadow', new fabric.Shadow(options));
|
879
|
+
},
|
880
|
+
|
881
|
+
/**
|
882
|
+
* Animates object's properties
|
883
|
+
* @method animate
|
884
|
+
*
|
885
|
+
* As object — multiple properties
|
886
|
+
*
|
887
|
+
* object.animate({ left: ..., top: ... });
|
888
|
+
* object.animate({ left: ..., top: ... }, { duration: ... });
|
889
|
+
*
|
890
|
+
* As string — one property
|
891
|
+
*
|
892
|
+
* object.animate('left', ...);
|
893
|
+
* object.animate('left', { duration: ... });
|
894
|
+
*
|
895
|
+
*/
|
896
|
+
animate: function() {
|
897
|
+
if (arguments[0] && typeof arguments[0] === 'object') {
|
898
|
+
for (var prop in arguments[0]) {
|
899
|
+
this._animate(prop, arguments[0][prop], arguments[1]);
|
900
|
+
}
|
901
|
+
}
|
902
|
+
else {
|
903
|
+
this._animate.apply(this, arguments);
|
904
|
+
}
|
905
|
+
return this;
|
906
|
+
},
|
907
|
+
|
908
|
+
/**
|
909
|
+
* @private
|
910
|
+
* @method _animate
|
911
|
+
*/
|
912
|
+
_animate: function(property, to, options) {
|
913
|
+
var obj = this, propPair;
|
914
|
+
|
915
|
+
to = to.toString();
|
916
|
+
|
917
|
+
if (!options) {
|
918
|
+
options = { };
|
919
|
+
}
|
920
|
+
else {
|
921
|
+
options = fabric.util.object.clone(options);
|
922
|
+
}
|
923
|
+
|
924
|
+
if (~property.indexOf('.')) {
|
925
|
+
propPair = property.split('.');
|
926
|
+
}
|
927
|
+
|
928
|
+
var currentValue = propPair
|
929
|
+
? this.get(propPair[0])[propPair[1]]
|
930
|
+
: this.get(property);
|
931
|
+
|
932
|
+
if (!('from' in options)) {
|
933
|
+
options.from = currentValue;
|
934
|
+
}
|
935
|
+
|
936
|
+
if (~to.indexOf('=')) {
|
937
|
+
to = currentValue + parseFloat(to.replace('=', ''));
|
938
|
+
}
|
939
|
+
else {
|
940
|
+
to = parseFloat(to);
|
941
|
+
}
|
942
|
+
|
943
|
+
fabric.util.animate({
|
944
|
+
startValue: options.from,
|
945
|
+
endValue: to,
|
946
|
+
byValue: options.by,
|
947
|
+
easing: options.easing,
|
948
|
+
duration: options.duration,
|
949
|
+
onChange: function(value) {
|
950
|
+
if (propPair) {
|
951
|
+
obj[propPair[0]][propPair[1]] = value;
|
952
|
+
}
|
953
|
+
else {
|
954
|
+
obj.set(property, value);
|
955
|
+
}
|
956
|
+
options.onChange && options.onChange();
|
957
|
+
},
|
958
|
+
onComplete: function() {
|
959
|
+
obj.setCoords();
|
960
|
+
options.onComplete && options.onComplete();
|
961
|
+
}
|
962
|
+
});
|
963
|
+
},
|
964
|
+
|
965
|
+
/**
|
966
|
+
* Centers object horizontally on canvas to which it was added last
|
967
|
+
* @method centerH
|
968
|
+
* @return {fabric.Object} thisArg
|
969
|
+
*/
|
970
|
+
centerH: function () {
|
971
|
+
this.canvas.centerObjectH(this);
|
972
|
+
return this;
|
973
|
+
},
|
974
|
+
|
975
|
+
/**
|
976
|
+
* Centers object vertically on canvas to which it was added last
|
977
|
+
* @method centerV
|
978
|
+
* @return {fabric.Object} thisArg
|
979
|
+
* @chainable
|
980
|
+
*/
|
981
|
+
centerV: function () {
|
982
|
+
this.canvas.centerObjectV(this);
|
983
|
+
return this;
|
984
|
+
},
|
985
|
+
|
986
|
+
/**
|
987
|
+
* Centers object vertically and horizontally on canvas to which is was added last
|
988
|
+
* @method center
|
989
|
+
* @return {fabric.Object} thisArg
|
990
|
+
* @chainable
|
991
|
+
*/
|
992
|
+
center: function () {
|
993
|
+
return this.centerH().centerV();
|
994
|
+
},
|
995
|
+
|
996
|
+
/**
|
997
|
+
* Removes object from canvas to which it was added last
|
998
|
+
* @method remove
|
999
|
+
* @return {fabric.Object} thisArg
|
1000
|
+
* @chainable
|
1001
|
+
*/
|
1002
|
+
remove: function() {
|
1003
|
+
return this.canvas.remove(this);
|
1004
|
+
},
|
1005
|
+
|
1006
|
+
/**
|
1007
|
+
* Moves an object to the bottom of the stack of drawn objects
|
1008
|
+
* @method sendToBack
|
1009
|
+
* @return {fabric.Object} thisArg
|
1010
|
+
* @chainable
|
1011
|
+
*/
|
1012
|
+
sendToBack: function() {
|
1013
|
+
this.canvas.sendToBack(this);
|
1014
|
+
return this;
|
1015
|
+
},
|
1016
|
+
|
1017
|
+
/**
|
1018
|
+
* Moves an object to the top of the stack of drawn objects
|
1019
|
+
* @method bringToFront
|
1020
|
+
* @return {fabric.Object} thisArg
|
1021
|
+
* @chainable
|
1022
|
+
*/
|
1023
|
+
bringToFront: function() {
|
1024
|
+
this.canvas.bringToFront(this);
|
1025
|
+
return this;
|
1026
|
+
},
|
1027
|
+
|
1028
|
+
/**
|
1029
|
+
* Moves an object one level down in stack of drawn objects
|
1030
|
+
* @method sendBackwards
|
1031
|
+
* @return {fabric.Object} thisArg
|
1032
|
+
* @chainable
|
1033
|
+
*/
|
1034
|
+
sendBackwards: function() {
|
1035
|
+
this.canvas.sendBackwards(this);
|
1036
|
+
return this;
|
1037
|
+
},
|
1038
|
+
|
1039
|
+
/**
|
1040
|
+
* Moves an object one level up in stack of drawn objects
|
1041
|
+
* @method bringForward
|
1042
|
+
* @return {fabric.Object} thisArg
|
1043
|
+
* @chainable
|
1044
|
+
*/
|
1045
|
+
bringForward: function() {
|
1046
|
+
this.canvas.bringForward(this);
|
1047
|
+
return this;
|
1048
|
+
}
|
1049
|
+
});
|
1050
|
+
|
1051
|
+
fabric.util.createAccessors(fabric.Object);
|
1052
|
+
|
1053
|
+
/**
|
1054
|
+
* Alias for {@link fabric.Object.prototype.setAngle}
|
1055
|
+
* @alias rotate -> setAngle
|
1056
|
+
*/
|
1057
|
+
fabric.Object.prototype.rotate = fabric.Object.prototype.setAngle;
|
1058
|
+
|
1059
|
+
extend(fabric.Object.prototype, fabric.Observable);
|
1060
|
+
|
1061
|
+
/**
|
1062
|
+
* @static
|
1063
|
+
* @constant
|
1064
|
+
* @type Number
|
1065
|
+
*/
|
1066
|
+
fabric.Object.NUM_FRACTION_DIGITS = 2;
|
1067
|
+
|
1068
|
+
})(typeof exports !== 'undefined' ? exports : this);
|