import * as d3 from 'd3'; import * as _ from 'lodash-es'; import { intersectNode } from './intersect/intersect-node.js'; import * as util from './util.js'; export { createEdgePaths, setCreateEdgePaths }; var createEdgePaths = function (selection, g, arrows) { var previousPaths = selection .selectAll('g.edgePath') .data(g.edges(), function (e) { return util.edgeToId(e); }) .classed('update', true); var newPaths = enter(previousPaths, g); exit(previousPaths, g); var svgPaths = previousPaths.merge !== undefined ? previousPaths.merge(newPaths) : previousPaths; util.applyTransition(svgPaths, g).style('opacity', 1); // Save DOM element in the path group, and set ID and class svgPaths.each(function (e) { var domEdge = d3.select(this); var edge = g.edge(e); edge.elem = this; if (edge.id) { domEdge.attr('id', edge.id); } util.applyClass( domEdge, edge['class'], (domEdge.classed('update') ? 'update ' : '') + 'edgePath' ); }); svgPaths.selectAll('path.path').each(function (e) { var edge = g.edge(e); edge.arrowheadId = _.uniqueId('arrowhead'); var domEdge = d3 .select(this) .attr('marker-end', function () { return 'url(' + makeFragmentRef(location.href, edge.arrowheadId) + ')'; }) .style('fill', 'none'); util.applyTransition(domEdge, g).attr('d', function (e) { return calcPoints(g, e); }); util.applyStyle(domEdge, edge.style); }); svgPaths.selectAll('defs *').remove(); svgPaths.selectAll('defs').each(function (e) { var edge = g.edge(e); var arrowhead = arrows[edge.arrowhead]; arrowhead(d3.select(this), edge.arrowheadId, edge, 'arrowhead'); }); return svgPaths; }; function setCreateEdgePaths(value) { createEdgePaths = value; } function makeFragmentRef(url, fragmentId) { var baseUrl = url.split('#')[0]; return baseUrl + '#' + fragmentId; } function calcPoints(g, e) { var edge = g.edge(e); var tail = g.node(e.v); var head = g.node(e.w); var points = edge.points.slice(1, edge.points.length - 1); points.unshift(intersectNode(tail, points[0])); points.push(intersectNode(head, points[points.length - 1])); return createLine(edge, points); } function createLine(edge, points) { // @ts-expect-error var line = (d3.line || d3.svg.line)() .x(function (d) { return d.x; }) .y(function (d) { return d.y; }); (line.curve || line.interpolate)(edge.curve); return line(points); } function getCoords(elem) { var bbox = elem.getBBox(); var matrix = elem.ownerSVGElement .getScreenCTM() .inverse() .multiply(elem.getScreenCTM()) .translate(bbox.width / 2, bbox.height / 2); return { x: matrix.e, y: matrix.f }; } function enter(svgPaths, g) { var svgPathsEnter = svgPaths.enter().append('g').attr('class', 'edgePath').style('opacity', 0); svgPathsEnter .append('path') .attr('class', 'path') .attr('d', function (e) { var edge = g.edge(e); var sourceElem = g.node(e.v).elem; var points = _.range(edge.points.length).map(function () { return getCoords(sourceElem); }); return createLine(edge, points); }); svgPathsEnter.append('defs'); return svgPathsEnter; } function exit(svgPaths, g) { var svgPathExit = svgPaths.exit(); util.applyTransition(svgPathExit, g).style('opacity', 0).remove(); }