Files
Cloud-book/node_modules/dagre-d3-renderer/lib/create-edge-paths.js
2025-08-27 17:10:05 +08:00

132 lines
3.3 KiB
JavaScript

import d3 from 'd3'
import _ from 'lodash'
import intersectNode from './intersect/intersect-node'
import util from './util'
function createEdgePaths (selection, g, arrows) {
const svgPaths = selection.selectAll('g.edgePath')
.data(g.edges(), function (e) { return util.edgeToId(e) })
.classed('update', true)
enter(svgPaths, g)
exit(svgPaths, g)
util.applyTransition(svgPaths, g)
.style('opacity', 1)
// Save DOM element in the path group, and set ID and class
svgPaths.each(function (e) {
const domEdge = d3.select(this)
const 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) {
const edge = g.edge(e)
edge.arrowheadId = _.uniqueId('arrowhead')
const domEdge = d3.select(this)
.attr('marker-end', function () {
return 'url(#' + 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) {
const edge = g.edge(e)
const arrowhead = arrows[edge.arrowhead]
arrowhead(d3.select(this), edge.arrowheadId, edge, 'arrowhead')
})
return svgPaths
}
function calcPoints (g, e) {
const edge = g.edge(e)
const tail = g.node(e.v)
const head = g.node(e.w)
const 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) {
const line = d3.svg.line()
.x(function (d) { return d.x })
.y(function (d) { return d.y })
if (_.has(edge, 'lineInterpolate')) {
line.interpolate(edge.lineInterpolate)
}
if (_.has(edge, 'lineTension')) {
line.tension(Number(edge.lineTension))
}
return line(points)
}
function getCoords (elem) {
const bbox = elem.getBBox()
const 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) {
const svgPathsEnter = svgPaths.enter()
.append('g')
.attr('class', 'edgePath')
.style('opacity', 0)
svgPathsEnter.append('path')
.attr('class', 'path')
.attr('d', function (e) {
const edge = g.edge(e)
const sourceElem = g.node(e.v).elem
const points = _.range(edge.points.length).map(function () { return getCoords(sourceElem) })
return createLine(edge, points)
})
svgPathsEnter.append('defs')
}
function exit (svgPaths, g) {
const svgPathExit = svgPaths.exit()
util.applyTransition(svgPathExit, g)
.style('opacity', 0)
.remove()
util.applyTransition(svgPathExit.select('path.path'), g)
.attr('d', function (e) {
const source = g.node(e.v)
if (source) {
const points = _.range(this.getTotalLength()).map(function () { return source })
return createLine({}, points)
} else {
return d3.select(this).attr('d')
}
})
}
export default createEdgePaths