- Go backend (server/)
- Frontend (web/, server/static/)
- Database and deployment files
- Scripts and docs
Co-Authored-By: 狸花猫/Claude-Qwen3.6-Plus 🐾
150 lines
5.9 KiB
JavaScript
150 lines
5.9 KiB
JavaScript
import { __extends } from "tslib";
|
||
import Element from './element';
|
||
import { multiplyVec2 } from '../util/matrix';
|
||
var AbstractShape = /** @class */ (function (_super) {
|
||
__extends(AbstractShape, _super);
|
||
function AbstractShape(cfg) {
|
||
return _super.call(this, cfg) || this;
|
||
}
|
||
// 是否在包围盒内
|
||
AbstractShape.prototype._isInBBox = function (refX, refY) {
|
||
var bbox = this.getBBox();
|
||
return bbox.minX <= refX && bbox.maxX >= refX && bbox.minY <= refY && bbox.maxY >= refY;
|
||
};
|
||
/**
|
||
* 属性更改后需要做的事情
|
||
* @protected
|
||
* @param {ShapeAttrs} targetAttrs 渲染的图像属性
|
||
*/
|
||
AbstractShape.prototype.afterAttrsChange = function (targetAttrs) {
|
||
_super.prototype.afterAttrsChange.call(this, targetAttrs);
|
||
this.clearCacheBBox();
|
||
};
|
||
// 计算包围盒时,需要缓存,这是一个高频的操作
|
||
AbstractShape.prototype.getBBox = function () {
|
||
var bbox = this.cfg.bbox;
|
||
if (!bbox) {
|
||
bbox = this.calculateBBox();
|
||
this.set('bbox', bbox);
|
||
}
|
||
return bbox;
|
||
};
|
||
// 计算相对于画布的包围盒
|
||
AbstractShape.prototype.getCanvasBBox = function () {
|
||
var canvasBBox = this.cfg.canvasBBox;
|
||
if (!canvasBBox) {
|
||
canvasBBox = this.calculateCanvasBBox();
|
||
this.set('canvasBBox', canvasBBox);
|
||
}
|
||
return canvasBBox;
|
||
};
|
||
AbstractShape.prototype.applyMatrix = function (matrix) {
|
||
_super.prototype.applyMatrix.call(this, matrix);
|
||
// 清理掉缓存的包围盒
|
||
this.set('canvasBBox', null);
|
||
};
|
||
/**
|
||
* 计算相对于画布的包围盒,默认等同于 bbox
|
||
* @return {BBox} 包围盒
|
||
*/
|
||
AbstractShape.prototype.calculateCanvasBBox = function () {
|
||
var bbox = this.getBBox();
|
||
var totalMatrix = this.getTotalMatrix();
|
||
var minX = bbox.minX, minY = bbox.minY, maxX = bbox.maxX, maxY = bbox.maxY;
|
||
if (totalMatrix) {
|
||
var topLeft = multiplyVec2(totalMatrix, [bbox.minX, bbox.minY]);
|
||
var topRight = multiplyVec2(totalMatrix, [bbox.maxX, bbox.minY]);
|
||
var bottomLeft = multiplyVec2(totalMatrix, [bbox.minX, bbox.maxY]);
|
||
var bottomRight = multiplyVec2(totalMatrix, [bbox.maxX, bbox.maxY]);
|
||
minX = Math.min(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]);
|
||
maxX = Math.max(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]);
|
||
minY = Math.min(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1]);
|
||
maxY = Math.max(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1]);
|
||
}
|
||
var attrs = this.attrs;
|
||
// 如果存在 shadow 则计算 shadow
|
||
if (attrs.shadowColor) {
|
||
var _a = attrs.shadowBlur, shadowBlur = _a === void 0 ? 0 : _a, _b = attrs.shadowOffsetX, shadowOffsetX = _b === void 0 ? 0 : _b, _c = attrs.shadowOffsetY, shadowOffsetY = _c === void 0 ? 0 : _c;
|
||
var shadowLeft = minX - shadowBlur + shadowOffsetX;
|
||
var shadowRight = maxX + shadowBlur + shadowOffsetX;
|
||
var shadowTop = minY - shadowBlur + shadowOffsetY;
|
||
var shadowBottom = maxY + shadowBlur + shadowOffsetY;
|
||
minX = Math.min(minX, shadowLeft);
|
||
maxX = Math.max(maxX, shadowRight);
|
||
minY = Math.min(minY, shadowTop);
|
||
maxY = Math.max(maxY, shadowBottom);
|
||
}
|
||
return {
|
||
x: minX,
|
||
y: minY,
|
||
minX: minX,
|
||
minY: minY,
|
||
maxX: maxX,
|
||
maxY: maxY,
|
||
width: maxX - minX,
|
||
height: maxY - minY,
|
||
};
|
||
};
|
||
/**
|
||
* @protected
|
||
* 清理缓存的 bbox
|
||
*/
|
||
AbstractShape.prototype.clearCacheBBox = function () {
|
||
this.set('bbox', null);
|
||
this.set('canvasBBox', null);
|
||
};
|
||
// 实现接口
|
||
AbstractShape.prototype.isClipShape = function () {
|
||
return this.get('isClipShape');
|
||
};
|
||
/**
|
||
* @protected
|
||
* 不同的图形自己实现是否在图形内部的逻辑,要判断边和填充区域
|
||
* @param {number} refX 相对于图形的坐标 x
|
||
* @param {number} refY 相对于图形的坐标 Y
|
||
* @return {boolean} 点是否在图形内部
|
||
*/
|
||
AbstractShape.prototype.isInShape = function (refX, refY) {
|
||
return false;
|
||
};
|
||
/**
|
||
* 是否仅仅使用 BBox 检测就可以判定拾取到图形
|
||
* 默认是 false,但是有些图形例如 image、marker 等都可直接使用 BBox 的检测而不需要使用图形拾取
|
||
* @return {Boolean} 仅仅使用 BBox 进行拾取
|
||
*/
|
||
AbstractShape.prototype.isOnlyHitBox = function () {
|
||
return false;
|
||
};
|
||
// 不同的 Shape 各自实现
|
||
AbstractShape.prototype.isHit = function (x, y) {
|
||
var startArrowShape = this.get('startArrowShape');
|
||
var endArrowShape = this.get('endArrowShape');
|
||
var vec = [x, y, 1];
|
||
vec = this.invertFromMatrix(vec);
|
||
var refX = vec[0], refY = vec[1];
|
||
var inBBox = this._isInBBox(refX, refY);
|
||
// 跳过图形的拾取,在某些图形中可以省略一倍的检测成本
|
||
if (this.isOnlyHitBox()) {
|
||
return inBBox;
|
||
}
|
||
// 被裁减掉的和不在包围盒内的不进行计算
|
||
if (inBBox && !this.isClipped(refX, refY)) {
|
||
// 对图形进行拾取判断
|
||
if (this.isInShape(refX, refY)) {
|
||
return true;
|
||
}
|
||
// 对起始箭头进行拾取判断
|
||
if (startArrowShape && startArrowShape.isHit(refX, refY)) {
|
||
return true;
|
||
}
|
||
// 对结束箭头进行拾取判断
|
||
if (endArrowShape && endArrowShape.isHit(refX, refY)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
return AbstractShape;
|
||
}(Element));
|
||
export default AbstractShape;
|
||
//# sourceMappingURL=shape.js.map
|