@antv/x6
Version:
JavaScript diagramming library that uses SVG and HTML for rendering
295 lines • 8.31 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.KAPPA = void 0;
exports.sample = sample;
exports.lineToPathData = lineToPathData;
exports.polygonToPathData = polygonToPathData;
exports.polylineToPathData = polylineToPathData;
exports.getPointsFromSvgElement = getPointsFromSvgElement;
exports.circleToPathData = circleToPathData;
exports.ellipseToPathData = ellipseToPathData;
exports.rectangleToPathData = rectangleToPathData;
exports.rectToPathData = rectToPathData;
exports.toPath = toPath;
exports.toPathData = toPathData;
exports.createSlicePathData = createSlicePathData;
const attr_1 = require("./attr");
const elem_1 = require("./elem");
exports.KAPPA = 0.551784;
function getNumbericAttribute(elem, attr, defaultValue = NaN) {
const v = elem.getAttribute(attr);
if (v == null) {
return defaultValue;
}
const n = parseFloat(v);
return Number.isNaN(n) ? defaultValue : n;
}
function sample(elem, interval = 1) {
const length = elem.getTotalLength();
const samples = [];
let distance = 0;
let sample;
while (distance < length) {
sample = elem.getPointAtLength(distance);
samples.push({ distance, x: sample.x, y: sample.y });
distance += interval;
}
return samples;
}
function lineToPathData(line) {
return [
'M',
getNumbericAttribute(line, 'x1'),
getNumbericAttribute(line, 'y1'),
'L',
getNumbericAttribute(line, 'x2'),
getNumbericAttribute(line, 'y2'),
].join(' ');
}
function polygonToPathData(polygon) {
const points = getPointsFromSvgElement(polygon);
if (points.length === 0) {
return null;
}
return `${svgPointsToPath(points)} Z`;
}
function polylineToPathData(polyline) {
const points = getPointsFromSvgElement(polyline);
if (points.length === 0) {
return null;
}
return svgPointsToPath(points);
}
function svgPointsToPath(points) {
const arr = points.map((p) => `${p.x} ${p.y}`);
return `M ${arr.join(' L')}`;
}
function getPointsFromSvgElement(elem) {
const points = [];
const nodePoints = elem.points;
if (nodePoints) {
for (let i = 0, ii = nodePoints.numberOfItems; i < ii; i += 1) {
points.push(nodePoints.getItem(i));
}
}
return points;
}
function circleToPathData(circle) {
const cx = getNumbericAttribute(circle, 'cx', 0);
const cy = getNumbericAttribute(circle, 'cy', 0);
const r = getNumbericAttribute(circle, 'r');
const cd = r * exports.KAPPA; // Control distance.
return [
'M',
cx,
cy - r, // Move to the first point.
'C',
cx + cd,
cy - r,
cx + r,
cy - cd,
cx + r,
cy, // I. Quadrant.
'C',
cx + r,
cy + cd,
cx + cd,
cy + r,
cx,
cy + r, // II. Quadrant.
'C',
cx - cd,
cy + r,
cx - r,
cy + cd,
cx - r,
cy, // III. Quadrant.
'C',
cx - r,
cy - cd,
cx - cd,
cy - r,
cx,
cy - r, // IV. Quadrant.
'Z',
].join(' ');
}
function ellipseToPathData(ellipse) {
const cx = getNumbericAttribute(ellipse, 'cx', 0);
const cy = getNumbericAttribute(ellipse, 'cy', 0);
const rx = getNumbericAttribute(ellipse, 'rx');
const ry = getNumbericAttribute(ellipse, 'ry') || rx;
const cdx = rx * exports.KAPPA; // Control distance x.
const cdy = ry * exports.KAPPA; // Control distance y.
const d = [
'M',
cx,
cy - ry, // Move to the first point.
'C',
cx + cdx,
cy - ry,
cx + rx,
cy - cdy,
cx + rx,
cy, // I. Quadrant.
'C',
cx + rx,
cy + cdy,
cx + cdx,
cy + ry,
cx,
cy + ry, // II. Quadrant.
'C',
cx - cdx,
cy + ry,
cx - rx,
cy + cdy,
cx - rx,
cy, // III. Quadrant.
'C',
cx - rx,
cy - cdy,
cx - cdx,
cy - ry,
cx,
cy - ry, // IV. Quadrant.
'Z',
].join(' ');
return d;
}
function rectangleToPathData(rect) {
return rectToPathData({
x: getNumbericAttribute(rect, 'x', 0),
y: getNumbericAttribute(rect, 'y', 0),
width: getNumbericAttribute(rect, 'width', 0),
height: getNumbericAttribute(rect, 'height', 0),
rx: getNumbericAttribute(rect, 'rx', 0),
ry: getNumbericAttribute(rect, 'ry', 0),
});
}
function rectToPathData(r) {
let d;
const x = r.x;
const y = r.y;
const width = r.width;
const height = r.height;
const topRx = Math.min(r.rx || r['top-rx'] || 0, width / 2);
const bottomRx = Math.min(r.rx || r['bottom-rx'] || 0, width / 2);
const topRy = Math.min(r.ry || r['top-ry'] || 0, height / 2);
const bottomRy = Math.min(r.ry || r['bottom-ry'] || 0, height / 2);
if (topRx || bottomRx || topRy || bottomRy) {
d = [
'M',
x,
y + topRy,
'v',
height - topRy - bottomRy,
'a',
bottomRx,
bottomRy,
0,
0,
0,
bottomRx,
bottomRy,
'h',
width - 2 * bottomRx,
'a',
bottomRx,
bottomRy,
0,
0,
0,
bottomRx,
-bottomRy,
'v',
-(height - bottomRy - topRy),
'a',
topRx,
topRy,
0,
0,
0,
-topRx,
-topRy,
'h',
-(width - 2 * topRx),
'a',
topRx,
topRy,
0,
0,
0,
-topRx,
topRy,
'Z',
];
}
else {
d = ['M', x, y, 'H', x + width, 'V', y + height, 'H', x, 'V', y, 'Z'];
}
return d.join(' ');
}
function toPath(elem) {
const path = (0, elem_1.createSvgElement)('path');
(0, attr_1.attr)(path, (0, attr_1.attr)(elem));
const d = toPathData(elem);
if (d) {
path.setAttribute('d', d);
}
return path;
}
function toPathData(elem) {
const tagName = elem.tagName.toLowerCase();
switch (tagName) {
case 'path':
return elem.getAttribute('d');
case 'line':
return lineToPathData(elem);
case 'polygon':
return polygonToPathData(elem);
case 'polyline':
return polylineToPathData(elem);
case 'ellipse':
return ellipseToPathData(elem);
case 'circle':
return circleToPathData(elem);
case 'rect':
return rectangleToPathData(elem);
default:
break;
}
throw new Error(`"${tagName}" cannot be converted to svg path element.`);
}
// Inspired by d3.js https://github.com/mbostock/d3/blob/master/src/svg/arc.js
function createSlicePathData(innerRadius, outerRadius, startAngle, endAngle) {
const svgArcMax = 2 * Math.PI - 1e-6;
const r0 = innerRadius;
const r1 = outerRadius;
let a0 = startAngle;
let a1 = endAngle;
if (a1 < a0) {
const tmp = a0;
a0 = a1;
a1 = tmp;
}
const da = a1 - a0;
const df = da < Math.PI ? '0' : '1';
const c0 = Math.cos(a0);
const s0 = Math.sin(a0);
const c1 = Math.cos(a1);
const s1 = Math.sin(a1);
return da >= svgArcMax
? r0
? // eslint-disable-next-line
`M0,${r1}A${r1},${r1} 0 1,1 0,${-r1}A${r1},${r1} 0 1,1 0,${r1}M0,${r0}A${r0},${r0} 0 1,0 0,${-r0}A${r0},${r0} 0 1,0 0,${r0}Z`
: // eslint-disable-next-line
`M0,${r1}A${r1},${r1} 0 1,1 0,${-r1}A${r1},${r1} 0 1,1 0,${r1}Z`
: r0
? // eslint-disable-next-line
`M${r1 * c0},${r1 * s0}A${r1},${r1} 0 ${df},1 ${r1 * c1},${r1 * s1}L${r0 * c1},${r0 * s1}A${r0},${r0} 0 ${df},0 ${r0 * c0},${r0 * s0}Z`
: // eslint-disable-next-line
`M${r1 * c0},${r1 * s0}A${r1},${r1} 0 ${df},1 ${r1 * c1},${r1 * s1}L0,0` +
`Z`;
}
//# sourceMappingURL=path.js.map