mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-04-28 17:24:42 +00:00
Allow excanvas to kick in for IE8 and lower
This commit is contained in:
parent
364e76713c
commit
3795149dda
3 changed files with 373 additions and 366 deletions
|
|
@ -1,74 +1,74 @@
|
|||
//= require "object.class"
|
||||
|
||||
(function(global) {
|
||||
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
var extend = fabric.util.object.extend;
|
||||
|
||||
|
||||
if (!global.fabric) {
|
||||
global.fabric = { };
|
||||
}
|
||||
|
||||
|
||||
if (global.fabric.Image) {
|
||||
fabric.warn('fabric.Image is already defined.');
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
if (!fabric.Object) {
|
||||
fabric.warn('fabric.Object is required for fabric.Image initialization');
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* @class Image
|
||||
* @extends fabric.Object
|
||||
*/
|
||||
fabric.Image = fabric.util.createClass(fabric.Object, /** @scope fabric.Image.prototype */ {
|
||||
|
||||
|
||||
/**
|
||||
* @property
|
||||
* @type Number
|
||||
*/
|
||||
maxwidth: null,
|
||||
|
||||
|
||||
/**
|
||||
* @property
|
||||
* @type Number
|
||||
*/
|
||||
maxheight: null,
|
||||
|
||||
|
||||
/**
|
||||
* @property
|
||||
* @type Boolean
|
||||
*/
|
||||
active: false,
|
||||
|
||||
|
||||
/**
|
||||
* @property
|
||||
* @type Boolean
|
||||
*/
|
||||
bordervisibility: false,
|
||||
|
||||
|
||||
/**
|
||||
* @property
|
||||
* @type Boolean
|
||||
*/
|
||||
cornervisibility: false,
|
||||
|
||||
|
||||
/**
|
||||
* @property
|
||||
* @type String
|
||||
*/
|
||||
type: 'image',
|
||||
|
||||
|
||||
/**
|
||||
* Filters to be applied to an image (when calling `applyFilters`)
|
||||
* @property
|
||||
* @type Array
|
||||
*/
|
||||
filters: [ ],
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param {HTMLImageElement | String} element Image element
|
||||
|
|
@ -76,18 +76,18 @@
|
|||
*/
|
||||
initialize: function(element, options) {
|
||||
options || (options = { });
|
||||
|
||||
|
||||
this.callSuper('initialize', options);
|
||||
this._initElement(element);
|
||||
this._originalImage = this.getElement();
|
||||
this._initConfig(options);
|
||||
|
||||
|
||||
if (options.filters) {
|
||||
this.filters = options.filters;
|
||||
this.applyFilters();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns image element which this instance if based on
|
||||
* @method getElement
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
getElement: function() {
|
||||
return this._element;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sets image element for this instance to a specified one
|
||||
* @method setElement
|
||||
|
|
@ -109,7 +109,7 @@
|
|||
this._initConfig();
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Resizes an image depending on whether maxwidth and maxheight are set up;
|
||||
* Width and height have to mantain the same proportion in the final image as it was in the initial one.
|
||||
|
|
@ -117,7 +117,7 @@
|
|||
* @param {Object} oImg
|
||||
* @param {Number} maxwidth maximum width of the image (in px)
|
||||
* @param {Number} maxheight maximum height of the image (in px)
|
||||
*/
|
||||
*/
|
||||
getNormalizedSize: function(oImg, maxwidth, maxheight) {
|
||||
if (maxheight && maxwidth && (oImg.width > oImg.height && (oImg.width / oImg.height) < (maxwidth / maxheight))) {
|
||||
// height is the constraining dimension.
|
||||
|
|
@ -138,13 +138,13 @@
|
|||
normalizedWidth = oImg.width;
|
||||
normalizedHeight = oImg.height;
|
||||
}
|
||||
|
||||
return {
|
||||
width: normalizedWidth,
|
||||
height: normalizedHeight
|
||||
|
||||
return {
|
||||
width: normalizedWidth,
|
||||
height: normalizedHeight
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns original size of an image
|
||||
* @method getOriginalSize
|
||||
|
|
@ -152,12 +152,12 @@
|
|||
*/
|
||||
getOriginalSize: function() {
|
||||
var element = this.getElement();
|
||||
return {
|
||||
width: element.width,
|
||||
return {
|
||||
width: element.width,
|
||||
height: element.height
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sets border visibility
|
||||
* @method setBorderVisibility
|
||||
|
|
@ -168,7 +168,7 @@
|
|||
this._adjustWidthHeightToBorders(showBorder);
|
||||
this.setCoords();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sets corner visibility
|
||||
* @method setCornersVisibility
|
||||
|
|
@ -177,7 +177,7 @@
|
|||
setCornersVisibility: function(visible) {
|
||||
this.cornervisibility = !!visible;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Renders image on a specified context
|
||||
* @method render
|
||||
|
|
@ -195,7 +195,7 @@
|
|||
}
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns object representation of an instance
|
||||
* @method toObject
|
||||
|
|
@ -207,7 +207,7 @@
|
|||
filters: this.filters.concat()
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns svg representation of an instance
|
||||
* @method toSVG
|
||||
|
|
@ -217,15 +217,15 @@
|
|||
return '<g transform="' + this.getSvgTransform() + '">'+
|
||||
'<image xlink:href="' + this.getSrc() + '" '+
|
||||
'style="' + this.getSvgStyles() + '" ' +
|
||||
// we're essentially moving origin of transformation from top/left corner to the center of the shape
|
||||
// by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left
|
||||
// we're essentially moving origin of transformation from top/left corner to the center of the shape
|
||||
// by wrapping it in container <g> element with actual transformation, then offsetting object to the top/left
|
||||
// so that object's center aligns with container's left/top
|
||||
'transform="translate('+ (-this.width/2) + ' ' + (-this.height/2) + ')" ' +
|
||||
'width="' + this.width + '" ' +
|
||||
'height="' + this.height + '"' + '/>'+
|
||||
'</g>';
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns source of an image
|
||||
* @method getSrc
|
||||
|
|
@ -234,16 +234,16 @@
|
|||
getSrc: function() {
|
||||
return this.getElement().src;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns string representation of an instance
|
||||
* @method toString
|
||||
* @return {String} String representation of an instance
|
||||
*/
|
||||
toString: function() {
|
||||
toString: function() {
|
||||
return '#<fabric.Image: { src: "' + this.getSrc() + '" }>';
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns a clone of an instance
|
||||
* @mthod clone
|
||||
|
|
@ -252,14 +252,14 @@
|
|||
clone: function(callback) {
|
||||
this.constructor.fromObject(this.toObject(), callback);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Applies filters assigned to this image (from "filters" array)
|
||||
* @mthod applyFilters
|
||||
* @param {Function} callback Callback is invoked when all filters have been applied and new image is generated
|
||||
*/
|
||||
applyFilters: function(callback) {
|
||||
|
||||
|
||||
if (this.filters.length === 0) {
|
||||
this.setElement(this._originalImage);
|
||||
callback && callback();
|
||||
|
|
@ -272,12 +272,16 @@
|
|||
replacement = isLikelyNode ? new (require('canvas').Image) : fabric.document.createElement('img'),
|
||||
_this = this;
|
||||
|
||||
if (!canvasEl.getContext && typeof G_vmlCanvasManager != 'undefined') {
|
||||
G_vmlCanvasManager.initElement(canvasEl);
|
||||
}
|
||||
|
||||
canvasEl.width = imgEl.width;
|
||||
canvasEl.height = imgEl.height;
|
||||
|
||||
canvasEl.getContext('2d').drawImage(imgEl, 0, 0);
|
||||
|
||||
this.filters.forEach(function(filter) {
|
||||
this.filters.forEach(function(filter) {
|
||||
filter && filter.applyTo(canvasEl);
|
||||
});
|
||||
|
||||
|
|
@ -304,7 +308,7 @@
|
|||
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
|
|
@ -318,7 +322,7 @@
|
|||
originalImgSize.height
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
|
|
@ -332,19 +336,19 @@
|
|||
this.currentBorder = 0;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_resetWidthHeight: function() {
|
||||
var element = this.getElement();
|
||||
|
||||
|
||||
this.set('width', element.width);
|
||||
this.set('height', element.height);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* The Image class's initialization method. This method is automatically
|
||||
* The Image class's initialization method. This method is automatically
|
||||
* called by the constructor.
|
||||
* @method _initElement
|
||||
* @param {HTMLImageElement|String} el The element representing the image
|
||||
|
|
@ -353,7 +357,7 @@
|
|||
this.setElement(fabric.util.getById(element));
|
||||
fabric.util.addClass(this.getElement(), fabric.Image.CSS_CANVAS);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @method _initConfig
|
||||
* @param {Object} options Options object
|
||||
|
|
@ -363,7 +367,7 @@
|
|||
this._setBorder();
|
||||
this._setWidthHeight();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @method _initFilters
|
||||
* @param {Object} object Object with filters property
|
||||
|
|
@ -375,7 +379,7 @@
|
|||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
|
|
@ -387,7 +391,7 @@
|
|||
this.currentBorder = 0;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
|
|
@ -396,7 +400,7 @@
|
|||
this.width = (this.getElement().width || 0) + sidesBorderWidth;
|
||||
this.height = (this.getElement().height || 0) + sidesBorderWidth;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns complexity of an instance
|
||||
* @method complexity
|
||||
|
|
@ -406,14 +410,14 @@
|
|||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Default CSS class name for canvas
|
||||
* @static
|
||||
* @type String
|
||||
*/
|
||||
fabric.Image.CSS_CANVAS = "canvas-img";
|
||||
|
||||
|
||||
/**
|
||||
* Creates an instance of fabric.Image from its object representation
|
||||
* @static
|
||||
|
|
@ -424,25 +428,25 @@
|
|||
fabric.Image.fromObject = function(object, callback) {
|
||||
var img = fabric.document.createElement('img'),
|
||||
src = object.src;
|
||||
|
||||
|
||||
if (object.width) {
|
||||
img.width = object.width;
|
||||
}
|
||||
if (object.height) {
|
||||
img.height = object.height;
|
||||
}
|
||||
|
||||
|
||||
/** @ignore */
|
||||
img.onload = function() {
|
||||
fabric.Image.prototype._initFilters.call(object, object);
|
||||
|
||||
|
||||
var instance = new fabric.Image(img, object);
|
||||
callback && callback(instance);
|
||||
img = img.onload = null;
|
||||
};
|
||||
img.src = src;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates an instance of fabric.Image from an URL string
|
||||
* @static
|
||||
|
|
@ -453,7 +457,7 @@
|
|||
*/
|
||||
fabric.Image.fromURL = function(url, callback, imgOptions) {
|
||||
var img = fabric.document.createElement('img');
|
||||
|
||||
|
||||
/** @ignore */
|
||||
img.onload = function() {
|
||||
if (callback) {
|
||||
|
|
@ -463,14 +467,14 @@
|
|||
};
|
||||
img.src = url;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* List of attribute names to account for when parsing SVG element (used by {@link fabric.Image.fromElement})
|
||||
* @static
|
||||
* @see http://www.w3.org/TR/SVG/struct.html#ImageElement
|
||||
*/
|
||||
fabric.Image.ATTRIBUTE_NAMES = 'x y width height fill fill-opacity opacity stroke stroke-width transform xlink:href'.split(' ');
|
||||
|
||||
|
||||
/**
|
||||
* Returns {@link fabric.Image} instance from an SVG element
|
||||
* @static
|
||||
|
|
@ -482,12 +486,12 @@
|
|||
*/
|
||||
fabric.Image.fromElement = function(element, callback, options) {
|
||||
options || (options = { });
|
||||
|
||||
|
||||
var parsedAttributes = fabric.parseAttributes(element, fabric.Image.ATTRIBUTE_NAMES);
|
||||
|
||||
|
||||
fabric.Image.fromURL(parsedAttributes['xlink:href'], callback, extend(parsedAttributes, options));
|
||||
};
|
||||
|
||||
|
||||
fabric.Image.async = true;
|
||||
|
||||
})(typeof exports != 'undefined' ? exports : this);
|
||||
|
||||
})(typeof exports != 'undefined' ? exports : this);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,20 +1,20 @@
|
|||
(function (global) {
|
||||
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
if (fabric.StaticCanvas) {
|
||||
fabric.warn('fabric.StaticCanvas is already defined.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// aliases for faster resolution
|
||||
var extend = fabric.util.object.extend,
|
||||
getElementOffset = fabric.util.getElementOffset,
|
||||
removeFromArray = fabric.util.removeFromArray,
|
||||
removeListener = fabric.util.removeListener,
|
||||
|
||||
|
||||
CANVAS_INIT_ERROR = new Error('Could not initialize `canvas` element');
|
||||
|
||||
|
||||
/**
|
||||
* @class fabric.StaticCanvas
|
||||
* @constructor
|
||||
|
|
@ -23,22 +23,22 @@
|
|||
*/
|
||||
fabric.StaticCanvas = function (el, options) {
|
||||
options || (options = { });
|
||||
|
||||
|
||||
this._initStatic(el, options);
|
||||
fabric.StaticCanvas.activeInstance = this;
|
||||
};
|
||||
|
||||
|
||||
extend(fabric.StaticCanvas.prototype, fabric.Observable);
|
||||
|
||||
|
||||
extend(fabric.StaticCanvas.prototype, /** @scope fabric.StaticCanvas.prototype */ {
|
||||
|
||||
|
||||
/**
|
||||
* Background color of canvas instance
|
||||
* @property
|
||||
* @type String
|
||||
*/
|
||||
backgroundColor: 'rgba(0, 0, 0, 0)',
|
||||
|
||||
|
||||
/**
|
||||
* Background image of canvas instance
|
||||
* Should be set via `setBackgroundImage`
|
||||
|
|
@ -46,28 +46,28 @@
|
|||
* @type String
|
||||
*/
|
||||
backgroundImage: '',
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether toObject/toDatalessObject should include default values
|
||||
* @property
|
||||
* @type Boolean
|
||||
*/
|
||||
includeDefaultValues: true,
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether objects' state should be saved
|
||||
* @property
|
||||
* @type Boolean
|
||||
*/
|
||||
stateful: true,
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether fabric.Canvas#add should also re-render canvas.
|
||||
* Disabling this option could give a great performance boost when adding a lot of objects to canvas at once
|
||||
* Indicates whether fabric.Canvas#add should also re-render canvas.
|
||||
* Disabling this option could give a great performance boost when adding a lot of objects to canvas at once
|
||||
* (followed by a manual rendering after addition)
|
||||
*/
|
||||
renderOnAddition: true,
|
||||
|
||||
|
||||
/**
|
||||
* Function that determines clipping of entire canvas area
|
||||
* Being passed context as first argument. See clipping canvas area in https://github.com/kangax/fabric.js/wiki/FAQ
|
||||
|
|
@ -75,21 +75,21 @@
|
|||
* @type Function
|
||||
*/
|
||||
clipTo: null,
|
||||
|
||||
|
||||
/**
|
||||
* Default canvas width
|
||||
* @constant
|
||||
* @type Number
|
||||
*/
|
||||
CANVAS_WIDTH: 600,
|
||||
|
||||
|
||||
/**
|
||||
* Default canvas height
|
||||
* @constant
|
||||
* @type Number
|
||||
*/
|
||||
CANVAS_HEIGHT: 600,
|
||||
|
||||
|
||||
/**
|
||||
* Callback; invoked right before object is about to be scaled/rotated
|
||||
* @method onBeforeScaleRotate
|
||||
|
|
@ -98,14 +98,14 @@
|
|||
onBeforeScaleRotate: function (target) {
|
||||
/* NOOP */
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Callback; invoked on every redraw of canvas and is being passed a number indicating current fps
|
||||
* @method onFpsUpdate
|
||||
* @param {Number} fps
|
||||
*/
|
||||
onFpsUpdate: null,
|
||||
|
||||
|
||||
_initStatic: function(el, options) {
|
||||
this._objects = [];
|
||||
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
}
|
||||
this.calcOffset();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Calculates canvas element offset relative to the document
|
||||
* This method is also attached as "resize" event handler of window
|
||||
|
|
@ -132,7 +132,7 @@
|
|||
this._offset = getElementOffset(this.lowerCanvasEl);
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sets overlay image for this canvas
|
||||
* @method setOverlayImage
|
||||
|
|
@ -147,7 +147,7 @@
|
|||
callback && callback();
|
||||
}, this);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sets background image for this canvas
|
||||
* @method setBackgroundImage
|
||||
|
|
@ -162,7 +162,7 @@
|
|||
callback && callback();
|
||||
}, this);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @method _createCanvasElement
|
||||
|
|
@ -179,12 +179,12 @@
|
|||
this._initCanvasElement(element);
|
||||
return element;
|
||||
},
|
||||
|
||||
|
||||
_initCanvasElement: function(element) {
|
||||
if (typeof element.getContext === 'undefined' &&
|
||||
typeof G_vmlCanvasManager !== 'undefined' &&
|
||||
if (typeof element.getContext === 'undefined' &&
|
||||
typeof G_vmlCanvasManager !== 'undefined' &&
|
||||
G_vmlCanvasManager.initElement) {
|
||||
|
||||
|
||||
G_vmlCanvasManager.initElement(element);
|
||||
}
|
||||
if (typeof element.getContext === 'undefined') {
|
||||
|
|
@ -200,14 +200,14 @@
|
|||
for (var prop in options) {
|
||||
this[prop] = options[prop];
|
||||
}
|
||||
|
||||
|
||||
this.width = parseInt(this.lowerCanvasEl.width, 10) || 0;
|
||||
this.height = parseInt(this.lowerCanvasEl.height, 10) || 0;
|
||||
|
||||
this.lowerCanvasEl.style.width = this.width + 'px';
|
||||
this.lowerCanvasEl.style.height = this.height + 'px';
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Creates a secondary canvas
|
||||
* @method _createLowerCanvas
|
||||
|
|
@ -215,16 +215,16 @@
|
|||
_createLowerCanvas: function (canvasEl) {
|
||||
this.lowerCanvasEl = fabric.util.getById(canvasEl) || this._createCanvasElement();
|
||||
this._initCanvasElement(this.lowerCanvasEl);
|
||||
|
||||
|
||||
fabric.util.addClass(this.lowerCanvasEl, 'lower-canvas');
|
||||
|
||||
|
||||
if (this.interactive) {
|
||||
this._applyCanvasStyle(this.lowerCanvasEl);
|
||||
}
|
||||
|
||||
|
||||
this.contextContainer = this.lowerCanvasEl.getContext('2d');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns canvas width
|
||||
* @method getWidth
|
||||
|
|
@ -233,7 +233,7 @@
|
|||
getWidth: function () {
|
||||
return this.width;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns canvas height
|
||||
* @method getHeight
|
||||
|
|
@ -242,7 +242,7 @@
|
|||
getHeight: function () {
|
||||
return this.height;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sets width of this canvas instance
|
||||
* @method setWidth
|
||||
|
|
@ -253,7 +253,7 @@
|
|||
setWidth: function (value) {
|
||||
return this._setDimension('width', value);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sets height of this canvas instance
|
||||
* @method setHeight
|
||||
|
|
@ -264,7 +264,7 @@
|
|||
setHeight: function (value) {
|
||||
return this._setDimension('height', value);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sets dimensions (width, height) of this canvas instance
|
||||
* @method setDimensions
|
||||
|
|
@ -278,7 +278,7 @@
|
|||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Helper for setting width/height
|
||||
* @private
|
||||
|
|
@ -291,24 +291,24 @@
|
|||
_setDimension: function (prop, value) {
|
||||
this.lowerCanvasEl[prop] = value;
|
||||
this.lowerCanvasEl.style[prop] = value + 'px';
|
||||
|
||||
|
||||
if (this.upperCanvasEl) {
|
||||
this.upperCanvasEl[prop] = value;
|
||||
this.upperCanvasEl.style[prop] = value + 'px';
|
||||
}
|
||||
|
||||
|
||||
if (this.wrapperEl) {
|
||||
this.wrapperEl.style[prop] = value + 'px';
|
||||
}
|
||||
|
||||
|
||||
this[prop] = value;
|
||||
|
||||
|
||||
this.calcOffset();
|
||||
this.renderAll();
|
||||
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns <canvas> element corresponding to this instance
|
||||
* @method getElement
|
||||
|
|
@ -317,19 +317,19 @@
|
|||
getElement: function () {
|
||||
return this.lowerCanvasEl;
|
||||
},
|
||||
|
||||
|
||||
// placeholder
|
||||
getActiveObject: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
|
||||
// placeholder
|
||||
getActiveGroup: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Given a context, renders an object on that context
|
||||
* Given a context, renders an object on that context
|
||||
* @param ctx {Object} context to render object on
|
||||
* @param object {Object} object to render
|
||||
* @private
|
||||
|
|
@ -337,7 +337,7 @@
|
|||
_draw: function (ctx, object) {
|
||||
object && object.render(ctx);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Adds objects to canvas, then renders canvas;
|
||||
* Objects should be instances of (or inherit from) fabric.Object
|
||||
|
|
@ -354,9 +354,9 @@
|
|||
this.renderOnAddition && this.renderAll();
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Inserts an object to canvas at specified index and renders canvas.
|
||||
* Inserts an object to canvas at specified index and renders canvas.
|
||||
* An object should be an instance of (or inherit from) fabric.Object
|
||||
* @method insertAt
|
||||
* @param object {Object} Object to insert
|
||||
|
|
@ -376,7 +376,7 @@
|
|||
this.renderAll();
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array of objects this instance has
|
||||
* @method getObjects
|
||||
|
|
@ -385,7 +385,7 @@
|
|||
getObjects: function () {
|
||||
return this._objects;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Clears specified context of canvas element
|
||||
* @method clearContext
|
||||
|
|
@ -397,7 +397,7 @@
|
|||
ctx.clearRect(0, 0, this.width, this.height);
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Clears all contexts (background, main, top) of an instance
|
||||
* @method clear
|
||||
|
|
@ -420,9 +420,9 @@
|
|||
* @param allOnTop {Boolean} optional Whether we want to force all images to be rendered on the top canvas
|
||||
* @return {fabric.Canvas} instance
|
||||
* @chainable
|
||||
*/
|
||||
*/
|
||||
renderAll: function (allOnTop) {
|
||||
|
||||
|
||||
var canvasToDrawOn = this[(allOnTop && this.interactive) ? 'contextTop' : 'contextContainer'];
|
||||
|
||||
if (this.contextTop) {
|
||||
|
|
@ -432,25 +432,25 @@
|
|||
if (!allOnTop) {
|
||||
this.clearContext(canvasToDrawOn);
|
||||
}
|
||||
|
||||
|
||||
var length = this._objects.length,
|
||||
activeGroup = this.getActiveGroup(),
|
||||
startTime = new Date();
|
||||
|
||||
|
||||
if (this.clipTo) {
|
||||
canvasToDrawOn.save();
|
||||
canvasToDrawOn.beginPath();
|
||||
this.clipTo(canvasToDrawOn);
|
||||
canvasToDrawOn.clip();
|
||||
}
|
||||
|
||||
|
||||
canvasToDrawOn.fillStyle = this.backgroundColor;
|
||||
canvasToDrawOn.fillRect(0, 0, this.width, this.height);
|
||||
|
||||
|
||||
if (typeof this.backgroundImage == 'object') {
|
||||
canvasToDrawOn.drawImage(this.backgroundImage, 0, 0, this.width, this.height);
|
||||
}
|
||||
|
||||
|
||||
if (length) {
|
||||
for (var i = 0; i < length; ++i) {
|
||||
if (!activeGroup ||
|
||||
|
|
@ -459,27 +459,27 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (this.clipTo) {
|
||||
canvasToDrawOn.restore();
|
||||
}
|
||||
|
||||
|
||||
// delegate rendering to group selection (if one exists)
|
||||
if (activeGroup) {
|
||||
this._draw(this.contextTop, activeGroup);
|
||||
}
|
||||
|
||||
|
||||
if (this.overlayImage) {
|
||||
this.contextTop.drawImage(this.overlayImage, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
if (this.onFpsUpdate) {
|
||||
var elapsedTime = new Date() - startTime;
|
||||
this.onFpsUpdate(~~(1000 / elapsedTime));
|
||||
}
|
||||
|
||||
|
||||
this.fire('after:render');
|
||||
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
|
|
@ -492,25 +492,25 @@
|
|||
*/
|
||||
renderTop: function () {
|
||||
this.clearContext(this.contextTop || this.contextContainer);
|
||||
|
||||
|
||||
if (this.overlayImage) {
|
||||
(this.contextTop || this.contextContainer).drawImage(this.overlayImage, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
// we render the top context - last object
|
||||
if (this.selection && this._groupSelector) {
|
||||
this._drawSelection();
|
||||
}
|
||||
|
||||
|
||||
// delegate rendering to group selection if one exists
|
||||
// used for drawing selection borders/corners
|
||||
var activeGroup = this.getActiveGroup();
|
||||
if (activeGroup) {
|
||||
activeGroup.render(this.contextTop);
|
||||
}
|
||||
|
||||
|
||||
this.fire('after:render');
|
||||
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
|
|
@ -526,7 +526,7 @@
|
|||
this.renderAll();
|
||||
return data;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Exports canvas element to a dataurl image (allowing to change image size via multiplier).
|
||||
* @method toDataURLWithMultiplier
|
||||
|
|
@ -535,40 +535,40 @@
|
|||
* @return {String}
|
||||
*/
|
||||
toDataURLWithMultiplier: function (format, multiplier) {
|
||||
|
||||
|
||||
var origWidth = this.getWidth(),
|
||||
origHeight = this.getHeight(),
|
||||
scaledWidth = origWidth * multiplier,
|
||||
scaledHeight = origHeight * multiplier,
|
||||
activeObject = this.getActiveObject();
|
||||
|
||||
|
||||
this.setWidth(scaledWidth).setHeight(scaledHeight);
|
||||
this.contextTop.scale(multiplier, multiplier);
|
||||
|
||||
|
||||
if (activeObject) {
|
||||
this.deactivateAll();
|
||||
}
|
||||
|
||||
// restoring width, height for `renderAll` to draw
|
||||
|
||||
// restoring width, height for `renderAll` to draw
|
||||
// background properly (while context is scaled)
|
||||
this.width = origWidth;
|
||||
this.height = origHeight;
|
||||
|
||||
|
||||
this.renderAll(true);
|
||||
|
||||
|
||||
var dataURL = this.toDataURL(format);
|
||||
|
||||
this.contextTop.scale(1 / multiplier, 1 / multiplier);
|
||||
this.setWidth(origWidth).setHeight(origHeight);
|
||||
|
||||
|
||||
if (activeObject) {
|
||||
this.setActiveObject(activeObject);
|
||||
}
|
||||
this.renderAll();
|
||||
|
||||
|
||||
return dataURL;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns coordinates of a center of canvas.
|
||||
* Returned value is an object with top and left properties
|
||||
|
|
@ -581,7 +581,7 @@
|
|||
left: this.getWidth() / 2
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Centers object horizontally.
|
||||
* @method centerObjectH
|
||||
|
|
@ -593,7 +593,7 @@
|
|||
this.renderAll();
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Centers object vertically.
|
||||
* @method centerObjectH
|
||||
|
|
@ -606,7 +606,7 @@
|
|||
this.renderAll();
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Centers object vertically and horizontally.
|
||||
* @method centerObject
|
||||
|
|
@ -617,7 +617,7 @@
|
|||
centerObject: function (object) {
|
||||
return this.centerObjectH(object).centerObjectV(object);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Straightens object, then rerenders canvas
|
||||
* @method straightenObject
|
||||
|
|
@ -630,7 +630,7 @@
|
|||
this.renderAll();
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returs dataless JSON representation of canvas
|
||||
* @method toDatalessJSON
|
||||
|
|
@ -639,7 +639,7 @@
|
|||
toDatalessJSON: function () {
|
||||
return this.toDatalessObject();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns object representation of canvas
|
||||
* @method toObject
|
||||
|
|
@ -648,7 +648,7 @@
|
|||
toObject: function () {
|
||||
return this._toObjectMethod('toObject');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns dataless object representation of canvas
|
||||
* @method toDatalessObject
|
||||
|
|
@ -657,13 +657,13 @@
|
|||
toDatalessObject: function () {
|
||||
return this._toObjectMethod('toDatalessObject');
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @method _toObjectMethod
|
||||
*/
|
||||
_toObjectMethod: function (methodName) {
|
||||
return {
|
||||
return {
|
||||
objects: this._objects.map(function (instance){
|
||||
// TODO (kangax): figure out how to clean this up
|
||||
if (!this.includeDefaultValues) {
|
||||
|
|
@ -679,12 +679,12 @@
|
|||
background: this.backgroundColor
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns SVG representation of canvas
|
||||
* @function
|
||||
* @method toSVG
|
||||
* @return {String}
|
||||
* @return {String}
|
||||
*/
|
||||
toSVG: function() {
|
||||
var markup = [
|
||||
|
|
@ -718,7 +718,7 @@
|
|||
isEmpty: function () {
|
||||
return this._objects.length === 0;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Removes an object from canvas and returns it
|
||||
* @method remove
|
||||
|
|
@ -733,7 +733,7 @@
|
|||
this.renderAll();
|
||||
return object;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Moves an object to the bottom of the stack of drawn objects
|
||||
* @method sendToBack
|
||||
|
|
@ -746,7 +746,7 @@
|
|||
this._objects.unshift(object);
|
||||
return this.renderAll();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Moves an object to the top of the stack of drawn objects
|
||||
* @method bringToFront
|
||||
|
|
@ -759,7 +759,7 @@
|
|||
this._objects.push(object);
|
||||
return this.renderAll();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Moves an object one level down in stack of drawn objects
|
||||
* @method sendBackwards
|
||||
|
|
@ -770,10 +770,10 @@
|
|||
sendBackwards: function (object) {
|
||||
var idx = this._objects.indexOf(object),
|
||||
nextIntersectingIdx = idx;
|
||||
|
||||
|
||||
// if object is not on the bottom of stack
|
||||
if (idx !== 0) {
|
||||
|
||||
|
||||
// traverse down the stack looking for the nearest intersecting object
|
||||
for (var i=idx-1; i>=0; --i) {
|
||||
if (object.intersectsWithObject(this._objects[i]) || object.isContainedWithinObject(this._objects[i])) {
|
||||
|
|
@ -786,7 +786,7 @@
|
|||
}
|
||||
return this.renderAll();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Moves an object one level up in stack of drawn objects
|
||||
* @method sendForward
|
||||
|
|
@ -799,10 +799,10 @@
|
|||
idx = objects.indexOf(object),
|
||||
nextIntersectingIdx = idx;
|
||||
|
||||
|
||||
|
||||
// if object is not on top of stack (last item in an array)
|
||||
if (idx !== objects.length-1) {
|
||||
|
||||
|
||||
// traverse up the stack looking for the nearest intersecting object
|
||||
for (var i = idx + 1, l = this._objects.length; i < l; ++i) {
|
||||
if (object.intersectsWithObject(objects[i]) || object.isContainedWithinObject(this._objects[i])) {
|
||||
|
|
@ -815,7 +815,7 @@
|
|||
}
|
||||
this.renderAll();
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns object at specified index
|
||||
* @method item
|
||||
|
|
@ -825,7 +825,7 @@
|
|||
item: function (index) {
|
||||
return this.getObjects()[index];
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns number representation of an instance complexity
|
||||
* @method complexity
|
||||
|
|
@ -837,7 +837,7 @@
|
|||
return memo;
|
||||
}, 0);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Iterates over all objects, invoking callback for each one of them
|
||||
* @method forEachObject
|
||||
|
|
@ -851,7 +851,7 @@
|
|||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Clears a canvas element and removes all event handlers.
|
||||
* @method dispose
|
||||
|
|
@ -867,24 +867,24 @@
|
|||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @method _resizeImageToFit
|
||||
* @param {HTMLImageElement} imgEl
|
||||
*/
|
||||
_resizeImageToFit: function (imgEl) {
|
||||
|
||||
|
||||
var imageWidth = imgEl.width || imgEl.offsetWidth,
|
||||
widthScaleFactor = this.getWidth() / imageWidth;
|
||||
|
||||
|
||||
// scale image down so that it has original dimensions when printed in large resolution
|
||||
if (imageWidth) {
|
||||
imgEl.width = imageWidth * widthScaleFactor;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string representation of an instance
|
||||
* @method toString
|
||||
|
|
@ -894,16 +894,16 @@
|
|||
return '#<fabric.Canvas (' + this.complexity() + '): '+
|
||||
'{ objects: ' + this.getObjects().length + ' }>';
|
||||
};
|
||||
|
||||
|
||||
extend(fabric.StaticCanvas, /** @scope fabric.StaticCanvas */ {
|
||||
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @property EMPTY_JSON
|
||||
* @type String
|
||||
*/
|
||||
EMPTY_JSON: '{"objects": [], "background": "white"}',
|
||||
|
||||
|
||||
/**
|
||||
* Takes <canvas> element and transforms its data in such way that it becomes grayscale
|
||||
* @static
|
||||
|
|
@ -913,7 +913,7 @@
|
|||
toGrayscale: function (canvasEl) {
|
||||
var context = canvasEl.getContext('2d'),
|
||||
imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
|
||||
data = imageData.data,
|
||||
data = imageData.data,
|
||||
iLen = imageData.width,
|
||||
jLen = imageData.height,
|
||||
index, average, i, j;
|
||||
|
|
@ -932,46 +932,46 @@
|
|||
|
||||
context.putImageData(imageData, 0, 0);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Provides a way to check support of some of the canvas methods
|
||||
* Provides a way to check support of some of the canvas methods
|
||||
* (either those of HTMLCanvasElement itself, or rendering context)
|
||||
*
|
||||
* @method supports
|
||||
* @param methodName {String} Method to check support for;
|
||||
* @param methodName {String} Method to check support for;
|
||||
* Could be one of "getImageData" or "toDataURL"
|
||||
* @return {Boolean | null} `true` if method is supported (or at least exists),
|
||||
* @return {Boolean | null} `true` if method is supported (or at least exists),
|
||||
* `null` if canvas element or context can not be initialized
|
||||
*/
|
||||
supports: function (methodName) {
|
||||
var el = fabric.document.createElement('canvas');
|
||||
|
||||
|
||||
if (typeof G_vmlCanvasManager !== 'undefined') {
|
||||
G_vmlCanvasManager.initElement(el);
|
||||
}
|
||||
if (!el || !el.getContext) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
var ctx = el.getContext('2d');
|
||||
if (!ctx) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
switch (methodName) {
|
||||
|
||||
|
||||
case 'getImageData':
|
||||
return typeof ctx.getImageData !== 'undefined';
|
||||
|
||||
|
||||
case 'toDataURL':
|
||||
return typeof el.toDataURL !== 'undefined';
|
||||
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Returs JSON representation of canvas
|
||||
* @function
|
||||
|
|
@ -979,5 +979,5 @@
|
|||
* @return {String} json string
|
||||
*/
|
||||
fabric.StaticCanvas.prototype.toJSON = fabric.StaticCanvas.prototype.toObject;
|
||||
|
||||
})(typeof exports != 'undefined' ? exports : this);
|
||||
|
||||
})(typeof exports != 'undefined' ? exports : this);
|
||||
|
|
|
|||
Loading…
Reference in a new issue