- Go backend (server/)
- Frontend (web/, server/static/)
- Database and deployment files
- Scripts and docs
Co-Authored-By: 狸花猫/Claude-Qwen3.6-Plus 🐾
264 lines
9.8 KiB
JavaScript
264 lines
9.8 KiB
JavaScript
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
var tslib_1 = require("tslib");
|
||
var g_math_1 = require("@antv/g-math");
|
||
var util_1 = require("@antv/util");
|
||
var base_1 = require("./base");
|
||
var path_util_1 = require("@antv/path-util");
|
||
var draw_1 = require("../util/draw");
|
||
var point_in_path_1 = require("../util/in-path/point-in-path");
|
||
var polygon_1 = require("../util/in-path/polygon");
|
||
var path_1 = require("../util/path");
|
||
var ArrowUtil = require("../util/arrow");
|
||
// 是否在多个多边形内部
|
||
function isInPolygons(polygons, x, y) {
|
||
var isHit = false;
|
||
for (var i = 0; i < polygons.length; i++) {
|
||
var points = polygons[i];
|
||
isHit = polygon_1.default(points, x, y);
|
||
if (isHit) {
|
||
break;
|
||
}
|
||
}
|
||
return isHit;
|
||
}
|
||
var Path = /** @class */ (function (_super) {
|
||
tslib_1.__extends(Path, _super);
|
||
function Path() {
|
||
return _super !== null && _super.apply(this, arguments) || this;
|
||
}
|
||
Path.prototype.getDefaultAttrs = function () {
|
||
var attrs = _super.prototype.getDefaultAttrs.call(this);
|
||
return tslib_1.__assign(tslib_1.__assign({}, attrs), { startArrow: false, endArrow: false });
|
||
};
|
||
Path.prototype.initAttrs = function (attrs) {
|
||
this._setPathArr(attrs.path);
|
||
this.setArrow();
|
||
};
|
||
// 更新属性时,检测是否更改了 path
|
||
Path.prototype.onAttrChange = function (name, value, originValue) {
|
||
_super.prototype.onAttrChange.call(this, name, value, originValue);
|
||
if (name === 'path') {
|
||
this._setPathArr(value);
|
||
}
|
||
// 由于箭头的绘制依赖于 line 的诸多 attrs,因此这里不再对每个 attr 进行判断,attr 每次变化都会影响箭头的更新
|
||
this.setArrow();
|
||
};
|
||
// 将 path 转换成绝对路径
|
||
Path.prototype._setPathArr = function (path) {
|
||
// 转换 path 的格式
|
||
this.attrs.path = path_util_1.path2Absolute(path);
|
||
var hasArc = path_1.default.hasArc(path);
|
||
// 为了加速 path 的绘制、拾取和计算,这个地方可以缓存很多东西
|
||
// 这些缓存都是第一次需要时计算和存储,虽然增加了复杂度,但是频繁调用的方法,性能有很大提升
|
||
this.set('hasArc', hasArc);
|
||
this.set('paramsCache', {}); // 清理缓存
|
||
this.set('segments', null); // 延迟生成 path,在动画场景下可能不会有拾取
|
||
this.set('curve', null);
|
||
this.set('tCache', null);
|
||
this.set('totalLength', null);
|
||
};
|
||
Path.prototype.getSegments = function () {
|
||
var segments = this.get('segements');
|
||
if (!segments) {
|
||
segments = path_util_1.path2Segments(this.attr('path'));
|
||
this.set('segments', segments);
|
||
}
|
||
return segments;
|
||
};
|
||
Path.prototype.setArrow = function () {
|
||
var attrs = this.attr();
|
||
var startArrow = attrs.startArrow, endArrow = attrs.endArrow;
|
||
if (startArrow) {
|
||
var tangent = this.getStartTangent();
|
||
ArrowUtil.addStartArrow(this, attrs, tangent[0][0], tangent[0][1], tangent[1][0], tangent[1][1]);
|
||
}
|
||
if (endArrow) {
|
||
var tangent = this.getEndTangent();
|
||
ArrowUtil.addEndArrow(this, attrs, tangent[0][0], tangent[0][1], tangent[1][0], tangent[1][1]);
|
||
}
|
||
};
|
||
Path.prototype.isInStrokeOrPath = function (x, y, isStroke, isFill, lineWidth) {
|
||
var segments = this.getSegments();
|
||
var hasArc = this.get('hasArc');
|
||
var isHit = false;
|
||
if (isStroke) {
|
||
var length_1 = this.getTotalLength();
|
||
isHit = path_1.default.isPointInStroke(segments, lineWidth, x, y, length_1);
|
||
}
|
||
if (!isHit && isFill) {
|
||
if (hasArc) {
|
||
// 存在曲线时,暂时使用 canvas 的 api 计算,后续可以进行多边形切割
|
||
isHit = point_in_path_1.default(this, x, y);
|
||
}
|
||
else {
|
||
var path = this.attr('path');
|
||
var extractResutl = path_1.default.extractPolygons(path);
|
||
// 提取出来的多边形包含闭合的和非闭合的,在这里统一按照多边形处理
|
||
isHit = isInPolygons(extractResutl.polygons, x, y) || isInPolygons(extractResutl.polylines, x, y);
|
||
}
|
||
}
|
||
return isHit;
|
||
};
|
||
Path.prototype.createPath = function (context) {
|
||
var attrs = this.attr();
|
||
var paramsCache = this.get('paramsCache'); // 由于计算圆弧的参数成本很大,所以要缓存
|
||
draw_1.drawPath(this, context, attrs, paramsCache);
|
||
};
|
||
Path.prototype.afterDrawPath = function (context) {
|
||
var startArrowShape = this.get('startArrowShape');
|
||
var endArrowShape = this.get('endArrowShape');
|
||
if (startArrowShape) {
|
||
startArrowShape.draw(context);
|
||
}
|
||
if (endArrowShape) {
|
||
endArrowShape.draw(context);
|
||
}
|
||
};
|
||
/**
|
||
* Get total length of path
|
||
* @return {number} length
|
||
*/
|
||
Path.prototype.getTotalLength = function () {
|
||
var totalLength = this.get('totalLength');
|
||
if (!util_1.isNil(totalLength)) {
|
||
return totalLength;
|
||
}
|
||
this._calculateCurve();
|
||
this._setTcache();
|
||
return this.get('totalLength');
|
||
};
|
||
/**
|
||
* Get point according to ratio
|
||
* @param {number} ratio
|
||
* @return {Point} point
|
||
*/
|
||
Path.prototype.getPoint = function (ratio) {
|
||
var tCache = this.get('tCache');
|
||
if (!tCache) {
|
||
this._calculateCurve();
|
||
this._setTcache();
|
||
tCache = this.get('tCache');
|
||
}
|
||
var subt;
|
||
var index;
|
||
var curve = this.get('curve');
|
||
if (!tCache || tCache.length === 0) {
|
||
if (curve) {
|
||
return {
|
||
x: curve[0][1],
|
||
y: curve[0][2],
|
||
};
|
||
}
|
||
return null;
|
||
}
|
||
util_1.each(tCache, function (v, i) {
|
||
if (ratio >= v[0] && ratio <= v[1]) {
|
||
subt = (ratio - v[0]) / (v[1] - v[0]);
|
||
index = i;
|
||
}
|
||
});
|
||
var seg = curve[index];
|
||
if (util_1.isNil(seg) || util_1.isNil(index)) {
|
||
return null;
|
||
}
|
||
var l = seg.length;
|
||
var nextSeg = curve[index + 1];
|
||
return g_math_1.Cubic.pointAt(seg[l - 2], seg[l - 1], nextSeg[1], nextSeg[2], nextSeg[3], nextSeg[4], nextSeg[5], nextSeg[6], subt);
|
||
};
|
||
Path.prototype._calculateCurve = function () {
|
||
var path = this.attr().path;
|
||
this.set('curve', path_1.default.pathToCurve(path));
|
||
};
|
||
Path.prototype._setTcache = function () {
|
||
var totalLength = 0;
|
||
var tempLength = 0;
|
||
// 每段 curve 对应起止点的长度比例列表,形如: [[0, 0.25], [0.25, 0.6]. [0.6, 0.9], [0.9, 1]]
|
||
var tCache = [];
|
||
var segmentT;
|
||
var segmentL;
|
||
var segmentN;
|
||
var l;
|
||
var curve = this.get('curve');
|
||
if (!curve) {
|
||
return;
|
||
}
|
||
util_1.each(curve, function (segment, i) {
|
||
segmentN = curve[i + 1];
|
||
l = segment.length;
|
||
if (segmentN) {
|
||
totalLength +=
|
||
g_math_1.Cubic.length(segment[l - 2], segment[l - 1], segmentN[1], segmentN[2], segmentN[3], segmentN[4], segmentN[5], segmentN[6]) || 0;
|
||
}
|
||
});
|
||
this.set('totalLength', totalLength);
|
||
if (totalLength === 0) {
|
||
this.set('tCache', []);
|
||
return;
|
||
}
|
||
util_1.each(curve, function (segment, i) {
|
||
segmentN = curve[i + 1];
|
||
l = segment.length;
|
||
if (segmentN) {
|
||
segmentT = [];
|
||
segmentT[0] = tempLength / totalLength;
|
||
segmentL = g_math_1.Cubic.length(segment[l - 2], segment[l - 1], segmentN[1], segmentN[2], segmentN[3], segmentN[4], segmentN[5], segmentN[6]);
|
||
// 当 path 不连续时,segmentL 可能为空,为空时需要作为 0 处理
|
||
tempLength += segmentL || 0;
|
||
segmentT[1] = tempLength / totalLength;
|
||
tCache.push(segmentT);
|
||
}
|
||
});
|
||
this.set('tCache', tCache);
|
||
};
|
||
/**
|
||
* Get start tangent vector
|
||
* @return {Array}
|
||
*/
|
||
Path.prototype.getStartTangent = function () {
|
||
var segments = this.getSegments();
|
||
var result;
|
||
if (segments.length > 1) {
|
||
var startPoint = segments[0].currentPoint;
|
||
var endPoint = segments[1].currentPoint;
|
||
var tangent = segments[1].startTangent;
|
||
result = [];
|
||
if (tangent) {
|
||
result.push([startPoint[0] - tangent[0], startPoint[1] - tangent[1]]);
|
||
result.push([startPoint[0], startPoint[1]]);
|
||
}
|
||
else {
|
||
result.push([endPoint[0], endPoint[1]]);
|
||
result.push([startPoint[0], startPoint[1]]);
|
||
}
|
||
}
|
||
return result;
|
||
};
|
||
/**
|
||
* Get end tangent vector
|
||
* @return {Array}
|
||
*/
|
||
Path.prototype.getEndTangent = function () {
|
||
var segments = this.getSegments();
|
||
var length = segments.length;
|
||
var result;
|
||
if (length > 1) {
|
||
var startPoint = segments[length - 2].currentPoint;
|
||
var endPoint = segments[length - 1].currentPoint;
|
||
var tangent = segments[length - 1].endTangent;
|
||
result = [];
|
||
if (tangent) {
|
||
result.push([endPoint[0] - tangent[0], endPoint[1] - tangent[1]]);
|
||
result.push([endPoint[0], endPoint[1]]);
|
||
}
|
||
else {
|
||
result.push([startPoint[0], startPoint[1]]);
|
||
result.push([endPoint[0], endPoint[1]]);
|
||
}
|
||
}
|
||
return result;
|
||
};
|
||
return Path;
|
||
}(base_1.default));
|
||
exports.default = Path;
|
||
//# sourceMappingURL=path.js.map
|