123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.Util = void 0;
- const x6_geometry_1 = require("@antv/x6-geometry");
- const x6_common_1 = require("@antv/x6-common");
- const util_1 = require("../registry/marker/util");
- var Util;
- (function (Util) {
- Util.normalizeMarker = util_1.normalize;
- /**
- * Transforms point by an SVG transformation represented by `matrix`.
- */
- function transformPoint(point, matrix) {
- const ret = x6_common_1.Dom.createSVGPoint(point.x, point.y).matrixTransform(matrix);
- return new x6_geometry_1.Point(ret.x, ret.y);
- }
- Util.transformPoint = transformPoint;
- /**
- * Transforms line by an SVG transformation represented by `matrix`.
- */
- function transformLine(line, matrix) {
- return new x6_geometry_1.Line(transformPoint(line.start, matrix), transformPoint(line.end, matrix));
- }
- Util.transformLine = transformLine;
- /**
- * Transforms polyline by an SVG transformation represented by `matrix`.
- */
- function transformPolyline(polyline, matrix) {
- let points = polyline instanceof x6_geometry_1.Polyline ? polyline.points : polyline;
- if (!Array.isArray(points)) {
- points = [];
- }
- return new x6_geometry_1.Polyline(points.map((p) => transformPoint(p, matrix)));
- }
- Util.transformPolyline = transformPolyline;
- function transformRectangle(rect, matrix) {
- const svgDocument = x6_common_1.Dom.createSvgElement('svg');
- const p = svgDocument.createSVGPoint();
- p.x = rect.x;
- p.y = rect.y;
- const corner1 = p.matrixTransform(matrix);
- p.x = rect.x + rect.width;
- p.y = rect.y;
- const corner2 = p.matrixTransform(matrix);
- p.x = rect.x + rect.width;
- p.y = rect.y + rect.height;
- const corner3 = p.matrixTransform(matrix);
- p.x = rect.x;
- p.y = rect.y + rect.height;
- const corner4 = p.matrixTransform(matrix);
- const minX = Math.min(corner1.x, corner2.x, corner3.x, corner4.x);
- const maxX = Math.max(corner1.x, corner2.x, corner3.x, corner4.x);
- const minY = Math.min(corner1.y, corner2.y, corner3.y, corner4.y);
- const maxY = Math.max(corner1.y, corner2.y, corner3.y, corner4.y);
- return new x6_geometry_1.Rectangle(minX, minY, maxX - minX, maxY - minY);
- }
- Util.transformRectangle = transformRectangle;
- /**
- * Returns the bounding box of the element after transformations are
- * applied. If `withoutTransformations` is `true`, transformations of
- * the element will not be considered when computing the bounding box.
- * If `target` is specified, bounding box will be computed relatively
- * to the `target` element.
- */
- function bbox(elem, withoutTransformations, target) {
- let box;
- const ownerSVGElement = elem.ownerSVGElement;
- // If the element is not in the live DOM, it does not have a bounding
- // box defined and so fall back to 'zero' dimension element.
- if (!ownerSVGElement) {
- return new x6_geometry_1.Rectangle(0, 0, 0, 0);
- }
- try {
- box = elem.getBBox();
- }
- catch (e) {
- // Fallback for IE.
- box = {
- x: elem.clientLeft,
- y: elem.clientTop,
- width: elem.clientWidth,
- height: elem.clientHeight,
- };
- }
- if (withoutTransformations) {
- return x6_geometry_1.Rectangle.create(box);
- }
- const matrix = x6_common_1.Dom.getTransformToElement(elem, target || ownerSVGElement);
- return transformRectangle(box, matrix);
- }
- Util.bbox = bbox;
- /**
- * Returns the bounding box of the element after transformations are
- * applied. Unlike `bbox()`, this function fixes a browser implementation
- * bug to return the correct bounding box if this elemenent is a group of
- * svg elements (if `options.recursive` is specified).
- */
- function getBBox(elem, options = {}) {
- let outputBBox;
- const ownerSVGElement = elem.ownerSVGElement;
- // If the element is not in the live DOM, it does not have a bounding box
- // defined and so fall back to 'zero' dimension element.
- // If the element is not an SVGGraphicsElement, we could not measure the
- // bounding box either
- if (!ownerSVGElement || !x6_common_1.Dom.isSVGGraphicsElement(elem)) {
- if (x6_common_1.Dom.isHTMLElement(elem)) {
- // If the element is a HTMLElement, return the position relative to the body
- const { left, top, width, height } = getBoundingOffsetRect(elem);
- return new x6_geometry_1.Rectangle(left, top, width, height);
- }
- return new x6_geometry_1.Rectangle(0, 0, 0, 0);
- }
- let target = options.target;
- const recursive = options.recursive;
- if (!recursive) {
- try {
- outputBBox = elem.getBBox();
- }
- catch (e) {
- outputBBox = {
- x: elem.clientLeft,
- y: elem.clientTop,
- width: elem.clientWidth,
- height: elem.clientHeight,
- };
- }
- if (!target) {
- return x6_geometry_1.Rectangle.create(outputBBox);
- }
- // transform like target
- const matrix = x6_common_1.Dom.getTransformToElement(elem, target);
- return transformRectangle(outputBBox, matrix);
- }
- // recursive
- {
- const children = elem.childNodes;
- const n = children.length;
- if (n === 0) {
- return getBBox(elem, {
- target,
- });
- }
- if (!target) {
- target = elem; // eslint-disable-line
- }
- for (let i = 0; i < n; i += 1) {
- const child = children[i];
- let childBBox;
- if (child.childNodes.length === 0) {
- childBBox = getBBox(child, {
- target,
- });
- }
- else {
- // if child is a group element, enter it with a recursive call
- childBBox = getBBox(child, {
- target,
- recursive: true,
- });
- }
- if (!outputBBox) {
- outputBBox = childBBox;
- }
- else {
- outputBBox = outputBBox.union(childBBox);
- }
- }
- return outputBBox;
- }
- }
- Util.getBBox = getBBox;
- function getBoundingOffsetRect(elem) {
- let left = 0;
- let top = 0;
- let width = 0;
- let height = 0;
- if (elem) {
- let current = elem;
- while (current) {
- left += current.offsetLeft;
- top += current.offsetTop;
- current = current.offsetParent;
- if (current) {
- left += parseInt(x6_common_1.Dom.getComputedStyle(current, 'borderLeft'), 10);
- top += parseInt(x6_common_1.Dom.getComputedStyle(current, 'borderTop'), 10);
- }
- }
- width = elem.offsetWidth;
- height = elem.offsetHeight;
- }
- return {
- left,
- top,
- width,
- height,
- };
- }
- Util.getBoundingOffsetRect = getBoundingOffsetRect;
- /**
- * Convert the SVGElement to an equivalent geometric shape. The element's
- * transformations are not taken into account.
- *
- * SVGRectElement => Rectangle
- *
- * SVGLineElement => Line
- *
- * SVGCircleElement => Ellipse
- *
- * SVGEllipseElement => Ellipse
- *
- * SVGPolygonElement => Polyline
- *
- * SVGPolylineElement => Polyline
- *
- * SVGPathElement => Path
- *
- * others => Rectangle
- */
- function toGeometryShape(elem) {
- const attr = (name) => {
- const s = elem.getAttribute(name);
- const v = s ? parseFloat(s) : 0;
- return Number.isNaN(v) ? 0 : v;
- };
- switch (elem instanceof SVGElement && elem.nodeName.toLowerCase()) {
- case 'rect':
- return new x6_geometry_1.Rectangle(attr('x'), attr('y'), attr('width'), attr('height'));
- case 'circle':
- return new x6_geometry_1.Ellipse(attr('cx'), attr('cy'), attr('r'), attr('r'));
- case 'ellipse':
- return new x6_geometry_1.Ellipse(attr('cx'), attr('cy'), attr('rx'), attr('ry'));
- case 'polyline': {
- const points = x6_common_1.Dom.getPointsFromSvgElement(elem);
- return new x6_geometry_1.Polyline(points);
- }
- case 'polygon': {
- const points = x6_common_1.Dom.getPointsFromSvgElement(elem);
- if (points.length > 1) {
- points.push(points[0]);
- }
- return new x6_geometry_1.Polyline(points);
- }
- case 'path': {
- let d = elem.getAttribute('d');
- if (!x6_geometry_1.Path.isValid(d)) {
- d = x6_geometry_1.Path.normalize(d);
- }
- return x6_geometry_1.Path.parse(d);
- }
- case 'line': {
- return new x6_geometry_1.Line(attr('x1'), attr('y1'), attr('x2'), attr('y2'));
- }
- default:
- break;
- }
- // Anything else is a rectangle
- return getBBox(elem);
- }
- Util.toGeometryShape = toGeometryShape;
- function translateAndAutoOrient(elem, position, reference, target) {
- const pos = x6_geometry_1.Point.create(position);
- const ref = x6_geometry_1.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 = x6_common_1.Dom.scale(elem);
- elem.setAttribute('transform', '');
- const bbox = getBBox(elem, {
- target,
- }).scale(s.sx, s.sy);
- // 1. Translate to origin.
- const translateToOrigin = x6_common_1.Dom.createSVGTransform();
- translateToOrigin.setTranslate(-bbox.x - bbox.width / 2, -bbox.y - bbox.height / 2);
- // 2. Rotate around origin.
- const rotateAroundOrigin = x6_common_1.Dom.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 = x6_common_1.Dom.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 = x6_common_1.Dom.getTransformToElement(elem, target);
- // 5. Apply transformations and the scale
- const transform = x6_common_1.Dom.createSVGTransform();
- transform.setMatrix(translateFromOrigin.matrix.multiply(rotateAroundOrigin.matrix.multiply(translateToOrigin.matrix.multiply(ctm.scale(s.sx, s.sy)))));
- elem.setAttribute('transform', x6_common_1.Dom.matrixToTransformString(transform.matrix));
- }
- Util.translateAndAutoOrient = translateAndAutoOrient;
- function findShapeNode(magnet) {
- if (magnet == null) {
- return null;
- }
- let node = magnet;
- do {
- let tagName = node.tagName;
- if (typeof tagName !== 'string')
- return null;
- tagName = tagName.toUpperCase();
- if (x6_common_1.Dom.hasClass(node, 'x6-port')) {
- node = node.nextElementSibling;
- }
- else if (tagName === 'G') {
- node = node.firstElementChild;
- }
- else if (tagName === 'TITLE') {
- node = node.nextElementSibling;
- }
- else
- break;
- } while (node);
- return node;
- }
- Util.findShapeNode = findShapeNode;
- // BBox is calculated by the attribute and shape of the node.
- // Because of the reduction in DOM API calls, there is a significant performance improvement.
- function getBBoxV2(elem) {
- const node = findShapeNode(elem);
- if (!x6_common_1.Dom.isSVGGraphicsElement(node)) {
- if (x6_common_1.Dom.isHTMLElement(elem)) {
- const { left, top, width, height } = getBoundingOffsetRect(elem);
- return new x6_geometry_1.Rectangle(left, top, width, height);
- }
- return new x6_geometry_1.Rectangle(0, 0, 0, 0);
- }
- const shape = toGeometryShape(node);
- const bbox = shape.bbox() || x6_geometry_1.Rectangle.create();
- // const transform = node.getAttribute('transform')
- // if (transform) {
- // const nodeMatrix = Dom.transformStringToMatrix(transform)
- // return transformRectangle(bbox, nodeMatrix)
- // }
- return bbox;
- }
- Util.getBBoxV2 = getBBoxV2;
- })(Util = exports.Util || (exports.Util = {}));
- //# sourceMappingURL=index.js.map
|