mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-05-24 05:03:44 +00:00
Update fabric.Image.filters.Mask - based on https://github.com/kangax/fabric.js/pull/667 (@aleph1)
[BACK_INCOMPAT] `fabric.Image._initFilters` is now async, add parameter callback Add `fabric.util.resolveNamespace` - used to get correct klass in `fabric.util.enlivenObjects` Doc additions
This commit is contained in:
parent
d94d88f14b
commit
901ee7f942
3 changed files with 160 additions and 20 deletions
114
src/filters/mask_filter.class.js
Normal file
114
src/filters/mask_filter.class.js
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
(function(global) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var fabric = global.fabric || (global.fabric = { }),
|
||||
extend = fabric.util.object.extend;
|
||||
|
||||
/**
|
||||
* Mask filter class
|
||||
* @class fabric.Image.filters.Mask
|
||||
* @memberOf fabric.Image.filters
|
||||
* @extends fabric.Image.filters.BaseFilter
|
||||
*/
|
||||
fabric.Image.filters.Mask = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Mask.prototype */ {
|
||||
|
||||
/**
|
||||
* Filter type
|
||||
* @param {String} type
|
||||
* @default
|
||||
*/
|
||||
type: 'Mask',
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @memberOf fabric.Image.filters.Mask.prototype
|
||||
* @param {Object} [options] Options object
|
||||
*/
|
||||
initialize: function(options) {
|
||||
options = options || { };
|
||||
|
||||
this.mask = options.mask;
|
||||
this.channel = [ 0, 1, 2, 3 ].indexOf(options.channel) > -1 ? options.channel : 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Applies filter to canvas element
|
||||
* @param {Object} canvasEl Canvas element to apply filter to
|
||||
*/
|
||||
applyTo: function(canvasEl) {
|
||||
if (!this.mask) return;
|
||||
|
||||
var context = canvasEl.getContext('2d'),
|
||||
imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
|
||||
data = imageData.data,
|
||||
maskEl = this.mask.getElement(),
|
||||
maskCanvasEl = fabric.util.createCanvasElement(),
|
||||
channel = this.channel,
|
||||
i,
|
||||
iLen = imageData.width * imageData.height * 4;
|
||||
|
||||
maskCanvasEl.width = maskEl.width;
|
||||
maskCanvasEl.height = maskEl.height;
|
||||
|
||||
maskCanvasEl.getContext('2d').drawImage(maskEl, 0, 0, maskEl.width, maskEl.height);
|
||||
|
||||
var maskImageData = maskCanvasEl.getContext('2d').getImageData(0, 0, maskEl.width, maskEl.height),
|
||||
maskData = maskImageData.data;
|
||||
|
||||
for (i = 0; i < iLen; i += 4) {
|
||||
data[i + 3] = maskData[i + channel];
|
||||
}
|
||||
|
||||
context.putImageData(imageData, 0, 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns object representation of an instance
|
||||
* @return {Object} Object representation of an instance
|
||||
*/
|
||||
toObject: function() {
|
||||
return extend(this.callSuper('toObject'), {
|
||||
mask: this.mask.toObject(),
|
||||
channel: this.channel
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns filter instance from an object representation
|
||||
* @static
|
||||
* @param {Object} object Object to create an instance from
|
||||
* @param {Function} [callback] Callback to invoke when a mask filter instance is created
|
||||
*/
|
||||
fabric.Image.filters.Mask.fromObject = function(object, callback) {
|
||||
var img = fabric.document.createElement('img'),
|
||||
src = object.mask.src;
|
||||
|
||||
/** @ignore */
|
||||
img.onload = function() {
|
||||
object.mask = new fabric.Image(img, object.mask);
|
||||
|
||||
callback && callback(new fabric.Image.filters.Mask(object));
|
||||
img = img.onload = img.onerror = null;
|
||||
};
|
||||
|
||||
/** @ignore */
|
||||
img.onerror = function() {
|
||||
fabric.log('Error loading ' + img.src);
|
||||
callback && callback(null, true);
|
||||
img = img.onload = img.onerror = null;
|
||||
};
|
||||
|
||||
img.src = src;
|
||||
};
|
||||
|
||||
/**
|
||||
* Indicates that instances of this type are async
|
||||
* @static
|
||||
* @type Boolean
|
||||
* @default
|
||||
*/
|
||||
fabric.Image.filters.Mask.async = true;
|
||||
|
||||
})(typeof exports !== 'undefined' ? exports : this);
|
||||
|
|
@ -79,7 +79,7 @@
|
|||
|
||||
/**
|
||||
* Returns original size of an image
|
||||
* @return {Object} object with "width" and "height" properties
|
||||
* @return {Object} Object with "width" and "height" properties
|
||||
*/
|
||||
getOriginalSize: function() {
|
||||
var element = this.getElement();
|
||||
|
|
@ -181,7 +181,7 @@
|
|||
|
||||
/**
|
||||
* Returns object representation of an instance
|
||||
* @param {Array} propertiesToInclude
|
||||
* @param {Array} propertiesToInclude Any properties that you might want to additionally include in the output
|
||||
* @return {Object} Object representation of an instance
|
||||
*/
|
||||
toObject: function(propertiesToInclude) {
|
||||
|
|
@ -252,7 +252,7 @@
|
|||
/**
|
||||
* Returns a clone of an instance
|
||||
* @param {Function} callback Callback is invoked with a clone as a first argument
|
||||
* @param {Array} propertiesToInclude
|
||||
* @param {Array} propertiesToInclude Any properties that you might want to additionally include in the output
|
||||
*/
|
||||
clone: function(callback, propertiesToInclude) {
|
||||
this.constructor.fromObject(this.toObject(propertiesToInclude), callback);
|
||||
|
|
@ -313,7 +313,7 @@
|
|||
|
||||
/**
|
||||
* @private
|
||||
* @param ctx
|
||||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
*/
|
||||
_render: function(ctx) {
|
||||
ctx.drawImage(
|
||||
|
|
@ -339,7 +339,7 @@
|
|||
* The Image class's initialization method. This method is automatically
|
||||
* called by the constructor.
|
||||
* @private
|
||||
* @param {HTMLImageElement|String} el The element representing the image
|
||||
* @param {HTMLImageElement|String} element The element representing the image
|
||||
*/
|
||||
_initElement: function(element) {
|
||||
this.setElement(fabric.util.getById(element));
|
||||
|
|
@ -359,12 +359,13 @@
|
|||
/**
|
||||
* @private
|
||||
* @param {Object} object Object with filters property
|
||||
* @param {Function} callback Callback to invoke when all fabric.Image.filters instances are created
|
||||
*/
|
||||
_initFilters: function(object) {
|
||||
_initFilters: function(object, callback) {
|
||||
if (object.filters && object.filters.length) {
|
||||
this.filters = object.filters.map(function(filterObj) {
|
||||
return filterObj && fabric.Image.filters[filterObj.type].fromObject(filterObj);
|
||||
});
|
||||
fabric.util.enlivenObjects(object.filters, function(enlivenedObjects) {
|
||||
callback(enlivenedObjects);
|
||||
}, 'fabric.Image.filters');
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -395,6 +396,7 @@
|
|||
* Default CSS class name for canvas
|
||||
* @static
|
||||
* @type String
|
||||
* @default
|
||||
*/
|
||||
fabric.Image.CSS_CANVAS = "canvas-img";
|
||||
|
||||
|
|
@ -416,11 +418,13 @@
|
|||
|
||||
/** @ignore */
|
||||
img.onload = function() {
|
||||
fabric.Image.prototype._initFilters.call(object, object);
|
||||
fabric.Image.prototype._initFilters.call(object, object, function(filters) {
|
||||
object.filters = filters;
|
||||
|
||||
var instance = new fabric.Image(img, object);
|
||||
callback && callback(instance);
|
||||
img = img.onload = img.onerror = null;
|
||||
var instance = new fabric.Image(img, object);
|
||||
callback && callback(instance);
|
||||
img = img.onload = img.onerror = null;
|
||||
});
|
||||
};
|
||||
|
||||
/** @ignore */
|
||||
|
|
@ -481,8 +485,8 @@
|
|||
/**
|
||||
* Indicates compression level used when generating PNG under Node (in applyFilters). Any of 0-9
|
||||
* @static
|
||||
* @default
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
fabric.Image.pngCompression = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -105,13 +105,34 @@
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns klass "Class" object of given fabric.Object type
|
||||
* Returns klass "Class" object of given namespace
|
||||
* @memberOf fabric.util
|
||||
* @param {String} type Type of object (eg. 'circle')
|
||||
* @param {String} namespace Namespace to get klass "Class" object from
|
||||
* @return {Object} klass "Class"
|
||||
*/
|
||||
function getKlass(type) {
|
||||
return fabric[fabric.util.string.camelize(fabric.util.string.capitalize(type))];
|
||||
function getKlass(type, namespace) {
|
||||
return resolveNamespace(namespace)[fabric.util.string.camelize(fabric.util.string.capitalize(type))];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns object of given namespace
|
||||
* @memberOf fabric.util
|
||||
* @param {String} namespace Namespace string e.g. 'fabric.Image.filter' or 'fabric'
|
||||
* @return {Object} Object for given namespace (default fabric)
|
||||
*/
|
||||
function resolveNamespace(namespace) {
|
||||
namespace = namespace || 'fabric';
|
||||
|
||||
var parts = namespace.split('.'),
|
||||
len = parts.length,
|
||||
obj = fabric.window;
|
||||
|
||||
for (var i = 0; i < len; ++i) {
|
||||
obj = obj[parts[i]];
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -143,7 +164,7 @@
|
|||
* @param {Array} objects Objects to enliven
|
||||
* @param {Function} callback Callback to invoke when all objects are created
|
||||
*/
|
||||
function enlivenObjects(objects, callback) {
|
||||
function enlivenObjects(objects, callback, namespace) {
|
||||
|
||||
function onLoaded() {
|
||||
if (++numLoadedObjects === numTotalObjects) {
|
||||
|
|
@ -161,7 +182,7 @@
|
|||
if (!o.type) {
|
||||
return;
|
||||
}
|
||||
var klass = fabric.util.getKlass(o.type);
|
||||
var klass = fabric.util.getKlass(o.type, namespace);
|
||||
if (klass.async) {
|
||||
klass.fromObject(o, function (o, error) {
|
||||
if (!error) {
|
||||
|
|
@ -278,7 +299,7 @@
|
|||
* Creates image element (works on client and node)
|
||||
* @static
|
||||
* @memberOf fabric.util
|
||||
* @return {Image} image element
|
||||
* @return {HTMLImageElement} HTML image element
|
||||
*/
|
||||
function createImage() {
|
||||
return fabric.isLikelyNode
|
||||
|
|
@ -495,6 +516,7 @@
|
|||
fabric.util.getRandomInt = getRandomInt;
|
||||
fabric.util.falseFunction = falseFunction;
|
||||
fabric.util.getKlass = getKlass;
|
||||
fabric.util.resolveNamespace = resolveNamespace;
|
||||
fabric.util.loadImage = loadImage;
|
||||
fabric.util.enlivenObjects = enlivenObjects;
|
||||
fabric.util.groupSVGElements = groupSVGElements;
|
||||
|
|
|
|||
Loading…
Reference in a new issue