NuclearDispersionSystem/ant-design-vue-jeecg/node_modules/@antv/g/lib/shapes/util/arrow.js
2023-09-14 14:47:11 +08:00

150 lines
4.0 KiB
Java

var Format = require('../../util/format');
var PathSegment = require('../util/path-segment');
var PI = Math.PI;
var sin = Math.sin;
var cos = Math.cos;
var atan2 = Math.atan2;
var DEFAULT_LENGTH = 10;
var DEFAULT_ANGLE = PI / 3;
function _addArrow(ctx, attrs, x1, y1, x2, y2, isStart) {
var leftX;
var leftY;
var rightX;
var rightY;
var offsetX;
var offsetY;
var angle;
if (!attrs.fill) {
// 闭合的不绘制箭头
var arrowLength = attrs.arrowLength || DEFAULT_LENGTH;
var arrowAngle = attrs.arrowAngle ? attrs.arrowAngle * PI / 180 : DEFAULT_ANGLE; // 转换为弧
// Calculate angle
angle = atan2(y1 - y2, x1 - x2);
/* // Adjust angle correctly
angle -= PI;*/
// Calculate offset to place arrow at edge of path
offsetX = Math.abs(attrs.lineWidth * cos(angle)) / 2;
offsetY = Math.abs(attrs.lineWidth * sin(angle)) / 2;
if (isStart) {
offsetX = -offsetX;
offsetY = -offsetY;
} // Calculate coordinates for left half of arrow
leftX = x2 + arrowLength * cos(angle + arrowAngle / 2);
leftY = y2 + arrowLength * sin(angle + arrowAngle / 2); // Calculate coordinates for right half of arrow
rightX = x2 + arrowLength * cos(angle - arrowAngle / 2);
rightY = y2 + arrowLength * sin(angle - arrowAngle / 2);
ctx.beginPath(); // Draw left half of arrow
ctx.moveTo(leftX - offsetX, leftY - offsetY);
ctx.lineTo(x2 - offsetX, y2 - offsetY); // Draw right half of arrow
ctx.lineTo(rightX - offsetX, rightY - offsetY); // Visually connect arrow to path
ctx.moveTo(x2 - offsetX, y2 - offsetY);
ctx.lineTo(x2 + offsetX, y2 + offsetY); // Move back to end of path
ctx.moveTo(x2, y2);
ctx.stroke();
}
}
function parsePath(attrs) {
var segments = [];
var pathArray = Format.parsePath(attrs.path);
var preSegment;
if (!Array.isArray(pathArray) || pathArray.length === 0 || pathArray[0][0] !== 'M' && pathArray[0][0] !== 'm') {
return false;
}
var count = pathArray.length;
for (var i = 0; i < pathArray.length; i++) {
var item = pathArray[i];
preSegment = new PathSegment(item, preSegment, i === count - 1);
segments.push(preSegment);
}
return segments;
}
/**
* 如果自定义箭头并且有 d 需要做偏移,如果直接画,线条会超出箭头尖端,因此需要根据箭头偏移 d, 返回线需要缩短的距离
* |----------------
* |<|--------------
* |
* @param {Number} x1 起始点 x
* @param {number} y1 起始点 y
* @param {number} x2 箭头作用点 x
* @param {number} y2 箭头作用点 y
* @param {number} d 箭头沿线条方向的偏移距离
* @return {{dx: number, dy: number}} 返回线条偏移距离
*/
function getShortenOffset(x1, y1, x2, y2, d) {
var rad = Math.atan2(y2 - y1, x2 - x1);
return {
dx: cos(rad) * d,
dy: sin(rad) * d
};
}
function _addCustomizedArrow(ctx, attrs, x1, y1, x2, y2, isStart) {
var shape = isStart ? attrs.startArrow : attrs.endArrow;
var d = shape.d;
var x = x2 - x1;
var y = y2 - y1;
var rad = Math.atan2(y, x);
var path = parsePath(shape);
if (!path) {
return;
}
if (d) {
x2 = x2 - cos(rad) * d;
y2 = y2 - sin(rad) * d;
}
ctx.save();
ctx.beginPath();
ctx.translate(x2, y2);
ctx.rotate(rad);
for (var i = 0; i < path.length; i++) {
path[i].draw(ctx);
}
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.fillStyle = ctx.strokeStyle;
ctx.fill();
ctx.restore();
}
module.exports = {
addStartArrow: function addStartArrow(ctx, attrs, x1, y1, x2, y2) {
if (typeof attrs.startArrow === 'object') {
_addCustomizedArrow(ctx, attrs, x1, y1, x2, y2, true);
} else if (attrs.startArrow) {
_addArrow(ctx, attrs, x1, y1, x2, y2, true);
}
},
addEndArrow: function addEndArrow(ctx, attrs, x1, y1, x2, y2) {
if (typeof attrs.endArrow === 'object') {
_addCustomizedArrow(ctx, attrs, x1, y1, x2, y2, false);
} else if (attrs.endArrow) {
_addArrow(ctx, attrs, x1, y1, x2, y2, false);
}
},
getShortenOffset: getShortenOffset
};