链接距离在d3力图中不正确

时间:2018-08-20 16:13:15

标签: javascript d3.js force-layout

我有一个React应用程序,试图显示具有指定链接距离的节点的图。我下面有以下代码,其中为每个链接指定了距离。该图显示良好,但链接距离不正确。例如,最远的节点的距离可以小于更靠近中心的节点的距离。有谁知道为什么会这样?我是d3的新手,所以这一切都很令人困惑。 enter image description here Link Distance

let FORCE = (function(nsp){

let that = this,
    width = 700,
    height = 500,
    color = d3.scaleOrdinal(d3.schemeCategory10),
    PointColors = ['#1769aa', 'magenta'],
    div = d3.select("body").append("div")
        .style("opacity", 0)
        .style("position", "absolute")
        .style("text-align", "center")
        .style("width",  "220px")
        .style("height",  "40px")
        .style("padding",  "2px")
        .style("font-family", "Roboto")
        .style("background", "#f5f5f5")
        .style("border", "0px")
        .style("border-radius", "8px")
        .style("pointer-events", "none"),



initForce = (nodes, links) => {
        nsp.force = d3.forceSimulation(nodes)
            .force("charge", d3.forceManyBody().strength(-500))
            .force("link", d3.forceLink(links).distance(function (d) { return (d.distance)*100;}))
            .force("center", d3.forceCenter().x(nsp.width /2).y(nsp.height / 2))
            .force("collide", d3.forceCollide([5]).iterations([5]));
    },


    enterNode = (selection) => {
        let circle = selection.select('circle')
            .attr("r", 10)
            .style("fill", '#1769aa' )
            .style("stroke", "#fff")
            .style("stroke-width", "2px")
            .on("mouseover", function(d){
                console.log(d)
                let matrix = this.getScreenCTM()
                    .translate(+ this.getAttribute("cx"), + this.getAttribute("cy"));
                PointColors = [PointColors[1], PointColors[0]]
                d3.select(this).style("fill", PointColors[0]);
                div.transition()
                   .duration(200)
                    .style("opacity", .9)
                div.html(d.name+'</br>Distance: '+d.distance)
                    .style("left", (window.pageXOffset + matrix.e + 15) + "px")
                    .style("top", (window.pageYOffset + matrix.f - 30) + "px")

                 })
            .on("mouseout", function(d) {
                PointColors = [PointColors[1], PointColors[0]]
                d3.select(this).style("fill", PointColors[0]);
                div.transition()
                    .duration(500)
                    .style("opacity", 0);
                })
            .on("click", function(d) {
                console.log(d);
                window.open(d.url, '_blank');
            });

            selection.select('text')
            .style("fill", "honeydew")
            .style("font-weight", "600")
            .style("text-anchor", "middle")
            .style("alignment-baseline", "middle")
            .style("font-size", "12px")
    },


    updateNode = (selection) => {
        selection
            .attr("transform", (d) => "translate(" + d.x + "," + d.y + ")")
            .attr("cx", function(d) { return d.x = Math.max(30, Math.min(width - 30, d.x)); })
            .attr("cy", function(d) { return d.y = Math.max(30, Math.min(height - 30, d.y)); })
    },


    enterLink = (selection) => {
        selection
            .attr("stroke-width", 2)
            .attr("stroke","#505050")
    },

    updateLink = (selection) => {
        selection
            .attr("x1", (d) => d.source.x)
            .attr("y1", (d) => d.source.y)
            .attr("x2", (d) => d.target.x)
            .attr("y2", (d) => d.target.y);
    },

    updateGraph = (selection) => {
        selection.selectAll('.node')
            .call(updateNode)
        selection.selectAll('.link')
            .call(updateLink);
    },

    dragStarted = (d) => {
        if (!d3.event.active) nsp.force.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y
    },

    dragging = (d) => {
        d.fx = d3.event.x;
        d.fy = d3.event.y
    },

    dragEnded = (d) => {
        if (!d3.event.active) nsp.force.alphaTarget(0);
        d.fx = null;
        d.fy = null
    },

    drag = () => d3.selectAll('g.node')
        .call(d3.drag()
            .on("start", dragStarted)
            .on("drag", dragging)
            .on("end", dragEnded)
        ),

    tick = (that) => {
        that.d3Graph = d3.select(ReactDOM.findDOMNode(that));
        nsp.force.on('tick', () => {
            that.d3Graph.call(updateGraph)
        });
    };

nsp.width = width;
nsp.height = height;
nsp.enterNode = enterNode;
nsp.updateNode = updateNode;
nsp.enterLink = enterLink;
nsp.updateLink = updateLink;
nsp.updateGraph = updateGraph;
nsp.initForce = initForce;
nsp.dragStarted = dragStarted;
nsp.dragging = dragging;
nsp.dragEnded = dragEnded;
nsp.drag = drag;
nsp.tick = tick;

return nsp

})(FORCE || {})

0 个答案:

没有答案