fabric-pure-browser
Version:
Fabric.js package with no node-specific dependencies (node-canvas, jsdom). The project is published once a day (in case if a new version appears) from 'master' branch of https://github.com/fabricjs/fabric.js repository. You can keep original imports in
200 lines (176 loc) • 6.02 kB
JavaScript
(function() {
'use strict';
var toFixed = fabric.util.toFixed;
/**
* Pattern class
* @class fabric.Pattern
* @see {@link http://fabricjs.com/patterns|Pattern demo}
* @see {@link http://fabricjs.com/dynamic-patterns|DynamicPattern demo}
* @see {@link fabric.Pattern#initialize} for constructor definition
*/
fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */ {
/**
* Repeat property of a pattern (one of repeat, repeat-x, repeat-y or no-repeat)
* @type String
* @default
*/
repeat: 'repeat',
/**
* Pattern horizontal offset from object's left/top corner
* @type Number
* @default
*/
offsetX: 0,
/**
* Pattern vertical offset from object's left/top corner
* @type Number
* @default
*/
offsetY: 0,
/**
* crossOrigin value (one of "", "anonymous", "use-credentials")
* @see https://developer.mozilla.org/en-US/docs/HTML/CORS_settings_attributes
* @type String
* @default
*/
crossOrigin: '',
/**
* transform matrix to change the pattern, imported from svgs.
* @type Array
* @default
*/
patternTransform: null,
/**
* Constructor
* @param {Object} [options] Options object
* @param {Function} [callback] function to invoke after callback init.
* @return {fabric.Pattern} thisArg
*/
initialize: function(options, callback) {
options || (options = { });
this.id = fabric.Object.__uid++;
this.setOptions(options);
if (!options.source || (options.source && typeof options.source !== 'string')) {
callback && callback(this);
return;
}
// function string
if (typeof fabric.util.getFunctionBody(options.source) !== 'undefined') {
this.source = new Function(fabric.util.getFunctionBody(options.source));
callback && callback(this);
}
else {
// img src string
var _this = this;
this.source = fabric.util.createImage();
fabric.util.loadImage(options.source, function(img) {
_this.source = img;
callback && callback(_this);
}, null, this.crossOrigin);
}
},
/**
* Returns object representation of a pattern
* @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
* @return {Object} Object representation of a pattern instance
*/
toObject: function(propertiesToInclude) {
var NUM_FRACTION_DIGITS = fabric.Object.NUM_FRACTION_DIGITS,
source, object;
// callback
if (typeof this.source === 'function') {
source = String(this.source);
}
// <img> element
else if (typeof this.source.src === 'string') {
source = this.source.src;
}
// <canvas> element
else if (typeof this.source === 'object' && this.source.toDataURL) {
source = this.source.toDataURL();
}
object = {
type: 'pattern',
source: source,
repeat: this.repeat,
crossOrigin: this.crossOrigin,
offsetX: toFixed(this.offsetX, NUM_FRACTION_DIGITS),
offsetY: toFixed(this.offsetY, NUM_FRACTION_DIGITS),
patternTransform: this.patternTransform ? this.patternTransform.concat() : null
};
fabric.util.populateWithProperties(this, object, propertiesToInclude);
return object;
},
/* _TO_SVG_START_ */
/**
* Returns SVG representation of a pattern
* @param {fabric.Object} object
* @return {String} SVG representation of a pattern
*/
toSVG: function(object) {
var patternSource = typeof this.source === 'function' ? this.source() : this.source,
patternWidth = patternSource.width / object.width,
patternHeight = patternSource.height / object.height,
patternOffsetX = this.offsetX / object.width,
patternOffsetY = this.offsetY / object.height,
patternImgSrc = '';
if (this.repeat === 'repeat-x' || this.repeat === 'no-repeat') {
patternHeight = 1;
if (patternOffsetY) {
patternHeight += Math.abs(patternOffsetY);
}
}
if (this.repeat === 'repeat-y' || this.repeat === 'no-repeat') {
patternWidth = 1;
if (patternOffsetX) {
patternWidth += Math.abs(patternOffsetX);
}
}
if (patternSource.src) {
patternImgSrc = patternSource.src;
}
else if (patternSource.toDataURL) {
patternImgSrc = patternSource.toDataURL();
}
return '<pattern id="SVGID_' + this.id +
'" x="' + patternOffsetX +
'" y="' + patternOffsetY +
'" width="' + patternWidth +
'" height="' + patternHeight + '">\n' +
'<image x="0" y="0"' +
' width="' + patternSource.width +
'" height="' + patternSource.height +
'" xlink:href="' + patternImgSrc +
'"></image>\n' +
'</pattern>\n';
},
/* _TO_SVG_END_ */
setOptions: function(options) {
for (var prop in options) {
this[prop] = options[prop];
}
},
/**
* Returns an instance of CanvasPattern
* @param {CanvasRenderingContext2D} ctx Context to create pattern
* @return {CanvasPattern}
*/
toLive: function(ctx) {
var source = typeof this.source === 'function' ? this.source() : this.source;
// if the image failed to load, return, and allow rest to continue loading
if (!source) {
return '';
}
// if an image
if (typeof source.src !== 'undefined') {
if (!source.complete) {
return '';
}
if (source.naturalWidth === 0 || source.naturalHeight === 0) {
return '';
}
}
return ctx.createPattern(source, this.repeat);
}
});
})();