08-27-周三_17-09-29
This commit is contained in:
71
node_modules/dagre-d3-renderer/lib/arrows.js
generated
vendored
Normal file
71
node_modules/dagre-d3-renderer/lib/arrows.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
import util from './util'
|
||||
|
||||
function normal (parent, id, edge, type) {
|
||||
const marker = parent.append('marker')
|
||||
.attr('id', id)
|
||||
.attr('viewBox', '0 0 10 10')
|
||||
.attr('refX', 9)
|
||||
.attr('refY', 5)
|
||||
.attr('markerUnits', 'strokeWidth')
|
||||
.attr('markerWidth', 8)
|
||||
.attr('markerHeight', 6)
|
||||
.attr('orient', 'auto')
|
||||
|
||||
const path = marker.append('path')
|
||||
.attr('d', 'M 0 0 L 10 5 L 0 10 z')
|
||||
.style('stroke-width', 1)
|
||||
.style('stroke-dasharray', '1,0')
|
||||
util.applyStyle(path, edge[type + 'Style'])
|
||||
if (edge[type + 'Class']) {
|
||||
path.attr('class', edge[type + 'Class'])
|
||||
}
|
||||
}
|
||||
|
||||
function vee (parent, id, edge, type) {
|
||||
const marker = parent.append('marker')
|
||||
.attr('id', id)
|
||||
.attr('viewBox', '0 0 10 10')
|
||||
.attr('refX', 9)
|
||||
.attr('refY', 5)
|
||||
.attr('markerUnits', 'strokeWidth')
|
||||
.attr('markerWidth', 8)
|
||||
.attr('markerHeight', 6)
|
||||
.attr('orient', 'auto')
|
||||
|
||||
const path = marker.append('path')
|
||||
.attr('d', 'M 0 0 L 10 5 L 0 10 L 4 5 z')
|
||||
.style('stroke-width', 1)
|
||||
.style('stroke-dasharray', '1,0')
|
||||
util.applyStyle(path, edge[type + 'Style'])
|
||||
if (edge[type + 'Class']) {
|
||||
path.attr('class', edge[type + 'Class'])
|
||||
}
|
||||
}
|
||||
|
||||
function undirected (parent, id, edge, type) {
|
||||
const marker = parent.append('marker')
|
||||
.attr('id', id)
|
||||
.attr('viewBox', '0 0 10 10')
|
||||
.attr('refX', 9)
|
||||
.attr('refY', 5)
|
||||
.attr('markerUnits', 'strokeWidth')
|
||||
.attr('markerWidth', 8)
|
||||
.attr('markerHeight', 6)
|
||||
.attr('orient', 'auto')
|
||||
|
||||
const path = marker.append('path')
|
||||
.attr('d', 'M 0 5 L 10 5')
|
||||
.style('stroke-width', 1)
|
||||
.style('stroke-dasharray', '1,0')
|
||||
util.applyStyle(path, edge[type + 'Style'])
|
||||
if (edge[type + 'Class']) {
|
||||
path.attr('class', edge[type + 'Class'])
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
normal,
|
||||
vee,
|
||||
undirected,
|
||||
default: normal
|
||||
}
|
45
node_modules/dagre-d3-renderer/lib/create-clusters.js
generated
vendored
Normal file
45
node_modules/dagre-d3-renderer/lib/create-clusters.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
import d3 from 'd3'
|
||||
|
||||
import util from './util'
|
||||
import addLabel from './label/add-label'
|
||||
|
||||
function createClusters (selection, g) {
|
||||
const clusters = g.nodes().filter(function (v) { return util.isSubgraph(g, v) })
|
||||
const svgClusters = selection.selectAll('g.cluster')
|
||||
.data(clusters, function (v) { return v })
|
||||
|
||||
svgClusters.selectAll('*').remove()
|
||||
svgClusters.enter()
|
||||
.append('g')
|
||||
.attr('class', 'cluster')
|
||||
.attr('id', function (v) {
|
||||
const node = g.node(v)
|
||||
return node.id
|
||||
})
|
||||
.style('opacity', 0)
|
||||
|
||||
util.applyTransition(svgClusters, g)
|
||||
.style('opacity', 1)
|
||||
|
||||
svgClusters.each(function (v) {
|
||||
const node = g.node(v)
|
||||
const thisGroup = d3.select(this)
|
||||
d3.select(this).append('rect')
|
||||
const labelGroup = thisGroup.append('g').attr('class', 'label')
|
||||
addLabel(labelGroup, node, node.clusterLabelPos)
|
||||
})
|
||||
|
||||
svgClusters.selectAll('rect').each(function (c) {
|
||||
const node = g.node(c)
|
||||
const domCluster = d3.select(this)
|
||||
util.applyStyle(domCluster, node.style)
|
||||
})
|
||||
|
||||
util.applyTransition(svgClusters.exit(), g)
|
||||
.style('opacity', 0)
|
||||
.remove()
|
||||
|
||||
return svgClusters
|
||||
}
|
||||
|
||||
export default createClusters
|
34
node_modules/dagre-d3-renderer/lib/create-edge-labels.js
generated
vendored
Normal file
34
node_modules/dagre-d3-renderer/lib/create-edge-labels.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import d3 from 'd3'
|
||||
import _ from 'lodash'
|
||||
|
||||
import addLabel from './label/add-label'
|
||||
import util from './util'
|
||||
|
||||
function createEdgeLabels (selection, g) {
|
||||
const svgEdgeLabels = selection.selectAll('g.edgeLabel')
|
||||
.data(g.edges(), function (e) { return util.edgeToId(e) })
|
||||
.classed('update', true)
|
||||
|
||||
svgEdgeLabels.selectAll('*').remove()
|
||||
svgEdgeLabels.enter()
|
||||
.append('g')
|
||||
.classed('edgeLabel', true)
|
||||
.style('opacity', 0)
|
||||
svgEdgeLabels.each(function (e) {
|
||||
const edge = g.edge(e)
|
||||
const label = addLabel(d3.select(this), g.edge(e), 0, 0).classed('label', true)
|
||||
const bbox = label.node().getBBox()
|
||||
|
||||
if (edge.labelId) { label.attr('id', edge.labelId) }
|
||||
if (!_.has(edge, 'width')) { edge.width = bbox.width }
|
||||
if (!_.has(edge, 'height')) { edge.height = bbox.height }
|
||||
})
|
||||
|
||||
util.applyTransition(svgEdgeLabels.exit(), g)
|
||||
.style('opacity', 0)
|
||||
.remove()
|
||||
|
||||
return svgEdgeLabels
|
||||
}
|
||||
|
||||
export default createEdgeLabels
|
131
node_modules/dagre-d3-renderer/lib/create-edge-paths.js
generated
vendored
Normal file
131
node_modules/dagre-d3-renderer/lib/create-edge-paths.js
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
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
|
57
node_modules/dagre-d3-renderer/lib/create-nodes.js
generated
vendored
Normal file
57
node_modules/dagre-d3-renderer/lib/create-nodes.js
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
import _ from 'lodash'
|
||||
import d3 from 'd3'
|
||||
|
||||
import addLabel from './label/add-label'
|
||||
import util from './util'
|
||||
|
||||
function createNodes (selection, g, shapes) {
|
||||
const simpleNodes = g.nodes().filter(function (v) { return !util.isSubgraph(g, v) })
|
||||
const svgNodes = selection.selectAll('g.node')
|
||||
.data(simpleNodes, function (v) { return v })
|
||||
.classed('update', true)
|
||||
|
||||
svgNodes.selectAll('*').remove()
|
||||
svgNodes.enter()
|
||||
.append('g')
|
||||
.attr('class', 'node')
|
||||
.style('opacity', 0)
|
||||
svgNodes.each(function (v) {
|
||||
const node = g.node(v)
|
||||
const thisGroup = d3.select(this)
|
||||
const labelGroup = thisGroup.append('g').attr('class', 'label')
|
||||
const labelDom = addLabel(labelGroup, node)
|
||||
const shape = shapes[node.shape]
|
||||
const bbox = _.pick(labelDom.node().getBBox(), 'width', 'height')
|
||||
|
||||
node.elem = this
|
||||
|
||||
if (node.id) { thisGroup.attr('id', node.id) }
|
||||
if (node.labelId) { labelGroup.attr('id', node.labelId) }
|
||||
util.applyClass(thisGroup, node['class'],
|
||||
(thisGroup.classed('update') ? 'update ' : '') + 'node')
|
||||
|
||||
if (_.has(node, 'width')) { bbox.width = node.width }
|
||||
if (_.has(node, 'height')) { bbox.height = node.height }
|
||||
|
||||
bbox.width += node.paddingLeft + node.paddingRight
|
||||
bbox.height += node.paddingTop + node.paddingBottom
|
||||
labelGroup.attr('transform', 'translate(' +
|
||||
((node.paddingLeft - node.paddingRight) / 2) + ',' +
|
||||
((node.paddingTop - node.paddingBottom) / 2) + ')')
|
||||
|
||||
const shapeSvg = shape(d3.select(this), bbox, node)
|
||||
util.applyStyle(shapeSvg, node.style)
|
||||
|
||||
const shapeBBox = shapeSvg.node().getBBox()
|
||||
node.width = shapeBBox.width
|
||||
node.height = shapeBBox.height
|
||||
})
|
||||
|
||||
util.applyTransition(svgNodes.exit(), g)
|
||||
.style('opacity', 0)
|
||||
.remove()
|
||||
|
||||
return svgNodes
|
||||
}
|
||||
|
||||
export default createNodes
|
13
node_modules/dagre-d3-renderer/lib/intersect/index.js
generated
vendored
Normal file
13
node_modules/dagre-d3-renderer/lib/intersect/index.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import node from './intersect-node'
|
||||
import circle from './intersect-circle'
|
||||
import ellipse from './intersect-ellipse'
|
||||
import polygon from './intersect-polygon'
|
||||
import rect from './intersect-rect'
|
||||
|
||||
export default {
|
||||
node,
|
||||
circle,
|
||||
ellipse,
|
||||
polygon,
|
||||
rect
|
||||
}
|
7
node_modules/dagre-d3-renderer/lib/intersect/intersect-circle.js
generated
vendored
Normal file
7
node_modules/dagre-d3-renderer/lib/intersect/intersect-circle.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import intersectEllipse from './intersect-ellipse'
|
||||
|
||||
function intersectCircle (node, rx, point) {
|
||||
return intersectEllipse(node, rx, rx, point)
|
||||
}
|
||||
|
||||
export default intersectCircle
|
24
node_modules/dagre-d3-renderer/lib/intersect/intersect-ellipse.js
generated
vendored
Normal file
24
node_modules/dagre-d3-renderer/lib/intersect/intersect-ellipse.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
function intersectEllipse (node, rx, ry, point) {
|
||||
// Formulae from: http://mathworld.wolfram.com/Ellipse-LineIntersection.html
|
||||
|
||||
const cx = node.x
|
||||
const cy = node.y
|
||||
|
||||
const px = cx - point.x
|
||||
const py = cy - point.y
|
||||
|
||||
const det = Math.sqrt(rx * rx * py * py + ry * ry * px * px)
|
||||
|
||||
let dx = Math.abs(rx * ry * px / det)
|
||||
if (point.x < cx) {
|
||||
dx = -dx
|
||||
}
|
||||
let dy = Math.abs(rx * ry * py / det)
|
||||
if (point.y < cy) {
|
||||
dy = -dy
|
||||
}
|
||||
|
||||
return {x: cx + dx, y: cy + dy}
|
||||
}
|
||||
|
||||
export default intersectEllipse
|
65
node_modules/dagre-d3-renderer/lib/intersect/intersect-line.js
generated
vendored
Normal file
65
node_modules/dagre-d3-renderer/lib/intersect/intersect-line.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Returns the point at which two lines, p and q, intersect or returns
|
||||
* undefined if they do not intersect.
|
||||
*/
|
||||
function intersectLine (p1, p2, q1, q2) {
|
||||
// Algorithm from J. Avro, (ed.) Graphics Gems, No 2, Morgan Kaufmann, 1994,
|
||||
// p7 and p473.
|
||||
|
||||
// Compute a1, b1, c1, where line joining points 1 and 2 is F(x,y) = a1 x +
|
||||
// b1 y + c1 = 0.
|
||||
const a1 = p2.y - p1.y
|
||||
const b1 = p1.x - p2.x
|
||||
const c1 = (p2.x * p1.y) - (p1.x * p2.y)
|
||||
|
||||
// Compute r3 and r4.
|
||||
const r3 = ((a1 * q1.x) + (b1 * q1.y) + c1)
|
||||
const r4 = ((a1 * q2.x) + (b1 * q2.y) + c1)
|
||||
|
||||
// Check signs of r3 and r4. If both point 3 and point 4 lie on
|
||||
// same side of line 1, the line segments do not intersect.
|
||||
if ((r3 !== 0) && (r4 !== 0) && sameSign(r3, r4)) {
|
||||
return /* DONT_INTERSECT */
|
||||
}
|
||||
|
||||
// Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0
|
||||
const a2 = q2.y - q1.y
|
||||
const b2 = q1.x - q2.x
|
||||
const c2 = (q2.x * q1.y) - (q1.x * q2.y)
|
||||
|
||||
// Compute r1 and r2
|
||||
const r1 = (a2 * p1.x) + (b2 * p1.y) + c2
|
||||
const r2 = (a2 * p2.x) + (b2 * p2.y) + c2
|
||||
|
||||
// Check signs of r1 and r2. If both point 1 and point 2 lie
|
||||
// on same side of second line segment, the line segments do
|
||||
// not intersect.
|
||||
if ((r1 !== 0) && (r2 !== 0) && (sameSign(r1, r2))) {
|
||||
return /* DONT_INTERSECT */
|
||||
}
|
||||
|
||||
// Line segments intersect: compute intersection point.
|
||||
const denom = (a1 * b2) - (a2 * b1)
|
||||
if (denom === 0) {
|
||||
return /* COLLINEAR */
|
||||
}
|
||||
|
||||
const offset = Math.abs(denom / 2)
|
||||
|
||||
// The denom/2 is to get rounding instead of truncating. It
|
||||
// is added or subtracted to the numerator, depending upon the
|
||||
// sign of the numerator.
|
||||
let num = (b1 * c2) - (b2 * c1)
|
||||
const x = (num < 0) ? ((num - offset) / denom) : ((num + offset) / denom)
|
||||
|
||||
num = (a2 * c1) - (a1 * c2)
|
||||
const y = (num < 0) ? ((num - offset) / denom) : ((num + offset) / denom)
|
||||
|
||||
return { x, y }
|
||||
}
|
||||
|
||||
function sameSign (r1, r2) {
|
||||
return r1 * r2 > 0
|
||||
}
|
||||
|
||||
export default intersectLine
|
5
node_modules/dagre-d3-renderer/lib/intersect/intersect-node.js
generated
vendored
Normal file
5
node_modules/dagre-d3-renderer/lib/intersect/intersect-node.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
function intersectNode (node, point) {
|
||||
return node.intersect(point)
|
||||
}
|
||||
|
||||
export default intersectNode
|
55
node_modules/dagre-d3-renderer/lib/intersect/intersect-polygon.js
generated
vendored
Normal file
55
node_modules/dagre-d3-renderer/lib/intersect/intersect-polygon.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import intersectLine from './intersect-line'
|
||||
|
||||
/*
|
||||
* Returns the point ({x, y}) at which the point argument intersects with the
|
||||
* node argument assuming that it has the shape specified by polygon.
|
||||
*/
|
||||
function intersectPolygon (node, polyPoints, point) {
|
||||
const x1 = node.x
|
||||
const y1 = node.y
|
||||
|
||||
const intersections = []
|
||||
|
||||
let minX = Number.POSITIVE_INFINITY
|
||||
let minY = Number.POSITIVE_INFINITY
|
||||
polyPoints.forEach(function (entry) {
|
||||
minX = Math.min(minX, entry.x)
|
||||
minY = Math.min(minY, entry.y)
|
||||
})
|
||||
|
||||
const left = x1 - node.width / 2 - minX
|
||||
const top = y1 - node.height / 2 - minY
|
||||
|
||||
for (let i = 0; i < polyPoints.length; i += 1) {
|
||||
const p1 = polyPoints[i]
|
||||
const p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0]
|
||||
const intersect = intersectLine(node, point,
|
||||
{x: left + p1.x, y: top + p1.y}, {x: left + p2.x, y: top + p2.y})
|
||||
if (intersect) {
|
||||
intersections.push(intersect)
|
||||
}
|
||||
}
|
||||
|
||||
if (!intersections.length) {
|
||||
console.log('NO INTERSECTION FOUND, RETURN NODE CENTER', node)
|
||||
return node
|
||||
}
|
||||
|
||||
if (intersections.length > 1) {
|
||||
// More intersections, find the one nearest to edge end point
|
||||
intersections.sort(function (p, q) {
|
||||
const pdx = p.x - point.x
|
||||
const pdy = p.y - point.y
|
||||
const distp = Math.sqrt(pdx * pdx + pdy * pdy)
|
||||
|
||||
const qdx = q.x - point.x
|
||||
const qdy = q.y - point.y
|
||||
const distq = Math.sqrt(qdx * qdx + qdy * qdy)
|
||||
|
||||
return (distp < distq) ? -1 : (distp === distq ? 0 : 1)
|
||||
})
|
||||
}
|
||||
return intersections[0]
|
||||
}
|
||||
|
||||
export default intersectPolygon
|
32
node_modules/dagre-d3-renderer/lib/intersect/intersect-rect.js
generated
vendored
Normal file
32
node_modules/dagre-d3-renderer/lib/intersect/intersect-rect.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
function intersectRect (node, point) {
|
||||
const x = node.x
|
||||
const y = node.y
|
||||
|
||||
// Rectangle intersection algorithm from:
|
||||
// http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
|
||||
const dx = point.x - x
|
||||
const dy = point.y - y
|
||||
let w = node.width / 2
|
||||
let h = node.height / 2
|
||||
|
||||
let sx, sy
|
||||
if (Math.abs(dy) * w > Math.abs(dx) * h) {
|
||||
// Intersection is top or bottom of rect.
|
||||
if (dy < 0) {
|
||||
h = -h
|
||||
}
|
||||
sx = dy === 0 ? 0 : h * dx / dy
|
||||
sy = h
|
||||
} else {
|
||||
// Intersection is left or right of rect.
|
||||
if (dx < 0) {
|
||||
w = -w
|
||||
}
|
||||
sx = w
|
||||
sy = dx === 0 ? 0 : w * dy / dx
|
||||
}
|
||||
|
||||
return {x: x + sx, y: y + sy}
|
||||
}
|
||||
|
||||
export default intersectRect
|
37
node_modules/dagre-d3-renderer/lib/label/add-html-label.js
generated
vendored
Normal file
37
node_modules/dagre-d3-renderer/lib/label/add-html-label.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import util from '../util'
|
||||
|
||||
function addHtmlLabel (root, node) {
|
||||
const fo = root
|
||||
.append('foreignObject')
|
||||
.attr('width', '100000')
|
||||
|
||||
const div = fo
|
||||
.append('xhtml:div')
|
||||
div.attr('xmlns', 'http://www.w3.org/1999/xhtml')
|
||||
|
||||
const label = node.label
|
||||
switch (typeof label) {
|
||||
case 'function':
|
||||
div.insert(label)
|
||||
break
|
||||
case 'object':
|
||||
// Currently we assume this is a DOM object.
|
||||
div.insert(function () { return label })
|
||||
break
|
||||
default: div.html(label)
|
||||
}
|
||||
|
||||
util.applyStyle(div, node.labelStyle)
|
||||
div.style('display', 'inline-block')
|
||||
// Fix for firefox
|
||||
div.style('white-space', 'nowrap')
|
||||
|
||||
const client = div[0][0].getBoundingClientRect()
|
||||
fo
|
||||
.attr('width', client.width)
|
||||
.attr('height', client.height)
|
||||
|
||||
return fo
|
||||
}
|
||||
|
||||
export default addHtmlLabel
|
37
node_modules/dagre-d3-renderer/lib/label/add-label.js
generated
vendored
Normal file
37
node_modules/dagre-d3-renderer/lib/label/add-label.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import addTextLabel from './add-text-label'
|
||||
import addHtmlLabel from './add-html-label'
|
||||
import addSVGLabel from './add-svg-label'
|
||||
|
||||
function addLabel (root, node, location) {
|
||||
const label = node.label
|
||||
const labelSvg = root.append('g')
|
||||
|
||||
// Allow the label to be a string, a function that returns a DOM element, or
|
||||
// a DOM element itself.
|
||||
if (node.labelType === 'svg') {
|
||||
addSVGLabel(labelSvg, node)
|
||||
} else if (typeof label !== 'string' || node.labelType === 'html') {
|
||||
addHtmlLabel(labelSvg, node)
|
||||
} else {
|
||||
addTextLabel(labelSvg, node)
|
||||
}
|
||||
|
||||
const labelBBox = labelSvg.node().getBBox()
|
||||
let y
|
||||
switch (location) {
|
||||
case 'top':
|
||||
y = (-node.height / 2)
|
||||
break
|
||||
case 'bottom':
|
||||
y = (node.height / 2) - labelBBox.height
|
||||
break
|
||||
default:
|
||||
y = (-labelBBox.height / 2)
|
||||
}
|
||||
labelSvg.attr('transform',
|
||||
'translate(' + (-labelBBox.width / 2) + ',' + y + ')')
|
||||
|
||||
return labelSvg
|
||||
}
|
||||
|
||||
export default addLabel
|
13
node_modules/dagre-d3-renderer/lib/label/add-svg-label.js
generated
vendored
Normal file
13
node_modules/dagre-d3-renderer/lib/label/add-svg-label.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import util from '../util'
|
||||
|
||||
function addSVGLabel (root, node) {
|
||||
const domNode = root
|
||||
|
||||
domNode.node().appendChild(node.label)
|
||||
|
||||
util.applyStyle(domNode, node.labelStyle)
|
||||
|
||||
return domNode
|
||||
}
|
||||
|
||||
export default addSVGLabel
|
45
node_modules/dagre-d3-renderer/lib/label/add-text-label.js
generated
vendored
Normal file
45
node_modules/dagre-d3-renderer/lib/label/add-text-label.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
import util from '../util'
|
||||
|
||||
/*
|
||||
* Attaches a text label to the specified root. Handles escape sequences.
|
||||
*/
|
||||
function addTextLabel (root, node) {
|
||||
const domNode = root.append('text')
|
||||
|
||||
const lines = processEscapeSequences(node.label).split('\n')
|
||||
for (let i = 0; i < lines.length; i += 1) {
|
||||
domNode
|
||||
.append('tspan')
|
||||
.attr('xml:space', 'preserve')
|
||||
.attr('dy', '1em')
|
||||
.attr('x', '1')
|
||||
.text(lines[i])
|
||||
}
|
||||
|
||||
util.applyStyle(domNode, node.labelStyle)
|
||||
|
||||
return domNode
|
||||
}
|
||||
|
||||
function processEscapeSequences (text) {
|
||||
let newText = ''
|
||||
let escaped = false
|
||||
let ch = null
|
||||
for (let i = 0; i < text.length; i += 1) {
|
||||
ch = text[i]
|
||||
if (escaped) {
|
||||
switch (ch) {
|
||||
case 'n': newText += '\n'; break
|
||||
default: newText += ch
|
||||
}
|
||||
escaped = false
|
||||
} else if (ch === '\\') {
|
||||
escaped = true
|
||||
} else {
|
||||
newText += ch
|
||||
}
|
||||
}
|
||||
return newText
|
||||
}
|
||||
|
||||
export default addTextLabel
|
31
node_modules/dagre-d3-renderer/lib/position-clusters.js
generated
vendored
Normal file
31
node_modules/dagre-d3-renderer/lib/position-clusters.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import d3 from 'd3'
|
||||
import util from './util'
|
||||
|
||||
function positionClusters (selection, g) {
|
||||
const created = selection.filter(function () { return !d3.select(this).classed('update') })
|
||||
|
||||
function translate (v) {
|
||||
const node = g.node(v)
|
||||
return 'translate(' + node.x + ',' + node.y + ')'
|
||||
}
|
||||
|
||||
created.attr('transform', translate)
|
||||
|
||||
util.applyTransition(selection, g)
|
||||
.style('opacity', 1)
|
||||
.attr('transform', translate)
|
||||
|
||||
util.applyTransition(created.selectAll('rect'), g)
|
||||
.attr('width', function (v) { return g.node(v).width })
|
||||
.attr('height', function (v) { return g.node(v).height })
|
||||
.attr('x', function (v) {
|
||||
const node = g.node(v)
|
||||
return -node.width / 2
|
||||
})
|
||||
.attr('y', function (v) {
|
||||
const node = g.node(v)
|
||||
return -node.height / 2
|
||||
})
|
||||
}
|
||||
|
||||
export default positionClusters
|
21
node_modules/dagre-d3-renderer/lib/position-edge-labels.js
generated
vendored
Normal file
21
node_modules/dagre-d3-renderer/lib/position-edge-labels.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import d3 from 'd3'
|
||||
import _ from 'lodash'
|
||||
|
||||
import util from './util'
|
||||
|
||||
function positionEdgeLabels (selection, g) {
|
||||
const created = selection.filter(function () { return !d3.select(this).classed('update') })
|
||||
|
||||
function translate (e) {
|
||||
const edge = g.edge(e)
|
||||
return _.has(edge, 'x') ? 'translate(' + edge.x + ',' + edge.y + ')' : ''
|
||||
}
|
||||
|
||||
created.attr('transform', translate)
|
||||
|
||||
util.applyTransition(selection, g)
|
||||
.style('opacity', 1)
|
||||
.attr('transform', translate)
|
||||
}
|
||||
|
||||
export default positionEdgeLabels
|
20
node_modules/dagre-d3-renderer/lib/position-nodes.js
generated
vendored
Normal file
20
node_modules/dagre-d3-renderer/lib/position-nodes.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import d3 from 'd3'
|
||||
|
||||
import util from './util'
|
||||
|
||||
function positionNodes (selection, g) {
|
||||
const created = selection.filter(function () { return !d3.select(this).classed('update') })
|
||||
|
||||
function translate (v) {
|
||||
const node = g.node(v)
|
||||
return 'translate(' + node.x + ',' + node.y + ')'
|
||||
}
|
||||
|
||||
created.attr('transform', translate)
|
||||
|
||||
util.applyTransition(selection, g)
|
||||
.style('opacity', 1)
|
||||
.attr('transform', translate)
|
||||
}
|
||||
|
||||
export default positionNodes
|
186
node_modules/dagre-d3-renderer/lib/render.js
generated
vendored
Normal file
186
node_modules/dagre-d3-renderer/lib/render.js
generated
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
import _ from 'lodash'
|
||||
import { layout } from 'dagre-layout'
|
||||
|
||||
import positionNodes from './position-nodes'
|
||||
import positionEdgeLabels from './position-edge-labels'
|
||||
import positionClusters from './position-clusters'
|
||||
import createNodes from './create-nodes'
|
||||
import createClusters from './create-clusters'
|
||||
import createEdgeLabels from './create-edge-labels'
|
||||
import createEdgePaths from './create-edge-paths'
|
||||
import shapes from './shapes'
|
||||
import arrows from './arrows'
|
||||
|
||||
// This design is based on http://bost.ocks.org/mike/chart/.
|
||||
function render () {
|
||||
let _createNodes = createNodes
|
||||
let _createClusters = createClusters
|
||||
let _createEdgeLabels = createEdgeLabels
|
||||
let _createEdgePaths = createEdgePaths
|
||||
let _shapes = shapes
|
||||
let _arrows = arrows
|
||||
|
||||
const fn = function (svg, g) {
|
||||
preProcessGraph(g)
|
||||
|
||||
const outputGroup = createOrSelectGroup(svg, 'output')
|
||||
const clustersGroup = createOrSelectGroup(outputGroup, 'clusters')
|
||||
const edgePathsGroup = createOrSelectGroup(outputGroup, 'edgePaths')
|
||||
const edgeLabels = _createEdgeLabels(createOrSelectGroup(outputGroup, 'edgeLabels'), g)
|
||||
const nodes = _createNodes(createOrSelectGroup(outputGroup, 'nodes'), g, _shapes)
|
||||
|
||||
layout(g)
|
||||
|
||||
positionNodes(nodes, g)
|
||||
positionEdgeLabels(edgeLabels, g)
|
||||
_createEdgePaths(edgePathsGroup, g, _arrows)
|
||||
|
||||
const clusters = _createClusters(clustersGroup, g)
|
||||
positionClusters(clusters, g)
|
||||
|
||||
postProcessGraph(g)
|
||||
}
|
||||
|
||||
fn.createNodes = function (value) {
|
||||
if (!arguments.length) {
|
||||
return _createNodes
|
||||
}
|
||||
_createNodes = value
|
||||
return fn
|
||||
}
|
||||
|
||||
fn.createClusters = function (value) {
|
||||
if (!arguments.length) {
|
||||
return _createClusters
|
||||
}
|
||||
_createClusters = value
|
||||
return fn
|
||||
}
|
||||
|
||||
fn.createEdgeLabels = function (value) {
|
||||
if (!arguments.length) {
|
||||
return _createEdgeLabels
|
||||
}
|
||||
_createEdgeLabels = value
|
||||
return fn
|
||||
}
|
||||
|
||||
fn.createEdgePaths = function (value) {
|
||||
if (!arguments.length) {
|
||||
return _createEdgePaths
|
||||
}
|
||||
_createEdgePaths = value
|
||||
return fn
|
||||
}
|
||||
|
||||
fn.shapes = function (value) {
|
||||
if (!arguments.length) {
|
||||
return _shapes
|
||||
}
|
||||
_shapes = value
|
||||
return fn
|
||||
}
|
||||
|
||||
fn.arrows = function (value) {
|
||||
if (!arguments.length) {
|
||||
return _arrows
|
||||
}
|
||||
_arrows = value
|
||||
return fn
|
||||
}
|
||||
|
||||
return fn
|
||||
}
|
||||
|
||||
const NODE_DEFAULT_ATTRS = {
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
paddingTop: 10,
|
||||
paddingBottom: 10,
|
||||
rx: 0,
|
||||
ry: 0,
|
||||
shape: 'rect'
|
||||
}
|
||||
|
||||
const EDGE_DEFAULT_ATTRS = {
|
||||
arrowhead: 'normal',
|
||||
lineInterpolate: 'linear'
|
||||
}
|
||||
|
||||
function preProcessGraph (g) {
|
||||
g.nodes().forEach(function (v) {
|
||||
const node = g.node(v)
|
||||
if (!_.has(node, 'label') && !g.children(v).length) { node.label = v }
|
||||
|
||||
if (_.has(node, 'paddingX')) {
|
||||
_.defaults(node, {
|
||||
paddingLeft: node.paddingX,
|
||||
paddingRight: node.paddingX
|
||||
})
|
||||
}
|
||||
|
||||
if (_.has(node, 'paddingY')) {
|
||||
_.defaults(node, {
|
||||
paddingTop: node.paddingY,
|
||||
paddingBottom: node.paddingY
|
||||
})
|
||||
}
|
||||
|
||||
if (_.has(node, 'padding')) {
|
||||
_.defaults(node, {
|
||||
paddingLeft: node.padding,
|
||||
paddingRight: node.padding,
|
||||
paddingTop: node.padding,
|
||||
paddingBottom: node.padding
|
||||
})
|
||||
}
|
||||
|
||||
_.defaults(node, NODE_DEFAULT_ATTRS)
|
||||
|
||||
_.each(['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom'], function (k) {
|
||||
node[k] = Number(node[k])
|
||||
})
|
||||
|
||||
// Save dimensions for restore during post-processing
|
||||
if (_.has(node, 'width')) { node._prevWidth = node.width }
|
||||
if (_.has(node, 'height')) { node._prevHeight = node.height }
|
||||
})
|
||||
|
||||
g.edges().forEach(function (e) {
|
||||
const edge = g.edge(e)
|
||||
if (!_.has(edge, 'label')) { edge.label = '' }
|
||||
_.defaults(edge, EDGE_DEFAULT_ATTRS)
|
||||
})
|
||||
}
|
||||
|
||||
function postProcessGraph (g) {
|
||||
_.each(g.nodes(), function (v) {
|
||||
const node = g.node(v)
|
||||
|
||||
// Restore original dimensions
|
||||
if (_.has(node, '_prevWidth')) {
|
||||
node.width = node._prevWidth
|
||||
} else {
|
||||
delete node.width
|
||||
}
|
||||
|
||||
if (_.has(node, '_prevHeight')) {
|
||||
node.height = node._prevHeight
|
||||
} else {
|
||||
delete node.height
|
||||
}
|
||||
|
||||
delete node._prevWidth
|
||||
delete node._prevHeight
|
||||
})
|
||||
}
|
||||
|
||||
function createOrSelectGroup (root, name) {
|
||||
let selection = root.select('g.' + name)
|
||||
if (selection.empty()) {
|
||||
selection = root.append('g').attr('class', name)
|
||||
}
|
||||
return selection
|
||||
}
|
||||
|
||||
export default render
|
79
node_modules/dagre-d3-renderer/lib/shapes.js
generated
vendored
Normal file
79
node_modules/dagre-d3-renderer/lib/shapes.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
import intersectRect from './intersect/intersect-rect'
|
||||
import intersectEllipse from './intersect/intersect-ellipse'
|
||||
import intersectCircle from './intersect/intersect-circle'
|
||||
import intersectPolygon from './intersect/intersect-polygon'
|
||||
|
||||
function rect (parent, bbox, node) {
|
||||
const shapeSvg = parent.insert('rect', ':first-child')
|
||||
.attr('rx', node.rx)
|
||||
.attr('ry', node.ry)
|
||||
.attr('x', -bbox.width / 2)
|
||||
.attr('y', -bbox.height / 2)
|
||||
.attr('width', bbox.width)
|
||||
.attr('height', bbox.height)
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersectRect(node, point)
|
||||
}
|
||||
|
||||
return shapeSvg
|
||||
}
|
||||
|
||||
function ellipse (parent, bbox, node) {
|
||||
const rx = bbox.width / 2
|
||||
const ry = bbox.height / 2
|
||||
const shapeSvg = parent.insert('ellipse', ':first-child')
|
||||
.attr('x', -bbox.width / 2)
|
||||
.attr('y', -bbox.height / 2)
|
||||
.attr('rx', rx)
|
||||
.attr('ry', ry)
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersectEllipse(node, rx, ry, point)
|
||||
}
|
||||
|
||||
return shapeSvg
|
||||
}
|
||||
|
||||
function circle (parent, bbox, node) {
|
||||
const r = Math.max(bbox.width, bbox.height) / 2
|
||||
const shapeSvg = parent.insert('circle', ':first-child')
|
||||
.attr('x', -bbox.width / 2)
|
||||
.attr('y', -bbox.height / 2)
|
||||
.attr('r', r)
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersectCircle(node, r, point)
|
||||
}
|
||||
|
||||
return shapeSvg
|
||||
}
|
||||
|
||||
// Circumscribe an ellipse for the bounding box with a diamond shape. I derived
|
||||
// the function to calculate the diamond shape from:
|
||||
// http://mathforum.org/kb/message.jspa?messageID=3750236
|
||||
function diamond (parent, bbox, node) {
|
||||
const w = (bbox.width * Math.SQRT2) / 2
|
||||
const h = (bbox.height * Math.SQRT2) / 2
|
||||
const points = [
|
||||
{ x: 0, y: -h },
|
||||
{ x: -w, y: 0 },
|
||||
{ x: 0, y: h },
|
||||
{ x: w, y: 0 }
|
||||
]
|
||||
const shapeSvg = parent.insert('polygon', ':first-child')
|
||||
.attr('points', points.map(function (p) { return p.x + ',' + p.y }).join(' '))
|
||||
|
||||
node.intersect = function (p) {
|
||||
return intersectPolygon(node, points, p)
|
||||
}
|
||||
|
||||
return shapeSvg
|
||||
}
|
||||
|
||||
export default {
|
||||
rect,
|
||||
ellipse,
|
||||
circle,
|
||||
diamond
|
||||
}
|
54
node_modules/dagre-d3-renderer/lib/util.js
generated
vendored
Normal file
54
node_modules/dagre-d3-renderer/lib/util.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import _ from 'lodash'
|
||||
|
||||
/*
|
||||
* Returns true if the specified node in the graph is a subgraph node. A
|
||||
* subgraph node is one that contains other nodes.
|
||||
*/
|
||||
function isSubgraph (g, v) {
|
||||
return !!g.children(v).length
|
||||
}
|
||||
|
||||
function edgeToId (e) {
|
||||
return escapeId(e.v) + ':' + escapeId(e.w) + ':' + escapeId(e.name)
|
||||
}
|
||||
|
||||
const ID_DELIM = /:/g
|
||||
function escapeId (str) {
|
||||
return str ? String(str).replace(ID_DELIM, '\\:') : ''
|
||||
}
|
||||
|
||||
function applyStyle (dom, styleFn) {
|
||||
if (styleFn) {
|
||||
dom.attr('style', styleFn)
|
||||
}
|
||||
}
|
||||
|
||||
function applyClass (dom, classFn, otherClasses) {
|
||||
if (classFn) {
|
||||
dom
|
||||
.attr('class', classFn)
|
||||
.attr('class', otherClasses + ' ' + dom.attr('class'))
|
||||
}
|
||||
}
|
||||
|
||||
function applyTransition (selection, g) {
|
||||
const graph = g.graph()
|
||||
|
||||
if (_.isPlainObject(graph)) {
|
||||
const transition = graph.transition
|
||||
if (_.isFunction(transition)) {
|
||||
return transition(selection)
|
||||
}
|
||||
}
|
||||
|
||||
return selection
|
||||
}
|
||||
|
||||
// Public utility functions
|
||||
export default {
|
||||
isSubgraph,
|
||||
edgeToId,
|
||||
applyStyle,
|
||||
applyClass,
|
||||
applyTransition
|
||||
}
|
Reference in New Issue
Block a user