Files
DredgePos/node_modules/konva/lib/Shape.js
2021-10-23 19:59:20 +10:00

516 lines
21 KiB
JavaScript

import { Konva } from './Global.js';
import { Transform, Util } from './Util.js';
import { Factory } from './Factory.js';
import { Node } from './Node.js';
import { getNumberValidator, getNumberOrAutoValidator, getStringValidator, getBooleanValidator, getStringOrGradientValidator, } from './Validators.js';
import { _registerNode } from './Global.js';
import * as PointerEvents from './PointerEvents.js';
var HAS_SHADOW = 'hasShadow';
var SHADOW_RGBA = 'shadowRGBA';
var patternImage = 'patternImage';
var linearGradient = 'linearGradient';
var radialGradient = 'radialGradient';
let dummyContext;
function getDummyContext() {
if (dummyContext) {
return dummyContext;
}
dummyContext = Util.createCanvasElement().getContext('2d');
return dummyContext;
}
export const shapes = {};
function _fillFunc(context) {
context.fill();
}
function _strokeFunc(context) {
context.stroke();
}
function _fillFuncHit(context) {
context.fill();
}
function _strokeFuncHit(context) {
context.stroke();
}
function _clearHasShadowCache() {
this._clearCache(HAS_SHADOW);
}
function _clearGetShadowRGBACache() {
this._clearCache(SHADOW_RGBA);
}
function _clearFillPatternCache() {
this._clearCache(patternImage);
}
function _clearLinearGradientCache() {
this._clearCache(linearGradient);
}
function _clearRadialGradientCache() {
this._clearCache(radialGradient);
}
export class Shape extends Node {
constructor(config) {
super(config);
let key;
while (true) {
key = Util.getRandomColor();
if (key && !(key in shapes)) {
break;
}
}
this.colorKey = key;
shapes[key] = this;
}
getContext() {
Util.warn('shape.getContext() method is deprecated. Please do not use it.');
return this.getLayer().getContext();
}
getCanvas() {
Util.warn('shape.getCanvas() method is deprecated. Please do not use it.');
return this.getLayer().getCanvas();
}
getSceneFunc() {
return this.attrs.sceneFunc || this['_sceneFunc'];
}
getHitFunc() {
return this.attrs.hitFunc || this['_hitFunc'];
}
hasShadow() {
return this._getCache(HAS_SHADOW, this._hasShadow);
}
_hasShadow() {
return (this.shadowEnabled() &&
this.shadowOpacity() !== 0 &&
!!(this.shadowColor() ||
this.shadowBlur() ||
this.shadowOffsetX() ||
this.shadowOffsetY()));
}
_getFillPattern() {
return this._getCache(patternImage, this.__getFillPattern);
}
__getFillPattern() {
if (this.fillPatternImage()) {
var ctx = getDummyContext();
const pattern = ctx.createPattern(this.fillPatternImage(), this.fillPatternRepeat() || 'repeat');
if (pattern && pattern.setTransform) {
const tr = new Transform();
tr.translate(this.fillPatternX(), this.fillPatternY());
tr.rotate(Konva.getAngle(this.fillPatternRotation()));
tr.scale(this.fillPatternScaleX(), this.fillPatternScaleY());
tr.translate(-1 * this.fillPatternOffsetX(), -1 * this.fillPatternOffsetY());
const m = tr.getMatrix();
pattern.setTransform({
a: m[0],
b: m[1],
c: m[2],
d: m[3],
e: m[4],
f: m[5],
});
}
return pattern;
}
}
_getLinearGradient() {
return this._getCache(linearGradient, this.__getLinearGradient);
}
__getLinearGradient() {
var colorStops = this.fillLinearGradientColorStops();
if (colorStops) {
var ctx = getDummyContext();
var start = this.fillLinearGradientStartPoint();
var end = this.fillLinearGradientEndPoint();
var grd = ctx.createLinearGradient(start.x, start.y, end.x, end.y);
for (var n = 0; n < colorStops.length; n += 2) {
grd.addColorStop(colorStops[n], colorStops[n + 1]);
}
return grd;
}
}
_getRadialGradient() {
return this._getCache(radialGradient, this.__getRadialGradient);
}
__getRadialGradient() {
var colorStops = this.fillRadialGradientColorStops();
if (colorStops) {
var ctx = getDummyContext();
var start = this.fillRadialGradientStartPoint();
var end = this.fillRadialGradientEndPoint();
var grd = ctx.createRadialGradient(start.x, start.y, this.fillRadialGradientStartRadius(), end.x, end.y, this.fillRadialGradientEndRadius());
for (var n = 0; n < colorStops.length; n += 2) {
grd.addColorStop(colorStops[n], colorStops[n + 1]);
}
return grd;
}
}
getShadowRGBA() {
return this._getCache(SHADOW_RGBA, this._getShadowRGBA);
}
_getShadowRGBA() {
if (this.hasShadow()) {
var rgba = Util.colorToRGBA(this.shadowColor());
return ('rgba(' +
rgba.r +
',' +
rgba.g +
',' +
rgba.b +
',' +
rgba.a * (this.shadowOpacity() || 1) +
')');
}
}
hasFill() {
return this._calculate('hasFill', [
'fillEnabled',
'fill',
'fillPatternImage',
'fillLinearGradientColorStops',
'fillRadialGradientColorStops',
], () => {
return (this.fillEnabled() &&
!!(this.fill() ||
this.fillPatternImage() ||
this.fillLinearGradientColorStops() ||
this.fillRadialGradientColorStops()));
});
}
hasStroke() {
return this._calculate('hasStroke', [
'strokeEnabled',
'strokeWidth',
'stroke',
'strokeLinearGradientColorStops',
], () => {
return (this.strokeEnabled() &&
this.strokeWidth() &&
!!(this.stroke() || this.strokeLinearGradientColorStops()));
});
}
hasHitStroke() {
const width = this.hitStrokeWidth();
if (width === 'auto') {
return this.hasStroke();
}
return this.strokeEnabled() && !!width;
}
intersects(point) {
var stage = this.getStage(), bufferHitCanvas = stage.bufferHitCanvas, p;
bufferHitCanvas.getContext().clear();
this.drawHit(bufferHitCanvas, null, true);
p = bufferHitCanvas.context.getImageData(Math.round(point.x), Math.round(point.y), 1, 1).data;
return p[3] > 0;
}
destroy() {
Node.prototype.destroy.call(this);
delete shapes[this.colorKey];
delete this.colorKey;
return this;
}
_useBufferCanvas(forceFill) {
var _a;
if (!this.getStage()) {
return false;
}
const perfectDrawEnabled = (_a = this.attrs.perfectDrawEnabled) !== null && _a !== void 0 ? _a : true;
if (!perfectDrawEnabled) {
return false;
}
const hasFill = forceFill || this.hasFill();
const hasStroke = this.hasStroke();
const isTransparent = this.getAbsoluteOpacity() !== 1;
if (hasFill && hasStroke && isTransparent) {
return true;
}
const hasShadow = this.hasShadow();
const strokeForShadow = this.shadowForStrokeEnabled();
if (hasFill && hasStroke && hasShadow && strokeForShadow) {
return true;
}
return false;
}
setStrokeHitEnabled(val) {
Util.warn('strokeHitEnabled property is deprecated. Please use hitStrokeWidth instead.');
if (val) {
this.hitStrokeWidth('auto');
}
else {
this.hitStrokeWidth(0);
}
}
getStrokeHitEnabled() {
if (this.hitStrokeWidth() === 0) {
return false;
}
else {
return true;
}
}
getSelfRect() {
var size = this.size();
return {
x: this._centroid ? -size.width / 2 : 0,
y: this._centroid ? -size.height / 2 : 0,
width: size.width,
height: size.height,
};
}
getClientRect(config = {}) {
const skipTransform = config.skipTransform;
const relativeTo = config.relativeTo;
const fillRect = this.getSelfRect();
const applyStroke = !config.skipStroke && this.hasStroke();
const strokeWidth = (applyStroke && this.strokeWidth()) || 0;
const fillAndStrokeWidth = fillRect.width + strokeWidth;
const fillAndStrokeHeight = fillRect.height + strokeWidth;
const applyShadow = !config.skipShadow && this.hasShadow();
const shadowOffsetX = applyShadow ? this.shadowOffsetX() : 0;
const shadowOffsetY = applyShadow ? this.shadowOffsetY() : 0;
const preWidth = fillAndStrokeWidth + Math.abs(shadowOffsetX);
const preHeight = fillAndStrokeHeight + Math.abs(shadowOffsetY);
const blurRadius = (applyShadow && this.shadowBlur()) || 0;
const width = preWidth + blurRadius * 2;
const height = preHeight + blurRadius * 2;
let roundingOffset = 0;
if (Math.round(strokeWidth / 2) !== strokeWidth / 2) {
roundingOffset = 1;
}
const rect = {
width: width + roundingOffset,
height: height + roundingOffset,
x: -Math.round(strokeWidth / 2 + blurRadius) +
Math.min(shadowOffsetX, 0) +
fillRect.x,
y: -Math.round(strokeWidth / 2 + blurRadius) +
Math.min(shadowOffsetY, 0) +
fillRect.y,
};
if (!skipTransform) {
return this._transformedRect(rect, relativeTo);
}
return rect;
}
drawScene(can, top) {
var layer = this.getLayer(), canvas = can || layer.getCanvas(), context = canvas.getContext(), cachedCanvas = this._getCanvasCache(), drawFunc = this.getSceneFunc(), hasShadow = this.hasShadow(), stage, bufferCanvas, bufferContext;
var skipBuffer = canvas.isCache;
var cachingSelf = top === this;
if (!this.isVisible() && !cachingSelf) {
return this;
}
if (cachedCanvas) {
context.save();
var m = this.getAbsoluteTransform(top).getMatrix();
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
this._drawCachedSceneCanvas(context);
context.restore();
return this;
}
if (!drawFunc) {
return this;
}
context.save();
if (this._useBufferCanvas() && !skipBuffer) {
stage = this.getStage();
bufferCanvas = stage.bufferCanvas;
bufferContext = bufferCanvas.getContext();
bufferContext.clear();
bufferContext.save();
bufferContext._applyLineJoin(this);
var o = this.getAbsoluteTransform(top).getMatrix();
bufferContext.transform(o[0], o[1], o[2], o[3], o[4], o[5]);
drawFunc.call(this, bufferContext, this);
bufferContext.restore();
var ratio = bufferCanvas.pixelRatio;
if (hasShadow) {
context._applyShadow(this);
}
context._applyOpacity(this);
context._applyGlobalCompositeOperation(this);
context.drawImage(bufferCanvas._canvas, 0, 0, bufferCanvas.width / ratio, bufferCanvas.height / ratio);
}
else {
context._applyLineJoin(this);
if (!cachingSelf) {
var o = this.getAbsoluteTransform(top).getMatrix();
context.transform(o[0], o[1], o[2], o[3], o[4], o[5]);
context._applyOpacity(this);
context._applyGlobalCompositeOperation(this);
}
if (hasShadow) {
context._applyShadow(this);
}
drawFunc.call(this, context, this);
}
context.restore();
return this;
}
drawHit(can, top, skipDragCheck = false) {
if (!this.shouldDrawHit(top, skipDragCheck)) {
return this;
}
var layer = this.getLayer(), canvas = can || layer.hitCanvas, context = canvas && canvas.getContext(), drawFunc = this.hitFunc() || this.sceneFunc(), cachedCanvas = this._getCanvasCache(), cachedHitCanvas = cachedCanvas && cachedCanvas.hit;
if (!this.colorKey) {
Util.warn('Looks like your canvas has a destroyed shape in it. Do not reuse shape after you destroyed it. If you want to reuse shape you should call remove() instead of destroy()');
}
if (cachedHitCanvas) {
context.save();
var m = this.getAbsoluteTransform(top).getMatrix();
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
this._drawCachedHitCanvas(context);
context.restore();
return this;
}
if (!drawFunc) {
return this;
}
context.save();
context._applyLineJoin(this);
const selfCache = this === top;
if (!selfCache) {
var o = this.getAbsoluteTransform(top).getMatrix();
context.transform(o[0], o[1], o[2], o[3], o[4], o[5]);
}
drawFunc.call(this, context, this);
context.restore();
return this;
}
drawHitFromCache(alphaThreshold = 0) {
var cachedCanvas = this._getCanvasCache(), sceneCanvas = this._getCachedSceneCanvas(), hitCanvas = cachedCanvas.hit, hitContext = hitCanvas.getContext(), hitWidth = hitCanvas.getWidth(), hitHeight = hitCanvas.getHeight(), hitImageData, hitData, len, rgbColorKey, i, alpha;
hitContext.clear();
hitContext.drawImage(sceneCanvas._canvas, 0, 0, hitWidth, hitHeight);
try {
hitImageData = hitContext.getImageData(0, 0, hitWidth, hitHeight);
hitData = hitImageData.data;
len = hitData.length;
rgbColorKey = Util._hexToRgb(this.colorKey);
for (i = 0; i < len; i += 4) {
alpha = hitData[i + 3];
if (alpha > alphaThreshold) {
hitData[i] = rgbColorKey.r;
hitData[i + 1] = rgbColorKey.g;
hitData[i + 2] = rgbColorKey.b;
hitData[i + 3] = 255;
}
else {
hitData[i + 3] = 0;
}
}
hitContext.putImageData(hitImageData, 0, 0);
}
catch (e) {
Util.error('Unable to draw hit graph from cached scene canvas. ' + e.message);
}
return this;
}
hasPointerCapture(pointerId) {
return PointerEvents.hasPointerCapture(pointerId, this);
}
setPointerCapture(pointerId) {
PointerEvents.setPointerCapture(pointerId, this);
}
releaseCapture(pointerId) {
PointerEvents.releaseCapture(pointerId, this);
}
}
Shape.prototype._fillFunc = _fillFunc;
Shape.prototype._strokeFunc = _strokeFunc;
Shape.prototype._fillFuncHit = _fillFuncHit;
Shape.prototype._strokeFuncHit = _strokeFuncHit;
Shape.prototype._centroid = false;
Shape.prototype.nodeType = 'Shape';
_registerNode(Shape);
Shape.prototype.eventListeners = {};
Shape.prototype.on.call(Shape.prototype, 'shadowColorChange.konva shadowBlurChange.konva shadowOffsetChange.konva shadowOpacityChange.konva shadowEnabledChange.konva', _clearHasShadowCache);
Shape.prototype.on.call(Shape.prototype, 'shadowColorChange.konva shadowOpacityChange.konva shadowEnabledChange.konva', _clearGetShadowRGBACache);
Shape.prototype.on.call(Shape.prototype, 'fillPriorityChange.konva fillPatternImageChange.konva fillPatternRepeatChange.konva fillPatternScaleXChange.konva fillPatternScaleYChange.konva fillPatternOffsetXChange.konva fillPatternOffsetYChange.konva fillPatternXChange.konva fillPatternYChange.konva fillPatternRotationChange.konva', _clearFillPatternCache);
Shape.prototype.on.call(Shape.prototype, 'fillPriorityChange.konva fillLinearGradientColorStopsChange.konva fillLinearGradientStartPointXChange.konva fillLinearGradientStartPointYChange.konva fillLinearGradientEndPointXChange.konva fillLinearGradientEndPointYChange.konva', _clearLinearGradientCache);
Shape.prototype.on.call(Shape.prototype, 'fillPriorityChange.konva fillRadialGradientColorStopsChange.konva fillRadialGradientStartPointXChange.konva fillRadialGradientStartPointYChange.konva fillRadialGradientEndPointXChange.konva fillRadialGradientEndPointYChange.konva fillRadialGradientStartRadiusChange.konva fillRadialGradientEndRadiusChange.konva', _clearRadialGradientCache);
Factory.addGetterSetter(Shape, 'stroke', undefined, getStringOrGradientValidator());
Factory.addGetterSetter(Shape, 'strokeWidth', 2, getNumberValidator());
Factory.addGetterSetter(Shape, 'fillAfterStrokeEnabled', false);
Factory.addGetterSetter(Shape, 'hitStrokeWidth', 'auto', getNumberOrAutoValidator());
Factory.addGetterSetter(Shape, 'strokeHitEnabled', true, getBooleanValidator());
Factory.addGetterSetter(Shape, 'perfectDrawEnabled', true, getBooleanValidator());
Factory.addGetterSetter(Shape, 'shadowForStrokeEnabled', true, getBooleanValidator());
Factory.addGetterSetter(Shape, 'lineJoin');
Factory.addGetterSetter(Shape, 'lineCap');
Factory.addGetterSetter(Shape, 'sceneFunc');
Factory.addGetterSetter(Shape, 'hitFunc');
Factory.addGetterSetter(Shape, 'dash');
Factory.addGetterSetter(Shape, 'dashOffset', 0, getNumberValidator());
Factory.addGetterSetter(Shape, 'shadowColor', undefined, getStringValidator());
Factory.addGetterSetter(Shape, 'shadowBlur', 0, getNumberValidator());
Factory.addGetterSetter(Shape, 'shadowOpacity', 1, getNumberValidator());
Factory.addComponentsGetterSetter(Shape, 'shadowOffset', ['x', 'y']);
Factory.addGetterSetter(Shape, 'shadowOffsetX', 0, getNumberValidator());
Factory.addGetterSetter(Shape, 'shadowOffsetY', 0, getNumberValidator());
Factory.addGetterSetter(Shape, 'fillPatternImage');
Factory.addGetterSetter(Shape, 'fill', undefined, getStringOrGradientValidator());
Factory.addGetterSetter(Shape, 'fillPatternX', 0, getNumberValidator());
Factory.addGetterSetter(Shape, 'fillPatternY', 0, getNumberValidator());
Factory.addGetterSetter(Shape, 'fillLinearGradientColorStops');
Factory.addGetterSetter(Shape, 'strokeLinearGradientColorStops');
Factory.addGetterSetter(Shape, 'fillRadialGradientStartRadius', 0);
Factory.addGetterSetter(Shape, 'fillRadialGradientEndRadius', 0);
Factory.addGetterSetter(Shape, 'fillRadialGradientColorStops');
Factory.addGetterSetter(Shape, 'fillPatternRepeat', 'repeat');
Factory.addGetterSetter(Shape, 'fillEnabled', true);
Factory.addGetterSetter(Shape, 'strokeEnabled', true);
Factory.addGetterSetter(Shape, 'shadowEnabled', true);
Factory.addGetterSetter(Shape, 'dashEnabled', true);
Factory.addGetterSetter(Shape, 'strokeScaleEnabled', true);
Factory.addGetterSetter(Shape, 'fillPriority', 'color');
Factory.addComponentsGetterSetter(Shape, 'fillPatternOffset', ['x', 'y']);
Factory.addGetterSetter(Shape, 'fillPatternOffsetX', 0, getNumberValidator());
Factory.addGetterSetter(Shape, 'fillPatternOffsetY', 0, getNumberValidator());
Factory.addComponentsGetterSetter(Shape, 'fillPatternScale', ['x', 'y']);
Factory.addGetterSetter(Shape, 'fillPatternScaleX', 1, getNumberValidator());
Factory.addGetterSetter(Shape, 'fillPatternScaleY', 1, getNumberValidator());
Factory.addComponentsGetterSetter(Shape, 'fillLinearGradientStartPoint', [
'x',
'y',
]);
Factory.addComponentsGetterSetter(Shape, 'strokeLinearGradientStartPoint', [
'x',
'y',
]);
Factory.addGetterSetter(Shape, 'fillLinearGradientStartPointX', 0);
Factory.addGetterSetter(Shape, 'strokeLinearGradientStartPointX', 0);
Factory.addGetterSetter(Shape, 'fillLinearGradientStartPointY', 0);
Factory.addGetterSetter(Shape, 'strokeLinearGradientStartPointY', 0);
Factory.addComponentsGetterSetter(Shape, 'fillLinearGradientEndPoint', [
'x',
'y',
]);
Factory.addComponentsGetterSetter(Shape, 'strokeLinearGradientEndPoint', [
'x',
'y',
]);
Factory.addGetterSetter(Shape, 'fillLinearGradientEndPointX', 0);
Factory.addGetterSetter(Shape, 'strokeLinearGradientEndPointX', 0);
Factory.addGetterSetter(Shape, 'fillLinearGradientEndPointY', 0);
Factory.addGetterSetter(Shape, 'strokeLinearGradientEndPointY', 0);
Factory.addComponentsGetterSetter(Shape, 'fillRadialGradientStartPoint', [
'x',
'y',
]);
Factory.addGetterSetter(Shape, 'fillRadialGradientStartPointX', 0);
Factory.addGetterSetter(Shape, 'fillRadialGradientStartPointY', 0);
Factory.addComponentsGetterSetter(Shape, 'fillRadialGradientEndPoint', [
'x',
'y',
]);
Factory.addGetterSetter(Shape, 'fillRadialGradientEndPointX', 0);
Factory.addGetterSetter(Shape, 'fillRadialGradientEndPointY', 0);
Factory.addGetterSetter(Shape, 'fillPatternRotation', 0);
Factory.backCompat(Shape, {
dashArray: 'dash',
getDashArray: 'getDash',
setDashArray: 'getDash',
drawFunc: 'sceneFunc',
getDrawFunc: 'getSceneFunc',
setDrawFunc: 'setSceneFunc',
drawHitFunc: 'hitFunc',
getDrawHitFunc: 'getHitFunc',
setDrawHitFunc: 'setHitFunc',
});