mask.js
2.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/**
* @author NHN Ent. FE Development Team <dl_javascript@nhn.com>
* @fileoverview Mask extending fabric.Image.filters.Mask
*/
import fabric from 'fabric';
/**
* Mask object
* @class Mask
* @extends {fabric.Image.filters.BlendImage}
* @ignore
*/
const Mask = fabric.util.createClass(
fabric.Image.filters.BlendImage,
/** @lends Mask.prototype */ {
/**
* Apply filter to canvas element
* @param {Object} pipelineState - Canvas element to apply filter
* @override
*/
applyTo(pipelineState) {
if (!this.mask) {
return;
}
const canvas = pipelineState.canvasEl;
const { width, height } = canvas;
const maskCanvasEl = this._createCanvasOfMask(width, height);
const ctx = canvas.getContext('2d');
const maskCtx = maskCanvasEl.getContext('2d');
const imageData = ctx.getImageData(0, 0, width, height);
this._drawMask(maskCtx, canvas, ctx);
this._mapData(maskCtx, imageData, width, height);
pipelineState.imageData = imageData;
},
/**
* Create canvas of mask image
* @param {number} width - Width of main canvas
* @param {number} height - Height of main canvas
* @returns {HTMLElement} Canvas element
* @private
*/
_createCanvasOfMask(width, height) {
const maskCanvasEl = fabric.util.createCanvasElement();
maskCanvasEl.width = width;
maskCanvasEl.height = height;
return maskCanvasEl;
},
/**
* Draw mask image on canvas element
* @param {Object} maskCtx - Context of mask canvas
* @private
*/
_drawMask(maskCtx) {
const { mask } = this;
const maskImg = mask.getElement();
const { angle, left, scaleX, scaleY, top } = mask;
maskCtx.save();
maskCtx.translate(left, top);
maskCtx.rotate((angle * Math.PI) / 180);
maskCtx.scale(scaleX, scaleY);
maskCtx.drawImage(maskImg, -maskImg.width / 2, -maskImg.height / 2);
maskCtx.restore();
},
/**
* Map mask image data to source image data
* @param {Object} maskCtx - Context of mask canvas
* @param {Object} imageData - Data of source image
* @param {number} width - Width of main canvas
* @param {number} height - Height of main canvas
* @private
*/
_mapData(maskCtx, imageData, width, height) {
const { data, height: imgHeight, width: imgWidth } = imageData;
const sourceData = data;
const len = imgWidth * imgHeight * 4;
const maskData = maskCtx.getImageData(0, 0, width, height).data;
for (let i = 0; i < len; i += 4) {
sourceData[i + 3] = maskData[i]; // adjust value of alpha data
}
},
}
);
export default Mask;