@antv/x6
Version:
JavaScript diagramming library that uses SVG and HTML for rendering.
93 lines • 4.54 kB
JavaScript
import { Point } from '../../geometry';
import { attr } from './attr';
import { getBBox, getTransformToElement } from './geom';
import { createSVGTransform, parseTransformString, transformStringToMatrix, matrixToTransformString, } from './matrix';
export function transform(elem, matrix, options = {}) {
if (matrix == null) {
return transformStringToMatrix(attr(elem, 'transform'));
}
if (options.absolute) {
elem.setAttribute('transform', matrixToTransformString(matrix));
return;
}
const transformList = elem.transform;
const svgTransform = createSVGTransform(matrix);
transformList.baseVal.appendItem(svgTransform);
}
export function translate(elem, tx, ty = 0, options = {}) {
let transformAttr = attr(elem, 'transform');
const transform = parseTransformString(transformAttr);
if (tx == null) {
return transform.translation;
}
transformAttr = transform.raw;
transformAttr = transformAttr.replace(/translate\([^)]*\)/g, '').trim();
const newTx = options.absolute ? tx : transform.translation.tx + tx;
const newTy = options.absolute ? ty : transform.translation.ty + ty;
const newTranslate = `translate(${newTx},${newTy})`;
// Note that `translate()` is always the first transformation. This is
// usually the desired case.
elem.setAttribute('transform', `${newTranslate} ${transformAttr}`.trim());
}
export function rotate(elem, angle, cx, cy, options = {}) {
let transformAttr = attr(elem, 'transform');
const transform = parseTransformString(transformAttr);
if (angle == null) {
return transform.rotation;
}
transformAttr = transform.raw;
transformAttr = transformAttr.replace(/rotate\([^)]*\)/g, '').trim();
angle %= 360; // eslint-disable-line
const newAngle = options.absolute ? angle : transform.rotation.angle + angle;
const newOrigin = cx != null && cy != null ? `,${cx},${cy}` : '';
const newRotate = `rotate(${newAngle}${newOrigin})`;
elem.setAttribute('transform', `${transformAttr} ${newRotate}`.trim());
}
export function scale(elem, sx, sy) {
let transformAttr = attr(elem, 'transform');
const transform = parseTransformString(transformAttr);
if (sx == null) {
return transform.scale;
}
sy = sy == null ? sx : sy; // eslint-disable-line
transformAttr = transform.raw;
transformAttr = transformAttr.replace(/scale\([^)]*\)/g, '').trim();
const newScale = `scale(${sx},${sy})`;
elem.setAttribute('transform', `${transformAttr} ${newScale}`.trim());
}
export function translateAndAutoOrient(elem, position, reference, target) {
const pos = Point.create(position);
const ref = Point.create(reference);
if (!target) {
const svg = elem instanceof SVGSVGElement ? elem : elem.ownerSVGElement;
target = svg; // eslint-disable-line
}
// Clean-up previously set transformations except the scale.
// If we didn't clean up the previous transformations then they'd
// add up with the old ones. Scale is an exception as it doesn't
// add up, consider: `this.scale(2).scale(2).scale(2)`. The result
// is that the element is scaled by the factor 2, not 8.
const s = scale(elem);
elem.setAttribute('transform', '');
const bbox = getBBox(elem, { target }).scale(s.sx, s.sy);
// 1. Translate to origin.
const translateToOrigin = createSVGTransform();
translateToOrigin.setTranslate(-bbox.x - bbox.width / 2, -bbox.y - bbox.height / 2);
// 2. Rotate around origin.
const rotateAroundOrigin = createSVGTransform();
const angle = pos.angleBetween(ref, pos.clone().translate(1, 0));
if (angle)
rotateAroundOrigin.setRotate(angle, 0, 0);
// 3. Translate to the `position` + the offset (half my width)
// towards the `reference` point.
const translateFromOrigin = createSVGTransform();
const finalPosition = pos.clone().move(ref, bbox.width / 2);
translateFromOrigin.setTranslate(2 * pos.x - finalPosition.x, 2 * pos.y - finalPosition.y);
// 4. Get the current transformation matrix of this node
const ctm = getTransformToElement(elem, target);
// 5. Apply transformations and the scale
const transform = createSVGTransform();
transform.setMatrix(translateFromOrigin.matrix.multiply(rotateAroundOrigin.matrix.multiply(translateToOrigin.matrix.multiply(ctm.scale(s.sx, s.sy)))));
elem.setAttribute('transform', matrixToTransformString(transform.matrix));
}
//# sourceMappingURL=transform.js.map