UNPKG

fabric

Version:

Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.

186 lines (178 loc) 5.05 kB
import { defineProperty as _defineProperty } from '../../_virtual/_rollupPluginBabelHelpers.mjs'; import { Group } from '../shapes/Group.mjs'; import { Shadow } from '../Shadow.mjs'; import { Rect } from '../shapes/Rect.mjs'; import { getRandomInt } from '../util/internals/getRandomInt.mjs'; import { BaseBrush } from './BaseBrush.mjs'; import { CENTER } from '../constants.mjs'; /** * * @param rects * @returns */ function getUniqueRects(rects) { const uniqueRects = {}; const uniqueRectsArray = []; for (let i = 0, key; i < rects.length; i++) { key = "".concat(rects[i].left).concat(rects[i].top); if (!uniqueRects[key]) { uniqueRects[key] = true; uniqueRectsArray.push(rects[i]); } } return uniqueRectsArray; } class SprayBrush extends BaseBrush { /** * Constructor * @param {Canvas} canvas * @return {SprayBrush} Instance of a spray brush */ constructor(canvas) { super(canvas); /** * Width of a spray * @type Number * @default */ _defineProperty(this, "width", 10); /** * Density of a spray (number of dots per chunk) * @type Number * @default */ _defineProperty(this, "density", 20); /** * Width of spray dots * @type Number * @default */ _defineProperty(this, "dotWidth", 1); /** * Width variance of spray dots * @type Number * @default */ _defineProperty(this, "dotWidthVariance", 1); /** * Whether opacity of a dot should be random * @type Boolean * @default */ _defineProperty(this, "randomOpacity", false); /** * Whether overlapping dots (rectangles) should be removed (for performance reasons) * @type Boolean * @default */ _defineProperty(this, "optimizeOverlapping", true); this.sprayChunks = []; this.sprayChunk = []; } /** * Invoked on mouse down * @param {Point} pointer */ onMouseDown(pointer) { this.sprayChunks = []; this.canvas.clearContext(this.canvas.contextTop); this._setShadow(); this.addSprayChunk(pointer); this.renderChunck(this.sprayChunk); } /** * Invoked on mouse move * @param {Point} pointer */ onMouseMove(pointer) { if (this.limitedToCanvasSize === true && this._isOutSideCanvas(pointer)) { return; } this.addSprayChunk(pointer); this.renderChunck(this.sprayChunk); } /** * Invoked on mouse up */ onMouseUp() { const originalRenderOnAddRemove = this.canvas.renderOnAddRemove; this.canvas.renderOnAddRemove = false; const rects = []; for (let i = 0; i < this.sprayChunks.length; i++) { const sprayChunk = this.sprayChunks[i]; for (let j = 0; j < sprayChunk.length; j++) { const chunck = sprayChunk[j]; const rect = new Rect({ width: chunck.width, height: chunck.width, left: chunck.x + 1, top: chunck.y + 1, originX: CENTER, originY: CENTER, fill: this.color }); rects.push(rect); } } const group = new Group(this.optimizeOverlapping ? getUniqueRects(rects) : rects, { objectCaching: true, subTargetCheck: false, interactive: false }); this.shadow && group.set('shadow', new Shadow(this.shadow)); this.canvas.fire('before:path:created', { path: group }); this.canvas.add(group); this.canvas.fire('path:created', { path: group }); this.canvas.clearContext(this.canvas.contextTop); this._resetShadow(); this.canvas.renderOnAddRemove = originalRenderOnAddRemove; this.canvas.requestRenderAll(); } renderChunck(sprayChunck) { const ctx = this.canvas.contextTop; ctx.fillStyle = this.color; this._saveAndTransform(ctx); for (let i = 0; i < sprayChunck.length; i++) { const point = sprayChunck[i]; ctx.globalAlpha = point.opacity; ctx.fillRect(point.x, point.y, point.width, point.width); } ctx.restore(); } /** * Render all spray chunks */ _render() { const ctx = this.canvas.contextTop; ctx.fillStyle = this.color; this._saveAndTransform(ctx); for (let i = 0; i < this.sprayChunks.length; i++) { this.renderChunck(this.sprayChunks[i]); } ctx.restore(); } /** * @param {Point} pointer */ addSprayChunk(pointer) { this.sprayChunk = []; const radius = this.width / 2; for (let i = 0; i < this.density; i++) { this.sprayChunk.push({ x: getRandomInt(pointer.x - radius, pointer.x + radius), y: getRandomInt(pointer.y - radius, pointer.y + radius), width: this.dotWidthVariance ? getRandomInt( // bottom clamp width to 1 Math.max(1, this.dotWidth - this.dotWidthVariance), this.dotWidth + this.dotWidthVariance) : this.dotWidth, opacity: this.randomOpacity ? getRandomInt(0, 100) / 100 : 1 }); } this.sprayChunks.push(this.sprayChunk); } } export { SprayBrush }; //# sourceMappingURL=SprayBrush.mjs.map