@visactor/vrender-components
Version:
components library for dp visualization
207 lines (202 loc) • 12.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.Brush = void 0;
const vrender_core_1 = require("@visactor/vrender-core"), vutils_1 = require("@visactor/vutils"), base_1 = require("../core/base"), type_1 = require("./type"), config_1 = require("./config"), register_1 = require("./register"), delayMap = {
debounce: vutils_1.debounce,
throttle: vutils_1.throttle
};
(0, register_1.loadBrushComponent)();
class Brush extends base_1.AbstractComponent {
constructor(attributes, options) {
super((null == options ? void 0 : options.skipDefault) ? attributes : (0, vutils_1.merge)({}, Brush.defaultAttributes, attributes)),
this.name = "brush", this._activeDrawState = !1, this._cacheDrawPoints = [], this._isDrawedBeforeEnd = !1,
this._isDownBeforeUpOutside = !1, this._activeMoveState = !1, this._operatingMaskMoveDx = 0,
this._operatingMaskMoveDy = 0, this._operatingMaskMoveRangeX = [ -1 / 0, 1 / 0 ],
this._operatingMaskMoveRangeY = [ -1 / 0, 1 / 0 ], this._brushMaskAABBBoundsDict = {},
this._onBrushStart = e => {
var _a;
if (this._outOfInteractiveRange(e)) return void (this._isDownBeforeUpOutside = !0);
e.stopPropagation();
const brushMoved = null === (_a = this.attribute.brushMoved) || void 0 === _a || _a;
this._activeMoveState = brushMoved && this._isPosInBrushMask(e), this._activeDrawState = !this._activeMoveState,
this._activeDrawState && this._initDraw(e), this._activeMoveState && this._initMove(e);
}, this._onBrushing = e => {
this._outOfInteractiveRange(e) || ((this._activeDrawState || this._activeMoveState) && e.stopPropagation(),
this._activeDrawState && this._drawing(e), this._activeMoveState && this._moving(e));
}, this._onBrushingWithDelay = 0 === this.attribute.delayTime ? this._onBrushing : delayMap[this.attribute.delayType](this._onBrushing, this.attribute.delayTime),
this._onBrushEnd = e => {
var _a;
if (!this._activeDrawState && !this._activeMoveState) return;
e.preventDefault();
const {removeOnClick: removeOnClick = !0} = this.attribute;
this._activeDrawState && !this._isDrawedBeforeEnd && removeOnClick ? ((null === (_a = this._operatingMask) || void 0 === _a ? void 0 : _a._AABBBounds.empty()) && this._dispatchEvent(type_1.IOperateType.brushClear, {
operateMask: this._operatingMask,
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict,
event: e
}), this._container.incrementalClearChild(), this._brushMaskAABBBoundsDict = {}) : (this._activeDrawState && this._dispatchEvent(type_1.IOperateType.drawEnd, {
operateMask: this._operatingMask,
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict,
event: e
}), this._activeMoveState && this._dispatchEvent(type_1.IOperateType.moveEnd, {
operateMask: this._operatingMask,
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict,
event: e
})), this._activeDrawState = !1, this._activeMoveState = !1, this._isDrawedBeforeEnd = !1,
this._operatingMask && this._operatingMask.setAttribute("pickable", !1);
}, this._onBrushClear = e => {
e.preventDefault();
const {removeOnClick: removeOnClick = !0} = this.attribute;
this._isDownBeforeUpOutside && removeOnClick && (this._dispatchEvent(type_1.IOperateType.brushClear, {
operateMask: this._operatingMask,
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict,
event: e
}), this._container.incrementalClearChild(), this._brushMaskAABBBoundsDict = {}),
this._activeDrawState = !1, this._activeMoveState = !1, this._isDrawedBeforeEnd = !1,
this._isDownBeforeUpOutside = !1, this._operatingMask && this._operatingMask.setAttribute("pickable", !1);
};
}
_bindBrushEvents() {
if (this.attribute.disableTriggerEvent) return;
const {trigger: trigger = config_1.DEFAULT_BRUSH_ATTRIBUTES.trigger, updateTrigger: updateTrigger = config_1.DEFAULT_BRUSH_ATTRIBUTES.updateTrigger, endTrigger: endTrigger = config_1.DEFAULT_BRUSH_ATTRIBUTES.endTrigger, resetTrigger: resetTrigger = config_1.DEFAULT_BRUSH_ATTRIBUTES.resetTrigger} = this.attribute;
(0, vutils_1.array)(trigger).forEach((t => vrender_core_1.vglobal.addEventListener(t, this._onBrushStart))),
(0, vutils_1.array)(updateTrigger).forEach((t => this.stage.addEventListener(t, this._onBrushingWithDelay))),
(0, vutils_1.array)(endTrigger).forEach((t => this.stage.addEventListener(t, this._onBrushEnd))),
(0, vutils_1.array)(resetTrigger).forEach((t => this.stage.addEventListener(t, this._onBrushClear)));
}
_isPosInBrushMask(e) {
const pos = this.eventPosToStagePos(e), brushMasks = this._container.getChildren();
for (let i = 0; i < brushMasks.length; i++) {
const {points: points = [], dx: dx = 0, dy: dy = 0} = brushMasks[i].attribute, pointsConsiderOffset = points.map((point => ({
x: point.x + dx,
y: point.y + dy
})));
if ((0, vutils_1.polygonContainPoint)(pointsConsiderOffset, pos.x, pos.y)) return this._operatingMask = brushMasks[i],
!0;
}
return !1;
}
_initDraw(e) {
const {brushMode: brushMode} = this.attribute, pos = this.eventPosToStagePos(e);
this._cacheDrawPoints = [ pos ], this._isDrawedBeforeEnd = !1, "single" === brushMode && (this._brushMaskAABBBoundsDict = {},
this._container.incrementalClearChild()), this._addBrushMask(), this._dispatchEvent(type_1.IOperateType.drawStart, {
operateMask: this._operatingMask,
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict,
event: e
});
}
_initMove(e) {
var _a, _b;
this._cacheMovePoint = this.eventPosToStagePos(e), this._operatingMaskMoveDx = null !== (_a = this._operatingMask.attribute.dx) && void 0 !== _a ? _a : 0,
this._operatingMaskMoveDy = null !== (_b = this._operatingMask.attribute.dy) && void 0 !== _b ? _b : 0;
const {interactiveRange: interactiveRange} = this.attribute, {minY: minY = -1 / 0, maxY: maxY = 1 / 0, minX: minX = -1 / 0, maxX: maxX = 1 / 0} = interactiveRange, {x1: x1, x2: x2, y1: y1, y2: y2} = this._operatingMask.globalAABBBounds, minMoveStepX = minX - x1, maxMoveStepX = maxX - x2, minMoveStepY = minY - y1, maxMoveStepY = maxY - y2;
this._operatingMaskMoveRangeX = [ minMoveStepX, maxMoveStepX ], this._operatingMaskMoveRangeY = [ minMoveStepY, maxMoveStepY ],
this._operatingMask.setAttribute("pickable", !0), this._dispatchEvent(type_1.IOperateType.moveStart, {
operateMask: this._operatingMask,
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict,
event: e
});
}
_drawing(e) {
var _a, _b;
const pos = this.eventPosToStagePos(e), {sizeThreshold: sizeThreshold = config_1.DEFAULT_SIZE_THRESHOLD, brushType: brushType} = this.attribute, cacheLength = this._cacheDrawPoints.length;
if (cacheLength > 0) {
const lastPos = null !== (_a = this._cacheDrawPoints[this._cacheDrawPoints.length - 1]) && void 0 !== _a ? _a : {};
if (pos.x === lastPos.x && pos.y === lastPos.y) return;
}
"polygon" === brushType || cacheLength <= 1 ? this._cacheDrawPoints.push(pos) : this._cacheDrawPoints[cacheLength - 1] = pos;
const maskPoints = this._computeMaskPoints();
this._operatingMask.setAttribute("points", maskPoints);
const {x1: x1 = 0, x2: x2 = 0, y1: y1 = 0, y2: y2 = 0} = null === (_b = this._operatingMask) || void 0 === _b ? void 0 : _b._AABBBounds;
this._isDrawedBeforeEnd = !this._operatingMask._AABBBounds.empty() && !!(Math.abs(x2 - x1) > sizeThreshold || Math.abs(y1 - y2) > sizeThreshold),
this._isDrawedBeforeEnd && (this._brushMaskAABBBoundsDict[this._operatingMask.name] = this._operatingMask.AABBBounds,
this._dispatchEvent(type_1.IOperateType.drawing, {
operateMask: this._operatingMask,
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict,
event: e
}));
}
_moving(e) {
const startPos = this._cacheMovePoint, pos = this.eventPosToStagePos(e);
if (pos.x === (null == startPos ? void 0 : startPos.x) && pos.y === (null == startPos ? void 0 : startPos.y)) return;
const moveStepX = pos.x - startPos.x, moveStepY = pos.y - startPos.y, moveX = Math.min(this._operatingMaskMoveRangeX[1], Math.max(this._operatingMaskMoveRangeX[0], moveStepX)) + this._operatingMaskMoveDx, moveY = Math.min(this._operatingMaskMoveRangeY[1], Math.max(this._operatingMaskMoveRangeY[0], moveStepY)) + this._operatingMaskMoveDy;
this._operatingMask.setAttributes({
dx: moveX,
dy: moveY
}), this._brushMaskAABBBoundsDict[this._operatingMask.name] = this._operatingMask.AABBBounds,
this._dispatchEvent(type_1.IOperateType.moving, {
operateMask: this._operatingMask,
operatedMaskAABBBounds: this._brushMaskAABBBoundsDict,
event: e
});
}
_computeMaskPoints() {
const {brushType: brushType, xRange: xRange = [ 0, 0 ], yRange: yRange = [ 0, 0 ]} = this.attribute;
let maskPoints = [];
const startPoint = this._cacheDrawPoints[0], endPoint = this._cacheDrawPoints[this._cacheDrawPoints.length - 1];
return maskPoints = "rect" === brushType ? [ startPoint, {
x: endPoint.x,
y: startPoint.y
}, endPoint, {
x: startPoint.x,
y: endPoint.y
} ] : "x" === brushType ? [ {
x: startPoint.x,
y: yRange[0]
}, {
x: endPoint.x,
y: yRange[0]
}, {
x: endPoint.x,
y: yRange[1]
}, {
x: startPoint.x,
y: yRange[1]
} ] : "y" === brushType ? [ {
x: xRange[0],
y: startPoint.y
}, {
x: xRange[0],
y: endPoint.y
}, {
x: xRange[1],
y: endPoint.y
}, {
x: xRange[1],
y: startPoint.y
} ] : (0, vutils_1.cloneDeep)(this._cacheDrawPoints), maskPoints;
}
_addBrushMask() {
var _a;
const {brushStyle: brushStyle, hasMask: hasMask} = this.attribute, brushMask = vrender_core_1.graphicCreator.polygon(Object.assign(Object.assign({
points: (0, vutils_1.cloneDeep)(this._cacheDrawPoints),
cursor: "move",
pickable: !1
}, brushStyle), {
opacity: hasMask ? null !== (_a = brushStyle.opacity) && void 0 !== _a ? _a : 1 : 0
}));
brushMask.name = `brush-${Date.now()}`, this._operatingMask = brushMask, this._container.add(brushMask),
this._brushMaskAABBBoundsDict[brushMask.name] = brushMask.AABBBounds;
}
_outOfInteractiveRange(e) {
const {interactiveRange: interactiveRange} = this.attribute, {minY: minY = -1 / 0, maxY: maxY = 1 / 0, minX: minX = -1 / 0, maxX: maxX = 1 / 0} = interactiveRange, pos = this.eventPosToStagePos(e);
return pos.x > maxX || pos.x < minX || pos.y > maxY || pos.y < minY;
}
eventPosToStagePos(e) {
return this.stage.eventPointTransform(e);
}
render() {
this._bindBrushEvents();
const group = this.createOrUpdateChild("brush-container", {}, "group");
this._container = group;
}
releaseBrushEvents() {
const {delayType: delayType = "throttle", delayTime: delayTime = 0, trigger: trigger = config_1.DEFAULT_BRUSH_ATTRIBUTES.trigger, updateTrigger: updateTrigger = config_1.DEFAULT_BRUSH_ATTRIBUTES.updateTrigger, endTrigger: endTrigger = config_1.DEFAULT_BRUSH_ATTRIBUTES.endTrigger, resetTrigger: resetTrigger = config_1.DEFAULT_BRUSH_ATTRIBUTES.resetTrigger} = this.attribute;
(0, vutils_1.array)(trigger).forEach((t => vrender_core_1.vglobal.removeEventListener(t, this._onBrushStart))),
(0, vutils_1.array)(updateTrigger).forEach((t => this.stage.removeEventListener(t, this._onBrushingWithDelay))),
(0, vutils_1.array)(endTrigger).forEach((t => this.stage.removeEventListener(t, this._onBrushEnd))),
(0, vutils_1.array)(resetTrigger).forEach((t => this.stage.removeEventListener(t, this._onBrushClear)));
}
}
exports.Brush = Brush, Brush.defaultAttributes = config_1.DEFAULT_BRUSH_ATTRIBUTES;
//# sourceMappingURL=brush.js.map