mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-05-13 00:03:10 +00:00
[BACK_INCOMPAT] fabric.StaticCanvas#backgroundImage and fabric.StaticCanvas#overlayImage are fabric.Image instances. fabric.StaticCanvas#backgroundImageOpacity, fabric.StaticCanvas#backgroundImageStretch, fabric.StaticCanvas#overlayImageLeft and fabric.StaticCanvas#overlayImageTop were removed.
`backgroundImage` and `overlayImage` are now `fabric.Image` instances New property `overlayColor` (analog to `backgroundColor`) - should be set with `canvas.setOverlayColor` `backgroundImageOpacity` was removed => use `fabric.Image#opacity` `overlayImageLeft ` was removed => use `fabric.Image#left` `overlayImageTop ` was removed => use `fabric.Image#top` `backgroundImageStretch` was removed => use `fabric.Image#width` and `fabric.Image#height`. If you scale your canvas you have to adjust the backgroundImage width/height manually. Update SVG output. Add 2nd parameter `firstLetterOnly` to `fabric.util.string.capitalize` => only first letter is transformed to uppercase (other letters stay untouched) Add `preserveAspectRatio="none"` to `fabric.Image#toSVG` (otherwise streched backgroundImage and overlayImage didn't work as expected) Update examples - TODO: Update jsfiddles for `setBackgroundImage` and `setOverlayImage` Add unit test Closes issue #270
This commit is contained in:
parent
3c30eb041a
commit
5017bc6626
8 changed files with 536 additions and 291 deletions
|
|
@ -1,5 +1,7 @@
|
|||
**Edge**
|
||||
|
||||
- [BACK_INCOMPAT] `fabric.StaticCanvas#backgroundImage` and `fabric.StaticCanvas#overlayImage` are `fabric.Image` instances. `fabric.StaticCanvas#backgroundImageOpacity`, `fabric.StaticCanvas#backgroundImageStretch`, `fabric.StaticCanvas#overlayImageLeft` and `fabric.StaticCanvas#overlayImageTop` were removed.
|
||||
|
||||
- [BACK_INCOMPAT] `fabric.Text#backgroundColor` is now `fabric.Object#backgroundColor`
|
||||
|
||||
- [BACK_INCOMPAT] Remove `fabric.Object#toGrayscale` and `fabric.Object#overlayFill` since they're too specific
|
||||
|
|
|
|||
|
|
@ -50,72 +50,74 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
|
|||
|
||||
var _this = this;
|
||||
this._enlivenObjects(serialized.objects, function () {
|
||||
_this._setBgOverlayImages(serialized, callback);
|
||||
_this._setBgOverlay(serialized, callback);
|
||||
}, reviver);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_setBgOverlayImages: function(serialized, callback) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} serialized Object with background and overlay information
|
||||
* @param {Function} callback Invoked after all background and overlay images/patterns loaded
|
||||
*/
|
||||
_setBgOverlay: function(serialized, callback) {
|
||||
var _this = this,
|
||||
backgroundPatternLoaded,
|
||||
backgroundImageLoaded,
|
||||
overlayImageLoaded;
|
||||
loaded = {
|
||||
backgroundColor: false,
|
||||
overlayColor: false,
|
||||
backgroundImage: false,
|
||||
overlayImage: false
|
||||
};
|
||||
|
||||
if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background && !serialized.overlay) {
|
||||
callback && callback();
|
||||
return;
|
||||
}
|
||||
|
||||
var cbIfLoaded = function () {
|
||||
callback && backgroundImageLoaded && overlayImageLoaded && backgroundPatternLoaded && callback();
|
||||
if (loaded.backgroundImage && loaded.overlayImage && loaded.backgroundColor && loaded.overlayColor) {
|
||||
_this.renderAll();
|
||||
callback && callback();
|
||||
}
|
||||
};
|
||||
|
||||
if (serialized.backgroundImage) {
|
||||
this.setBackgroundImage(serialized.backgroundImage, function() {
|
||||
this.__setBgOverlay('backgroundImage', serialized.backgroundImage, loaded, cbIfLoaded);
|
||||
this.__setBgOverlay('overlayImage', serialized.overlayImage, loaded, cbIfLoaded);
|
||||
this.__setBgOverlay('backgroundColor', serialized.background, loaded, cbIfLoaded);
|
||||
this.__setBgOverlay('overlayColor', serialized.overlay, loaded, cbIfLoaded);
|
||||
|
||||
_this.backgroundImageOpacity = serialized.backgroundImageOpacity;
|
||||
_this.backgroundImageStretch = serialized.backgroundImageStretch;
|
||||
cbIfLoaded();
|
||||
},
|
||||
|
||||
_this.renderAll();
|
||||
/**
|
||||
* @private
|
||||
* @param {String} property Property to set (backgroundImage, overlayImage, backgroundColor, overlayColor)
|
||||
* @param {(Object|String)} value Value to set
|
||||
* @param {Object} loaded Set loaded property to true if property is set
|
||||
* @param {Object} callback Callback function to invoke after property is set
|
||||
*/
|
||||
__setBgOverlay: function(property, value, loaded, callback) {
|
||||
var _this = this;
|
||||
|
||||
backgroundImageLoaded = true;
|
||||
if (!value) {
|
||||
loaded[property] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
cbIfLoaded();
|
||||
if (property === 'backgroundImage' || property === 'overlayImage') {
|
||||
fabric.Image.fromObject(value, function(img) {
|
||||
_this[property] = img;
|
||||
loaded[property] = true;
|
||||
callback && callback();
|
||||
});
|
||||
}
|
||||
else {
|
||||
backgroundImageLoaded = true;
|
||||
}
|
||||
|
||||
if (serialized.overlayImage) {
|
||||
this.setOverlayImage(serialized.overlayImage, function() {
|
||||
|
||||
_this.overlayImageLeft = serialized.overlayImageLeft || 0;
|
||||
_this.overlayImageTop = serialized.overlayImageTop || 0;
|
||||
|
||||
_this.renderAll();
|
||||
overlayImageLoaded = true;
|
||||
|
||||
cbIfLoaded();
|
||||
this['set' + fabric.util.string.capitalize(property, true)](value, function() {
|
||||
loaded[property] = true;
|
||||
callback && callback();
|
||||
});
|
||||
}
|
||||
else {
|
||||
overlayImageLoaded = true;
|
||||
}
|
||||
|
||||
if (serialized.background) {
|
||||
this.setBackgroundColor(serialized.background, function() {
|
||||
|
||||
_this.renderAll();
|
||||
backgroundPatternLoaded = true;
|
||||
|
||||
cbIfLoaded();
|
||||
});
|
||||
}
|
||||
else {
|
||||
backgroundPatternLoaded = true;
|
||||
}
|
||||
|
||||
if (!serialized.backgroundImage && !serialized.overlayImage && !serialized.background) {
|
||||
callback && callback();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -805,23 +805,31 @@
|
|||
* @return {String}
|
||||
*/
|
||||
function createSVGRefElementsMarkup(canvas) {
|
||||
var markup = '';
|
||||
var markup = [ ];
|
||||
|
||||
if (canvas.backgroundColor && canvas.backgroundColor.source) {
|
||||
markup = [
|
||||
'<pattern x="0" y="0" id="backgroundColorPattern" ',
|
||||
'width="', canvas.backgroundColor.source.width,
|
||||
'" height="', canvas.backgroundColor.source.height,
|
||||
_createSVGPattern(markup, canvas, 'backgroundColor');
|
||||
_createSVGPattern(markup, canvas, 'overlayColor');
|
||||
|
||||
return markup.join('');
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
function _createSVGPattern(markup, canvas, property) {
|
||||
if (canvas[property] && canvas[property].toSVG) {
|
||||
markup.push(
|
||||
'<pattern x="0" y="0" id="', property, 'Pattern" ',
|
||||
'width="', canvas[property].source.width,
|
||||
'" height="', canvas[property].source.height,
|
||||
'" patternUnits="userSpaceOnUse">',
|
||||
'<image x="0" y="0" ',
|
||||
'width="', canvas.backgroundColor.source.width,
|
||||
'" height="', canvas.backgroundColor.source.height,
|
||||
'" xlink:href="', canvas.backgroundColor.source.src,
|
||||
'width="', canvas[property].source.width,
|
||||
'" height="', canvas[property].source.height,
|
||||
'" xlink:href="', canvas[property].source.src,
|
||||
'"></image></pattern>'
|
||||
].join('');
|
||||
);
|
||||
}
|
||||
|
||||
return markup;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@
|
|||
'" transform="translate(' + (-this.width/2) + ' ' + (-this.height/2) + ')',
|
||||
'" width="', this.width,
|
||||
'" height="', this.height,
|
||||
'" preserveAspectRatio="none"',
|
||||
'"></image>'
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -44,56 +44,41 @@
|
|||
},
|
||||
|
||||
/**
|
||||
* Background color of canvas instance
|
||||
* @type String
|
||||
* Background color of canvas instance.
|
||||
* Should be set via {@link fabric.StaticCanvas#setBackgroundColor}.
|
||||
* @type {(String|fabric.Pattern)}
|
||||
* @default
|
||||
*/
|
||||
backgroundColor: '',
|
||||
|
||||
/**
|
||||
* Background image of canvas instance
|
||||
* Should be set via {@link fabric.StaticCanvas#setBackgroundImage}
|
||||
* @type String
|
||||
* Background image of canvas instance.
|
||||
* Should be set via {@link fabric.StaticCanvas#setBackgroundImage}.
|
||||
* <b>Backwards incompatibility note:</b> The "backgroundImageOpacity" and "backgroundImageStretch" properties are deprecated since 1.3.9.
|
||||
* Use {@link fabric.Image#opacity}, {@link fabric.Image#width} and {@link fabric.Image#height}.
|
||||
* @type fabric.Image
|
||||
* @default
|
||||
*/
|
||||
backgroundImage: '',
|
||||
backgroundImage: null,
|
||||
|
||||
/**
|
||||
* Opacity of the background image of the canvas instance
|
||||
* @type Float
|
||||
* Overlay color of canvas instance.
|
||||
* Should be set via {@link fabric.StaticCanvas#setOverlayColor}
|
||||
* @since 1.3.9
|
||||
* @type {(String|fabric.Pattern)}
|
||||
* @default
|
||||
*/
|
||||
backgroundImageOpacity: 1,
|
||||
overlayColor: '',
|
||||
|
||||
/**
|
||||
* Indicates whether the background image should be stretched to fit the
|
||||
* dimensions of the canvas instance.
|
||||
* @type Boolean
|
||||
* Overlay image of canvas instance.
|
||||
* Should be set via {@link fabric.StaticCanvas#setOverlayImage}.
|
||||
* <b>Backwards incompatibility note:</b> The "overlayImageLeft" and "overlayImageTop" properties are deprecated since 1.3.9.
|
||||
* Use {@link fabric.Image#left} and {@link fabric.Image#top}.
|
||||
* @type fabric.Image
|
||||
* @default
|
||||
*/
|
||||
backgroundImageStretch: true,
|
||||
|
||||
/**
|
||||
* Overlay image of canvas instance
|
||||
* Should be set via {@link fabric.StaticCanvas#setOverlayImage}
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
overlayImage: '',
|
||||
|
||||
/**
|
||||
* Left offset of overlay image (if present)
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
overlayImageLeft: 0,
|
||||
|
||||
/**
|
||||
* Top offset of overlay image (if present)
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
overlayImageTop: 0,
|
||||
overlayImage: null,
|
||||
|
||||
/**
|
||||
* Indicates whether toObject/toDatalessObject should include default values
|
||||
|
|
@ -168,6 +153,9 @@
|
|||
if (options.backgroundColor) {
|
||||
this.setBackgroundColor(options.backgroundColor, this.renderAll.bind(this));
|
||||
}
|
||||
if (options.overlayColor) {
|
||||
this.setOverlayColor(options.overlayColor, this.renderAll.bind(this));
|
||||
}
|
||||
this.calcOffset();
|
||||
},
|
||||
|
||||
|
|
@ -184,74 +172,115 @@
|
|||
|
||||
/**
|
||||
* Sets {@link fabric.StaticCanvas#overlayImage|overlay image} for this canvas
|
||||
* @param {String} url url of an image to set overlay to
|
||||
* @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set overlay to
|
||||
* @param {Function} callback callback to invoke when image is loaded and set as an overlay
|
||||
* @param {Object} [options] Optional options to set for the overlay image
|
||||
* @param {Number} [options.overlayImageLeft] {@link fabric.StaticCanvas#overlayImageLeft|Left offset} of overlay image
|
||||
* @param {Number} [options.overlayImageTop] {@link fabric.StaticCanvas#overlayImageTop|Top offset} of overlay image
|
||||
* @param {Object} [options] Optional options to set for the {@link fabric.Image|overlay image}.
|
||||
* @return {fabric.Canvas} thisArg
|
||||
* @chainable
|
||||
* @see {@link http://jsfiddle.net/fabricjs/MnzHT/|jsFiddle demo}
|
||||
* @example <caption>Normal overlayImage</caption>
|
||||
* canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas));
|
||||
* @example <caption>Displaced overlayImage (left and top != 0)</caption>
|
||||
* @example <caption>Normal overlayImage with left/top = 0</caption>
|
||||
* canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {
|
||||
* overlayImageLeft: 100,
|
||||
* overlayImageTop: 100
|
||||
* // Needed to position overlayImage at 0/0
|
||||
* originX: 'left',
|
||||
* originY: 'top'
|
||||
* });
|
||||
* @example <caption>overlayImage with different properties</caption>
|
||||
* canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {
|
||||
* opacity: 0.5,
|
||||
* angle: 45,
|
||||
* left: 400,
|
||||
* top: 400,
|
||||
* originX: 'left',
|
||||
* originY: 'top'
|
||||
* });
|
||||
* @example <caption>Stretched overlayImage #1 - width/height correspond to canvas width/height</caption>
|
||||
* fabric.Image.fromURL('http://fabricjs.com/assets/jail_cell_bars.png', function(img) {
|
||||
* img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'});
|
||||
* canvas.setOverlayImage(img, canvas.renderAll.bind(canvas));
|
||||
* });
|
||||
* @example <caption>Stretched overlayImage #2 - width/height correspond to canvas width/height</caption>
|
||||
* canvas.setOverlayImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {
|
||||
* width: canvas.width,
|
||||
* height: canvas.height,
|
||||
* // Needed to position overlayImage at 0/0
|
||||
* originX: 'left',
|
||||
* originY: 'top'
|
||||
* });
|
||||
*/
|
||||
setOverlayImage: function (url, callback, options) { // TODO (kangax): test callback
|
||||
fabric.util.loadImage(url, function(img) {
|
||||
this.overlayImage = img;
|
||||
if (options && ('overlayImageLeft' in options)) {
|
||||
this.overlayImageLeft = options.overlayImageLeft;
|
||||
}
|
||||
if (options && ('overlayImageTop' in options)) {
|
||||
this.overlayImageTop = options.overlayImageTop;
|
||||
}
|
||||
callback && callback();
|
||||
}, this);
|
||||
|
||||
return this;
|
||||
setOverlayImage: function (image, callback, options) {
|
||||
return this.__setBgOverlayImage('overlayImage', image, callback, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets {@link fabric.StaticCanvas#backgroundImage|background image} for this canvas
|
||||
* @param {String} url URL of an image to set background to
|
||||
* @param {Function} callback callback to invoke when image is loaded and set as background
|
||||
* @param {Object} [options] Optional options to set for the background image
|
||||
* @param {Float} [options.backgroundImageOpacity] {@link fabric.StaticCanvas#backgroundImageOpacity|Opacity} of the background image of the canvas instance
|
||||
* @param {Boolean} [options.backgroundImageStretch] Indicates whether the background image should be {@link fabric.StaticCanvas#backgroundImageStretch|strechted} to fit the canvas
|
||||
* @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set background to
|
||||
* @param {Function} callback Callback to invoke when image is loaded and set as background
|
||||
* @param {Object} [options] Optional options to set for the {@link fabric.Image|background image}.
|
||||
* @return {fabric.Canvas} thisArg
|
||||
* @chainable
|
||||
* @see {@link http://jsfiddle.net/fabricjs/YH9yD/|jsFiddle demo}
|
||||
* @example <caption>Normal backgroundImage</caption>
|
||||
* canvas.setBackgroundImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas));
|
||||
* @example <caption>Stretched backgroundImage with opacity</caption>
|
||||
* canvas.setBackgroundImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas), {
|
||||
* backgroundImageOpacity: 0.5,
|
||||
* backgroundImageStretch: true
|
||||
* @example <caption>Normal backgroundImage with left/top = 0</caption>
|
||||
* canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {
|
||||
* // Needed to position backgroundImage at 0/0
|
||||
* originX: 'left',
|
||||
* originY: 'top'
|
||||
* });
|
||||
* @example <caption>backgroundImage with different properties</caption>
|
||||
* canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {
|
||||
* opacity: 0.5,
|
||||
* angle: 45,
|
||||
* left: 400,
|
||||
* top: 400,
|
||||
* originX: 'left',
|
||||
* originY: 'top'
|
||||
* });
|
||||
* @example <caption>Stretched backgroundImage #1 - width/height correspond to canvas width/height</caption>
|
||||
* fabric.Image.fromURL('http://fabricjs.com/assets/honey_im_subtle.png', function(img) {
|
||||
* img.set({width: canvas.width, height: canvas.height, originX: 'left', originY: 'top'});
|
||||
* canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas));
|
||||
* });
|
||||
* @example <caption>Stretched backgroundImage #2 - width/height correspond to canvas width/height</caption>
|
||||
* canvas.setBackgroundImage('http://fabricjs.com/assets/honey_im_subtle.png', canvas.renderAll.bind(canvas), {
|
||||
* width: canvas.width,
|
||||
* height: canvas.height,
|
||||
* // Needed to position backgroundImage at 0/0
|
||||
* originX: 'left',
|
||||
* originY: 'top'
|
||||
* });
|
||||
*/
|
||||
setBackgroundImage: function (url, callback, options) {
|
||||
fabric.util.loadImage(url, function(img) {
|
||||
this.backgroundImage = img;
|
||||
if (options && ('backgroundImageOpacity' in options)) {
|
||||
this.backgroundImageOpacity = options.backgroundImageOpacity;
|
||||
}
|
||||
if (options && ('backgroundImageStretch' in options)) {
|
||||
this.backgroundImageStretch = options.backgroundImageStretch;
|
||||
}
|
||||
callback && callback();
|
||||
}, this);
|
||||
setBackgroundImage: function (image, callback, options) {
|
||||
return this.__setBgOverlayImage('backgroundImage', image, callback, options);
|
||||
},
|
||||
|
||||
return this;
|
||||
/**
|
||||
* Sets {@link fabric.StaticCanvas#overlayColor|background color} for this canvas
|
||||
* @param {(String|fabric.Pattern)} overlayColor Color or pattern to set background color to
|
||||
* @param {Function} callback Callback to invoke when background color is set
|
||||
* @return {fabric.Canvas} thisArg
|
||||
* @chainable
|
||||
* @see {@link http://jsfiddle.net/fabricjs/pB55h/|jsFiddle demo}
|
||||
* @example <caption>Normal overlayColor - color value</caption>
|
||||
* canvas.setOverlayColor('rgba(255, 73, 64, 0.6)', canvas.renderAll.bind(canvas));
|
||||
* @example <caption>fabric.Pattern used as overlayColor</caption>
|
||||
* canvas.setOverlayColor({
|
||||
* source: 'http://fabricjs.com/assets/escheresque_ste.png'
|
||||
* }, canvas.renderAll.bind(canvas));
|
||||
* @example <caption>fabric.Pattern used as overlayColor with repeat and offset</caption>
|
||||
* canvas.setOverlayColor({
|
||||
* source: 'http://fabricjs.com/assets/escheresque_ste.png',
|
||||
* repeat: 'repeat',
|
||||
* offsetX: 200,
|
||||
* offsetY: 100
|
||||
* }, canvas.renderAll.bind(canvas));
|
||||
*/
|
||||
setOverlayColor: function(overlayColor, callback) {
|
||||
return this.__setBgOverlayColor('overlayColor', overlayColor, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets {@link fabric.StaticCanvas#backgroundColor|background color} for this canvas
|
||||
* @param {String|fabric.Pattern} backgroundColor Color or pattern to set background color to
|
||||
* @param {Function} callback callback to invoke when background color is set
|
||||
* @param {(String|fabric.Pattern)} backgroundColor Color or pattern to set background color to
|
||||
* @param {Function} callback Callback to invoke when background color is set
|
||||
* @return {fabric.Canvas} thisArg
|
||||
* @chainable
|
||||
* @see {@link http://jsfiddle.net/fabricjs/hXzvk/|jsFiddle demo}
|
||||
|
|
@ -261,20 +290,61 @@
|
|||
* canvas.setBackgroundColor({
|
||||
* source: 'http://fabricjs.com/assets/escheresque_ste.png'
|
||||
* }, canvas.renderAll.bind(canvas));
|
||||
* @example <caption>fabric.Pattern used as backgroundColor with repeat and offset</caption>
|
||||
* canvas.setBackgroundColor({
|
||||
* source: 'http://fabricjs.com/assets/escheresque_ste.png',
|
||||
* repeat: 'repeat',
|
||||
* offsetX: 200,
|
||||
* offsetY: 100
|
||||
* }, canvas.renderAll.bind(canvas));
|
||||
*/
|
||||
setBackgroundColor: function(backgroundColor, callback) {
|
||||
if (backgroundColor.source) {
|
||||
return this.__setBgOverlayColor('backgroundColor', backgroundColor, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundImage|backgroundImage} or {@link fabric.StaticCanvas#overlayImage|overlayImage})
|
||||
* @param {(fabric.Image|String)} image fabric.Image instance or URL of an image to set background or overlay to
|
||||
* @param {Function} callback Callback to invoke when image is loaded and set as background or overlay
|
||||
* @param {Object} [options] Optional options to set for the {@link fabric.Image|image}.
|
||||
*/
|
||||
__setBgOverlayImage: function(property, image, callback, options) {
|
||||
if (typeof image === 'string') {
|
||||
fabric.util.loadImage(image, function(img) {
|
||||
this[property] = new fabric.Image(img, options);
|
||||
callback && callback();
|
||||
}, this);
|
||||
}
|
||||
else {
|
||||
this[property] = image;
|
||||
callback && callback();
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {String} property Property to set ({@link fabric.StaticCanvas#backgroundColor|backgroundColor} or {@link fabric.StaticCanvas#overlayColor|overlayColor})
|
||||
* @param {(Object|String)} color Object with pattern information or color value
|
||||
* @param {Function} [callback] Callback is invoked when color is set
|
||||
*/
|
||||
__setBgOverlayColor: function(property, color, callback) {
|
||||
if (color.source) {
|
||||
var _this = this;
|
||||
fabric.util.loadImage(backgroundColor.source, function(img) {
|
||||
_this.backgroundColor = new fabric.Pattern({
|
||||
fabric.util.loadImage(color.source, function(img) {
|
||||
_this[property] = new fabric.Pattern({
|
||||
source: img,
|
||||
repeat: backgroundColor.repeat
|
||||
repeat: color.repeat,
|
||||
offsetX: color.offsetX,
|
||||
offsetY: color.offsetY
|
||||
});
|
||||
callback && callback();
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.backgroundColor = backgroundColor;
|
||||
this[property] = color;
|
||||
callback && callback();
|
||||
}
|
||||
|
||||
|
|
@ -576,9 +646,7 @@
|
|||
canvasToDrawOn.restore();
|
||||
}
|
||||
|
||||
if (this.overlayImage) {
|
||||
canvasToDrawOn.drawImage(this.overlayImage, this.overlayImageLeft, this.overlayImageTop);
|
||||
}
|
||||
this._renderOverlay(canvasToDrawOn);
|
||||
|
||||
if (this.controlsAboveOverlay && this.interactive) {
|
||||
this.drawControls(canvasToDrawOn);
|
||||
|
|
@ -589,16 +657,26 @@
|
|||
return this;
|
||||
},
|
||||
|
||||
_renderObjects: function(canvasToDrawOn, activeGroup) {
|
||||
/**
|
||||
* @private
|
||||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
* @param {fabric.Group} activeGroup
|
||||
*/
|
||||
_renderObjects: function(ctx, activeGroup) {
|
||||
for (var i = 0, length = this._objects.length; i < length; ++i) {
|
||||
if (!activeGroup ||
|
||||
(activeGroup && this._objects[i] && !activeGroup.contains(this._objects[i]))) {
|
||||
this._draw(canvasToDrawOn, this._objects[i]);
|
||||
this._draw(ctx, this._objects[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_renderActiveGroup: function(canvasToDrawOn, activeGroup) {
|
||||
/**
|
||||
* @private
|
||||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
* @param {fabric.Group} activeGroup
|
||||
*/
|
||||
_renderActiveGroup: function(ctx, activeGroup) {
|
||||
|
||||
// delegate rendering to group selection (if one exists)
|
||||
if (activeGroup) {
|
||||
|
|
@ -611,42 +689,50 @@
|
|||
}
|
||||
});
|
||||
activeGroup._set('objects', sortedObjects);
|
||||
this._draw(canvasToDrawOn, activeGroup);
|
||||
}
|
||||
},
|
||||
|
||||
_renderBackground: function(canvasToDrawOn) {
|
||||
if (this.backgroundColor) {
|
||||
canvasToDrawOn.fillStyle = this.backgroundColor.toLive
|
||||
? this.backgroundColor.toLive(canvasToDrawOn)
|
||||
: this.backgroundColor;
|
||||
|
||||
canvasToDrawOn.fillRect(
|
||||
this.backgroundColor.offsetX || 0,
|
||||
this.backgroundColor.offsetY || 0,
|
||||
this.width,
|
||||
this.height);
|
||||
}
|
||||
if (typeof this.backgroundImage === 'object') {
|
||||
this._renderBackroundImage(canvasToDrawOn);
|
||||
this._draw(ctx, activeGroup);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {CanvasRenderingContext2D} canvasToDrawOn Context to render on
|
||||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
*/
|
||||
_renderBackroundImage: function(canvasToDrawOn) {
|
||||
canvasToDrawOn.save();
|
||||
canvasToDrawOn.globalAlpha = this.backgroundImageOpacity;
|
||||
_renderBackground: function(ctx) {
|
||||
if (this.backgroundColor) {
|
||||
ctx.fillStyle = this.backgroundColor.toLive
|
||||
? this.backgroundColor.toLive(ctx)
|
||||
: this.backgroundColor;
|
||||
|
||||
if (this.backgroundImageStretch) {
|
||||
canvasToDrawOn.drawImage(this.backgroundImage, 0, 0, this.width, this.height);
|
||||
ctx.fillRect(
|
||||
this.backgroundColor.offsetX || 0,
|
||||
this.backgroundColor.offsetY || 0,
|
||||
this.width,
|
||||
this.height);
|
||||
}
|
||||
else {
|
||||
canvasToDrawOn.drawImage(this.backgroundImage, 0, 0);
|
||||
if (this.backgroundImage) {
|
||||
this.backgroundImage.render(ctx);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
*/
|
||||
_renderOverlay: function(ctx) {
|
||||
if (this.overlayColor) {
|
||||
ctx.fillStyle = this.overlayColor.toLive
|
||||
? this.overlayColor.toLive(ctx)
|
||||
: this.overlayColor;
|
||||
|
||||
ctx.fillRect(
|
||||
this.overlayColor.offsetX || 0,
|
||||
this.overlayColor.offsetY || 0,
|
||||
this.width,
|
||||
this.height);
|
||||
}
|
||||
if (this.overlayImage) {
|
||||
this.overlayImage.render(ctx);
|
||||
}
|
||||
canvasToDrawOn.restore();
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -777,22 +863,13 @@
|
|||
instance.includeDefaultValues = originalValue;
|
||||
}
|
||||
return object;
|
||||
}, this),
|
||||
background: (this.backgroundColor && this.backgroundColor.toObject)
|
||||
? this.backgroundColor.toObject()
|
||||
: this.backgroundColor
|
||||
}, this)
|
||||
};
|
||||
if (this.backgroundImage) {
|
||||
data.backgroundImage = this.backgroundImage.src;
|
||||
data.backgroundImageOpacity = this.backgroundImageOpacity;
|
||||
data.backgroundImageStretch = this.backgroundImageStretch;
|
||||
}
|
||||
if (this.overlayImage) {
|
||||
data.overlayImage = this.overlayImage.src;
|
||||
data.overlayImageLeft = this.overlayImageLeft;
|
||||
data.overlayImageTop = this.overlayImageTop;
|
||||
}
|
||||
|
||||
extend(data, this.__serializeBgOverlay());
|
||||
|
||||
fabric.util.populateWithProperties(this, data, propertiesToInclude);
|
||||
|
||||
if (activeGroup) {
|
||||
this.setActiveGroup(new fabric.Group(activeGroup.getObjects()));
|
||||
activeGroup.forEachObject(function(o) { o.set('active', true) });
|
||||
|
|
@ -800,6 +877,31 @@
|
|||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
__serializeBgOverlay: function() {
|
||||
var data = {
|
||||
background: (this.backgroundColor && this.backgroundColor.toObject)
|
||||
? this.backgroundColor.toObject()
|
||||
: this.backgroundColor
|
||||
};
|
||||
|
||||
if (this.overlayColor) {
|
||||
data.overlay = this.overlayColor.toObject
|
||||
? this.overlayColor.toObject()
|
||||
: this.overlayColor;
|
||||
}
|
||||
if (this.backgroundImage) {
|
||||
data.backgroundImage = this.backgroundImage.toObject();
|
||||
}
|
||||
if (this.overlayImage) {
|
||||
data.overlayImage = this.overlayImage.toObject();
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
/* _TO_SVG_START_ */
|
||||
/**
|
||||
* Returns SVG representation of canvas
|
||||
|
|
@ -843,14 +945,23 @@
|
|||
|
||||
this._setSVGPreamble(markup, options);
|
||||
this._setSVGHeader(markup, options);
|
||||
this._setSVGBackgroundColor(markup);
|
||||
this._setSVGBackgroundImage(markup);
|
||||
this._setSVGOverlayImage(markup);
|
||||
|
||||
this._setSVGBgOverlayColor(markup, 'backgroundColor');
|
||||
this._setSVGBgOverlayImage(markup, 'backgroundImage');
|
||||
|
||||
this._setSVGObjects(markup, reviver);
|
||||
|
||||
this._setSVGBgOverlayColor(markup, 'overlayColor');
|
||||
this._setSVGBgOverlayImage(markup, 'overlayImage');
|
||||
|
||||
markup.push('</svg>');
|
||||
|
||||
return markup.join('');
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_setSVGPreamble: function(markup, options) {
|
||||
if (!options.suppressPreamble) {
|
||||
markup.push(
|
||||
|
|
@ -861,6 +972,9 @@
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_setSVGHeader: function(markup, options) {
|
||||
markup.push(
|
||||
'<svg ',
|
||||
|
|
@ -869,7 +983,7 @@
|
|||
'version="1.1" ',
|
||||
'width="', (options.viewBox ? options.viewBox.width : this.width), '" ',
|
||||
'height="', (options.viewBox ? options.viewBox.height : this.height), '" ',
|
||||
(this.backgroundColor && !this.backgroundColor.source
|
||||
(this.backgroundColor && !this.backgroundColor.toLive
|
||||
? 'style="background-color: ' + this.backgroundColor +'" '
|
||||
: null),
|
||||
(options.viewBox
|
||||
|
|
@ -888,45 +1002,9 @@
|
|||
);
|
||||
},
|
||||
|
||||
_setSVGBackgroundColor: function(markup) {
|
||||
if (this.backgroundColor && this.backgroundColor.source) {
|
||||
markup.push(
|
||||
'<rect x="0" y="0" ',
|
||||
'width="', (this.backgroundColor.repeat === 'repeat-y' || this.backgroundColor.repeat === 'no-repeat' ? this.backgroundColor.source.width : this.width),
|
||||
'" height="', (this.backgroundColor.repeat === 'repeat-x' || this.backgroundColor.repeat === 'no-repeat' ? this.backgroundColor.source.height : this.height),
|
||||
'" fill="url(#backgroundColorPattern)"',
|
||||
'></rect>'
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
_setSVGBackgroundImage: function(markup) {
|
||||
if (this.backgroundImage) {
|
||||
markup.push(
|
||||
'<image x="0" y="0" ',
|
||||
'width="', (this.backgroundImageStretch ? this.width : this.backgroundImage.width),
|
||||
'" height="', (this.backgroundImageStretch ? this.height : this.backgroundImage.height),
|
||||
'" preserveAspectRatio="', (this.backgroundImageStretch ? 'none' : 'defer'),
|
||||
'" xlink:href="', this.backgroundImage.src,
|
||||
'" style="opacity:', this.backgroundImageOpacity,
|
||||
'"></image>'
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
_setSVGOverlayImage: function(markup) {
|
||||
if (this.overlayImage) {
|
||||
markup.push(
|
||||
'<image x="', this.overlayImageLeft,
|
||||
'" y="', this.overlayImageTop,
|
||||
'" width="', this.overlayImage.width,
|
||||
'" height="', this.overlayImage.height,
|
||||
'" xlink:href="', this.overlayImage.src,
|
||||
'"></image>'
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_setSVGObjects: function(markup, reviver) {
|
||||
var activeGroup = this.getActiveGroup();
|
||||
if (activeGroup) {
|
||||
|
|
@ -941,7 +1019,39 @@
|
|||
o.set('active', true);
|
||||
});
|
||||
}
|
||||
markup.push('</svg>');
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_setSVGBgOverlayImage: function(markup, property) {
|
||||
if (this[property] && this[property].toSVG) {
|
||||
markup.push(this[property].toSVG());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_setSVGBgOverlayColor: function(markup, property) {
|
||||
if (this[property] && this[property].source) {
|
||||
markup.push(
|
||||
'<rect x="', this[property].offsetX, '" y="', this[property].offsetY, '" ',
|
||||
'width="', (this[property].repeat === 'repeat-y' || this[property].repeat === 'no-repeat' ? this[property].source.width : this.width),
|
||||
'" height="', (this[property].repeat === 'repeat-x' || this[property].repeat === 'no-repeat' ? this[property].source.height : this.height),
|
||||
'" fill="url(#' + property + 'Pattern)"',
|
||||
'></rect>'
|
||||
);
|
||||
}
|
||||
else if (this[property] && property === 'overlayColor') {
|
||||
markup.push(
|
||||
'<rect x="0" y="0" ',
|
||||
'width="', this.width,
|
||||
'" height="', this.height,
|
||||
'" fill="', this[property], '"',
|
||||
'></rect>'
|
||||
);
|
||||
}
|
||||
},
|
||||
/* _TO_SVG_END_ */
|
||||
|
||||
|
|
|
|||
|
|
@ -30,10 +30,12 @@ function camelize(string) {
|
|||
* Capitalizes a string
|
||||
* @memberOf fabric.util.string
|
||||
* @param {String} string String to capitalize
|
||||
* @param {Boolean} [firstLetterOnly] If true only first letter is capitalized and other letters stay untouched,
|
||||
* if false first letter is capitalized and other letters are converted to lowercase.
|
||||
* @return {String} Capitalized version of a string
|
||||
*/
|
||||
function capitalize(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
|
||||
function capitalize(string, firstLetterOnly) {
|
||||
return string.charAt(0).toUpperCase() + (firstLetterOnly ? string.slice(1) : string.slice(1).toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
' -3.56, 6.891, -7.481, 8.848], ["c", -4.689, 2.336, -9.084, -0.802, -11.277, -2.868], ["l",'+
|
||||
' -1.948, 3.104], ["l", -1.628, -1.333], ["l", 3.138, -4.689], ["c", 0.025, 0, 9, 1.932, 9, 1.932], '+
|
||||
'["c", 0.877, -9.979, 2.893, -12.905, 4.942, -15.621], ["C", 17.878, 21.775, 18.713, 17.397, 18.511, '+
|
||||
'13.99], ["z", null]]}], "background": "#ff5555"}';
|
||||
'13.99], ["z", null]]}], "background": "#ff5555","overlay": "rgba(0,0,0,0.2)"}';
|
||||
|
||||
var PATH_OBJ_JSON = '{"type": "path", "originX": "center", "originY": "center", "left": 268, "top": 266, "width": 51, "height": 49,'+
|
||||
' "fill": "rgb(0,0,0)", "stroke": null, "strokeWidth": 1, "scaleX": 1, "scaleY": 1, '+
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
var RECT_JSON = '{"objects":[{"type":"rect","originX":"center","originY":"center","left":0,"top":0,"width":10,"height":10,"fill":"rgb(0,0,0)",'+
|
||||
'"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,'+
|
||||
'"shadow":null,'+
|
||||
'"visible":true,"clipTo":null,"backgroundColor":"","rx":0,"ry":0,"x":0,"y":0}],"background":"#ff5555"}';
|
||||
'"visible":true,"clipTo":null,"backgroundColor":"","rx":0,"ry":0,"x":0,"y":0}],"background":"#ff5555","overlay":"rgba(0,0,0,0.2)"}';
|
||||
|
||||
var el = fabric.document.createElement('canvas');
|
||||
el.width = 600; el.height = 600;
|
||||
|
|
@ -68,7 +68,7 @@
|
|||
canvas.clear();
|
||||
canvas.setActiveGroup(null);
|
||||
canvas.backgroundColor = fabric.Canvas.prototype.backgroundColor;
|
||||
canvas.backgroundImage = '';
|
||||
canvas.overlayColor = fabric.Canvas.prototype.overlayColor;
|
||||
canvas.calcOffset();
|
||||
upperCanvasEl.style.display = 'none';
|
||||
}
|
||||
|
|
@ -248,19 +248,12 @@
|
|||
ok(typeof canvas.toJSON == 'function');
|
||||
equal(JSON.stringify(canvas.toJSON()), EMPTY_JSON);
|
||||
canvas.backgroundColor = '#ff5555';
|
||||
equal(JSON.stringify(canvas.toJSON()), '{"objects":[],"background":"#ff5555"}', '`background` value should be reflected in json');
|
||||
canvas.overlayColor = 'rgba(0,0,0,0.2)';
|
||||
equal(JSON.stringify(canvas.toJSON()), '{"objects":[],"background":"#ff5555","overlay":"rgba(0,0,0,0.2)"}', '`background` and `overlayColor` value should be reflected in json');
|
||||
canvas.add(makeRect());
|
||||
deepEqual(JSON.stringify(canvas.toJSON()), RECT_JSON);
|
||||
});
|
||||
|
||||
test('toDatalessJSON', function() {
|
||||
var path = new fabric.Path('M 100 100 L 300 100 L 200 300 z', {
|
||||
sourcePath: 'http://example.com/'
|
||||
});
|
||||
canvas.add(path);
|
||||
equal(JSON.stringify(canvas.toDatalessJSON()), PATH_DATALESS_JSON);
|
||||
});
|
||||
|
||||
test('toJSON with active group', function() {
|
||||
var rect = new fabric.Rect({ width: 50, height: 50, left: 100, top: 100 });
|
||||
var circle = new fabric.Circle({ radius: 50, left: 50, top: 50 });
|
||||
|
|
@ -273,6 +266,14 @@
|
|||
equal(json, jsonWithActiveGroup);
|
||||
});
|
||||
|
||||
test('toDatalessJSON', function() {
|
||||
var path = new fabric.Path('M 100 100 L 300 100 L 200 300 z', {
|
||||
sourcePath: 'http://example.com/'
|
||||
});
|
||||
canvas.add(path);
|
||||
equal(JSON.stringify(canvas.toDatalessJSON()), PATH_DATALESS_JSON);
|
||||
});
|
||||
|
||||
test('toObject', function() {
|
||||
ok(typeof canvas.toObject == 'function');
|
||||
var expectedObject = {
|
||||
|
|
@ -318,6 +319,7 @@
|
|||
ok(!canvas.isEmpty(), 'canvas is not empty');
|
||||
equal(obj.type, 'path', 'first object is a path object');
|
||||
equal(canvas.backgroundColor, '#ff5555', 'backgroundColor is populated properly');
|
||||
equal(canvas.overlayColor, 'rgba(0,0,0,0.2)', 'overlayColor is populated properly');
|
||||
|
||||
equal(obj.get('left'), 268);
|
||||
equal(obj.get('top'), 266);
|
||||
|
|
@ -345,6 +347,7 @@
|
|||
ok(!canvas.isEmpty(), 'canvas is not empty');
|
||||
equal(obj.type, 'path', 'first object is a path object');
|
||||
equal(canvas.backgroundColor, '#ff5555', 'backgroundColor is populated properly');
|
||||
equal(canvas.overlayColor, 'rgba(0,0,0,0.2)', 'overlayColor is populated properly');
|
||||
|
||||
equal(obj.get('left'), 268);
|
||||
equal(obj.get('top'), 266);
|
||||
|
|
@ -380,6 +383,7 @@
|
|||
ok(!canvas.isEmpty(), 'canvas is not empty');
|
||||
equal(obj.type, 'path', 'first object is a path object');
|
||||
equal(canvas.backgroundColor, '#ff5555', 'backgroundColor is populated properly');
|
||||
equal(canvas.overlayColor, 'rgba(0,0,0,0.2)', 'overlayColor is populated properly');
|
||||
|
||||
equal(obj.get('left'), 268);
|
||||
equal(obj.get('top'), 266);
|
||||
|
|
@ -400,20 +404,19 @@
|
|||
});
|
||||
|
||||
asyncTest('loadFromJSON with no objects', function() {
|
||||
var c1 = new fabric.Canvas('c1', { backgroundColor: 'green' }),
|
||||
c2 = new fabric.Canvas('c2', { backgroundColor: 'red' });
|
||||
var c1 = new fabric.Canvas('c1', { backgroundColor: 'green', overlayColor: 'yellow' }),
|
||||
c2 = new fabric.Canvas('c2', { backgroundColor: 'red', overlayColor: 'orange' });
|
||||
|
||||
var json = c1.toJSON();
|
||||
var fired = false;
|
||||
c2.loadFromJSON(json, function() {
|
||||
fired = true;
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
ok(fired, 'Callback should be fired even if no objects');
|
||||
equal(c2.backgroundColor, 'green', 'Color should be set properly');
|
||||
equal(c2.overlayColor, 'yellow', 'Color should be set properly');
|
||||
start();
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('loadFromJSON with empty fabric.Group', function() {
|
||||
|
|
@ -428,12 +431,10 @@
|
|||
var fired = false;
|
||||
c2.loadFromJSON(json, function() {
|
||||
fired = true;
|
||||
});
|
||||
|
||||
setTimeout(function() {
|
||||
ok(fired, 'Callback should be fired even if empty fabric.Group exists');
|
||||
start();
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('loadFromJSON with async content', function() {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
' -3.56, 6.891, -7.481, 8.848], ["c", -4.689, 2.336, -9.084, -0.802, -11.277, -2.868], ["l",'+
|
||||
' -1.948, 3.104], ["l", -1.628, -1.333], ["l", 3.138, -4.689], ["c", 0.025, 0, 9, 1.932, 9, 1.932], '+
|
||||
'["c", 0.877, -9.979, 2.893, -12.905, 4.942, -15.621], ["C", 17.878, 21.775, 18.713, 17.397, 18.511, '+
|
||||
'13.99], ["z", null]]}], "background": "#ff5555"}';
|
||||
'13.99], ["z", null]]}], "background": "#ff5555", "overlay":"rgba(0,0,0,0.2)"}';
|
||||
|
||||
var PATH_DATALESS_JSON = '{"objects":[{"type":"path","originX":"center","originY":"center","left":200,"top":200,"width":200,"height":200,"fill":"rgb(0,0,0)",'+
|
||||
'"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+
|
||||
|
|
@ -33,13 +33,97 @@
|
|||
var RECT_JSON = '{"objects":[{"type":"rect","originX":"center","originY":"center","left":0,"top":0,"width":10,"height":10,"fill":"rgb(0,0,0)",'+
|
||||
'"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+
|
||||
'"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,'+
|
||||
'"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","rx":0,"ry":0,"x":0,"y":0}],"background":"#ff5555"}';
|
||||
'"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","rx":0,"ry":0,"x":0,"y":0}],"background":"#ff5555","overlay":"rgba(0,0,0,0.2)"}';
|
||||
|
||||
var RECT_JSON_WITH_PADDING = '{"objects":[{"type":"rect","originX":"center","originY":"center","left":0,"top":0,"width":10,"height":20,"fill":"rgb(0,0,0)",'+
|
||||
'"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,'+
|
||||
'"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,'+
|
||||
'"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","padding":123,"foo":"bar","rx":0,"ry":0,"x":0,"y":0}],"background":""}';
|
||||
|
||||
function getAbsolutePath(path) {
|
||||
var isAbsolute = /^https?:/.test(path);
|
||||
if (isAbsolute) return path;
|
||||
var imgEl = _createImageElement();
|
||||
imgEl.src = path;
|
||||
var src = imgEl.src;
|
||||
imgEl = null;
|
||||
return src;
|
||||
}
|
||||
|
||||
var IMG_SRC = fabric.isLikelyNode ? (__dirname + '/../fixtures/test_image.gif') : getAbsolutePath('../fixtures/test_image.gif'),
|
||||
IMG_WIDTH = 276,
|
||||
IMG_HEIGHT = 110;
|
||||
|
||||
var REFERENCE_IMG_OBJECT = {
|
||||
'type': 'image',
|
||||
'originX': 'center',
|
||||
'originY': 'center',
|
||||
'left': 0,
|
||||
'top': 0,
|
||||
'width': IMG_WIDTH, // node-canvas doesn't seem to allow setting width/height on image objects
|
||||
'height': IMG_HEIGHT, // or does it now?
|
||||
'fill': 'rgb(0,0,0)',
|
||||
'stroke': null,
|
||||
'strokeWidth': 1,
|
||||
'strokeDashArray': null,
|
||||
'strokeLineCap': 'butt',
|
||||
'strokeLineJoin': 'miter',
|
||||
'strokeMiterLimit': 10,
|
||||
'scaleX': 1,
|
||||
'scaleY': 1,
|
||||
'angle': 0,
|
||||
'flipX': false,
|
||||
'flipY': false,
|
||||
'opacity': 1,
|
||||
'src': fabric.isLikelyNode ? undefined : IMG_SRC,
|
||||
'shadow': null,
|
||||
'visible': true,
|
||||
'backgroundColor': '',
|
||||
'clipTo': null,
|
||||
'filters': []
|
||||
};
|
||||
|
||||
function _createImageElement() {
|
||||
return fabric.isLikelyNode ? new (require('canvas').Image) : fabric.document.createElement('img');
|
||||
}
|
||||
|
||||
function _createImageObject(width, height, callback) {
|
||||
var elImage = _createImageElement();
|
||||
elImage.width = width;
|
||||
elImage.height = height;
|
||||
setSrc(elImage, IMG_SRC, function() {
|
||||
callback(new fabric.Image(elImage));
|
||||
});
|
||||
}
|
||||
|
||||
function createImageObject(callback) {
|
||||
return _createImageObject(IMG_WIDTH, IMG_HEIGHT, callback)
|
||||
}
|
||||
|
||||
function setSrc(img, src, callback) {
|
||||
if (fabric.isLikelyNode) {
|
||||
require('fs').readFile(src, function(err, imgData) {
|
||||
if (err) throw err;
|
||||
img.src = imgData;
|
||||
callback && callback();
|
||||
});
|
||||
}
|
||||
else {
|
||||
img.src = src;
|
||||
callback && callback();
|
||||
}
|
||||
}
|
||||
|
||||
function fixImageDimension(imgObj) {
|
||||
// workaround for node-canvas sometimes producing images with width/height and sometimes not
|
||||
if (imgObj.width === 0) {
|
||||
imgObj.width = IMG_WIDTH;
|
||||
}
|
||||
if (imgObj.height === 0) {
|
||||
imgObj.height = IMG_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
// force creation of static canvas
|
||||
// TODO: fix this
|
||||
var Canvas = fabric.Canvas;
|
||||
|
|
@ -61,6 +145,7 @@
|
|||
teardown: function() {
|
||||
canvas.clear();
|
||||
canvas.backgroundColor = fabric.StaticCanvas.prototype.backgroundColor;
|
||||
canvas.overlayColor = fabric.StaticCanvas.prototype.overlayColor;
|
||||
canvas.calcOffset();
|
||||
}
|
||||
});
|
||||
|
|
@ -352,11 +437,62 @@
|
|||
ok(typeof canvas.toJSON == 'function');
|
||||
equal(JSON.stringify(canvas.toJSON()), '{"objects":[],"background":""}');
|
||||
canvas.backgroundColor = '#ff5555';
|
||||
equal(JSON.stringify(canvas.toJSON()), '{"objects":[],"background":"#ff5555"}', '`background` value should be reflected in json');
|
||||
canvas.overlayColor = 'rgba(0,0,0,0.2)';
|
||||
equal(JSON.stringify(canvas.toJSON()), '{"objects":[],"background":"#ff5555","overlay":"rgba(0,0,0,0.2)"}', '`background` and `overlay` value should be reflected in json');
|
||||
canvas.add(makeRect());
|
||||
deepEqual(JSON.stringify(canvas.toJSON()), RECT_JSON);
|
||||
});
|
||||
|
||||
test('toJSON custom properties non-existence check', function() {
|
||||
var rect = new fabric.Rect({ width: 10, height: 20 });
|
||||
rect.padding = 123;
|
||||
canvas.add(rect);
|
||||
rect.foo = 'bar';
|
||||
|
||||
canvas.bar = 456;
|
||||
|
||||
var data = canvas.toJSON(['padding', 'foo', 'bar', 'baz']);
|
||||
ok('padding' in data.objects[0]);
|
||||
ok('foo' in data.objects[0], 'foo shouldn\'t be included if it\'s not in an object');
|
||||
ok(!('bar' in data.objects[0]), 'bar shouldn\'t be included if it\'s not in an object');
|
||||
ok(!('baz' in data.objects[0]), 'bar shouldn\'t be included if it\'s not in an object');
|
||||
ok(!('foo' in data));
|
||||
ok(!('baz' in data));
|
||||
ok('bar' in data);
|
||||
});
|
||||
|
||||
asyncTest('toJSON backgroundImage', function() {
|
||||
createImageObject(function(image) {
|
||||
|
||||
canvas.backgroundImage = image;
|
||||
|
||||
var json = canvas.toJSON();
|
||||
|
||||
fixImageDimension(json.backgroundImage);
|
||||
deepEqual(json.backgroundImage, REFERENCE_IMG_OBJECT);
|
||||
|
||||
canvas.backgroundImage = null;
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('toJSON overlayImage', function() {
|
||||
createImageObject(function(image) {
|
||||
|
||||
canvas.overlayImage = image;
|
||||
|
||||
var json = canvas.toJSON();
|
||||
|
||||
fixImageDimension(json.overlayImage);
|
||||
deepEqual(json.overlayImage, REFERENCE_IMG_OBJECT);
|
||||
|
||||
canvas.overlayImage = null;
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
test('toDatalessJSON', function() {
|
||||
var path = new fabric.Path('M 100 100 L 300 100 L 200 300 z', {
|
||||
sourcePath: 'http://example.com/'
|
||||
|
|
@ -458,6 +594,7 @@
|
|||
ok(!canvas.isEmpty(), 'canvas is not empty');
|
||||
equal(obj.type, 'path', 'first object is a path object');
|
||||
equal(canvas.backgroundColor, '#ff5555', 'backgroundColor is populated properly');
|
||||
equal(canvas.overlayColor, 'rgba(0,0,0,0.2)', 'overlayColor is populated properly');
|
||||
|
||||
equal(obj.get('left'), 268);
|
||||
equal(obj.get('top'), 266);
|
||||
|
|
@ -499,22 +636,19 @@
|
|||
});
|
||||
});
|
||||
|
||||
test('toJSON custom properties non-existence check', function() {
|
||||
var rect = new fabric.Rect({ width: 10, height: 20 });
|
||||
rect.padding = 123;
|
||||
canvas.add(rect);
|
||||
rect.foo = 'bar';
|
||||
asyncTest('loadFromJSON with text', function() {
|
||||
var json = '{"objects":[{"type":"text","left":150,"top":200,"width":128,"height":64.32,"fill":"#000000","stroke":"","strokeWidth":"","scaleX":0.8,"scaleY":0.8,"angle":0,"flipX":false,"flipY":false,"opacity":1,"text":"NAME HERE","fontSize":24,"fontWeight":"","fontFamily":"Delicious_500","fontStyle":"","lineHeight":"","textDecoration":"","textAlign":"center","path":"","strokeStyle":"","backgroundColor":""}],"background":"#ffffff"}';
|
||||
canvas.loadFromJSON(json, function() {
|
||||
|
||||
canvas.bar = 456;
|
||||
canvas.renderAll();
|
||||
|
||||
var data = canvas.toJSON(['padding', 'foo', 'bar', 'baz']);
|
||||
ok('padding' in data.objects[0]);
|
||||
ok('foo' in data.objects[0], 'foo shouldn\'t be included if it\'s not in an object');
|
||||
ok(!('bar' in data.objects[0]), 'bar shouldn\'t be included if it\'s not in an object');
|
||||
ok(!('baz' in data.objects[0]), 'bar shouldn\'t be included if it\'s not in an object');
|
||||
ok(!('foo' in data));
|
||||
ok(!('baz' in data));
|
||||
ok('bar' in data);
|
||||
equal('text', canvas.item(0).type);
|
||||
equal(150, canvas.item(0).left);
|
||||
equal(200, canvas.item(0).top)
|
||||
equal('NAME HERE', canvas.item(0).text);
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
test('remove', function() {
|
||||
|
|
@ -895,19 +1029,4 @@
|
|||
deepEqual(objectsAdded[3], circle3);
|
||||
});
|
||||
|
||||
asyncTest('loadFromJSON with text', function() {
|
||||
var json = '{"objects":[{"type":"text","left":150,"top":200,"width":128,"height":64.32,"fill":"#000000","stroke":"","strokeWidth":"","scaleX":0.8,"scaleY":0.8,"angle":0,"flipX":false,"flipY":false,"opacity":1,"text":"NAME HERE","fontSize":24,"fontWeight":"","fontFamily":"Delicious_500","fontStyle":"","lineHeight":"","textDecoration":"","textAlign":"center","path":"","strokeStyle":"","backgroundColor":""}],"background":"#ffffff"}';
|
||||
canvas.loadFromJSON(json, function() {
|
||||
|
||||
canvas.renderAll();
|
||||
|
||||
equal('text', canvas.item(0).type);
|
||||
equal(150, canvas.item(0).left);
|
||||
equal(200, canvas.item(0).top)
|
||||
equal('NAME HERE', canvas.item(0).text);
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
||||
|
|
|
|||
Loading…
Reference in a new issue