sunzi-fabric
Version:
made by fabric@3.2.0
122 lines (108 loc) • 3.58 kB
JavaScript
/**
* CircleBrush class
* @class fabric.CircleBrush
*/
var ErasureGroup = fabric.util.createClass(fabric.Group, /** @lends fabric.ErasureGroup.prototype */ {
/**
* Width of a brush
* @type Number
* @default
*/
original: null,
/**
* Width of a brush
* @type Number
* @default
*/
erasedPath: null,
/**
* Constructor
* @param {fabric.Canvas} canvas
* @return {fabric.CircleBrush} Instance of a circle brush
*/
initialize: function(original, erasedPath, options, isAlreadyGrouped) {
this.original = original;
this.erasedPath = erasedPath;
this.callSuper('initialize', [this.original, this.erasedPath], options, isAlreadyGrouped);
},
_calcBounds: function (onlyWidthHeight) {
var aX = [],
aY = [],
props = ['tr', 'br', 'bl', 'tl'],
jLen = props.length,
ignoreZoom = true;
var o = this.original;
o.setCoords(ignoreZoom);
for (var j = 0; j < jLen; j++) {
var prop = props[j];
aX.push(o.oCoords[prop].x);
aY.push(o.oCoords[prop].y);
}
this._getBounds(aX, aY, onlyWidthHeight);
}
});
/*
* Note1: Might not work with versions other than 3.1.0
*
* Made it so that the path will be 'merged' with other objects
* into a customized group and has a 'destination-out' composition
*/
fabric.ErasureBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fabric.ErasureBrush.prototype */ {
/**
* On mouseup after drawing the path on contextTop canvas
* we use the points captured to create an new fabric path object
* and add it to the fabric canvas.
*/
_finalizeAndAddPath: function () {
var ctx = this.canvas.contextTop;
ctx.closePath();
if (this.decimate) {
this._points = this.decimatePoints(this._points, this.decimate);
}
var pathData = this.convertPointsToSVGPath(this._points).join('');
if (pathData === 'M 0 0 Q 0 0 0 0 L 0 0') {
// do not create 0 width/height paths, as they are
// rendered inconsistently across browsers
// Firefox 4, for example, renders a dot,
// whereas Chrome 10 renders nothing
this.canvas.requestRenderAll();
return;
}
// use globalCompositeOperation to 'fake' eraser
var path = this.createPath(pathData);
path.globalCompositeOperation = 'destination-out';
path.selectable = false;
path.evented = false;
path.absolutePositioned = true;
// grab all the objects that intersects with the path
var objects = this.canvas.getObjects().filter(function(obj) {
// if (obj instanceof fabric.Textbox) return false;
// if (obj instanceof fabric.IText) return false;
if (!obj.intersectsWithObject(path)) return false;
return true;
}.bind(this));
if (objects.length > 0) {
// merge those objects into a group
var mergedGroup = new fabric.Group(objects);
var newPath = new ErasureGroup(mergedGroup, path);
var left = newPath.left;
var top = newPath.top;
// convert it into a dataURL, then back to a fabric image
var newData = newPath.toDataURL({
withoutTransform: true
});
fabric.Image.fromURL(newData, function(fabricImage) {
fabricImage.set({
left: left,
top: top,
});
// remove the old objects then add the new image
this.canvas.remove.apply(this.canvas, objects);
this.canvas.add(fabricImage);
}.bind(this));
}
this.canvas.clearContext(this.canvas.contextTop);
this.canvas.renderAll();
this._resetShadow();
},
});