【问题标题】:Making D3 like Force-Directed Graph with PNGs使用 PNG 制作 D3 类似力有向图
【发布时间】:2017-03-02 13:01:32
【问题描述】:

我一直在尝试使用 PNG(意味着点应该是图片)制作像 Force-Directed Graph(例如:https://bl.ocks.org/mbostock/4062045)的 D3。

这是一个视觉创意:

我尝试的另一种方法是将每个图形元素映射到 parallax.js (http://matthew.wagerfield.com/parallax/) 并在每个图形元素的中心之间画一条线,但我还不知道该怎么做。

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    由于您没有发布您的代码来创建部队,我将提供一个一般性的答案。您可能需要根据您的特定代码对其进行调整。

    这里的基本思想是为每个节点附加组元素,并将圆圈和图像都附加到这些组中。这里我使用的是 40x40 PNG:

    var node = svg.selectAll("foo")
         .data(nodes)
         .enter()
         .append("g")
         .call(d3.drag()
             .on("start", dragstarted)
             .on("drag", dragged)
             .on("end", dragended));
    
     var nodeCircle = node.append("circle")
         .attr("r", 20)
         .attr("stroke", "gray")
         .attr("fill", "none");
    
     var nodeImage = node.append("image")
         .attr("xlink:href", d => d.image)
         .attr("height", "40")
         .attr("width", "40")
         .attr("x", -20)
         .attr("y", -20);
    

    每张图片的url在节点的数据数组中:

     var nodes = [{
         "id": "foo",
         "image": "https://icons.iconarchive.com/icons/google/chrome/48/Google-Chrome-icon.png"
     }, {
         "id": "bar",
         "image": "https://icons.iconarchive.com/icons/carlosjj/mozilla/48/Firefox-icon.png"
     }, {
         "id": "baz",
         "image": "https://icons.iconarchive.com/icons/johanchalibert/mac-osx-yosemite/48/safari-icon.png"
     }, {
         "id": "barbaz",
         "image": "https://icons.iconarchive.com/icons/ampeross/smooth/48/Opera-icon.png"
     }];
    

    这是一个演示:

    var width = 300;
     var height = 200;
    
     var svg = d3.select("body")
         .append("svg")
         .attr("width", width)
         .attr("height", height);
    
     var nodes = [{
         "id": "Chrome",
         "image": "https://icons.iconarchive.com/icons/google/chrome/48/Google-Chrome-icon.png"
     }, {
         "id": "Firefox",
         "image": "https://icons.iconarchive.com/icons/carlosjj/mozilla/48/Firefox-icon.png"
     }, {
         "id": "Safari",
         "image": "https://icons.iconarchive.com/icons/johanchalibert/mac-osx-yosemite/48/safari-icon.png"
     }, {
         "id": "Opera",
         "image": "https://icons.iconarchive.com/icons/ampeross/smooth/48/Opera-icon.png"
     }];
    
     var edges = [{
         "source": 0,
         "target": 1
     }, {
         "source": 0,
         "target": 2
     }, {
         "source": 0,
         "target": 3
     }];
    
     var simulation = d3.forceSimulation()
         .force("link", d3.forceLink())
         .force("charge", d3.forceManyBody().strength(-1000))
         .force("center", d3.forceCenter(width / 2, height / 2));
    
     var links = svg.selectAll("foo")
         .data(edges)
         .enter()
         .append("line")
         .style("stroke", "#ccc")
         .style("stroke-width", 1);
    
     var color = d3.scaleOrdinal(d3.schemeCategory20);
    
     var node = svg.selectAll("foo")
         .data(nodes)
         .enter()
         .append("g")
         .call(d3.drag()
             .on("start", dragstarted)
             .on("drag", dragged)
             .on("end", dragended));
    
     var nodeCircle = node.append("circle")
         .attr("r", 20)
         .attr("stroke", "gray")
         .attr("stroke-width", "2px")
         .attr("fill", "white");
    
     var nodeImage = node.append("image")
         .attr("xlink:href", d => d.image)
         .attr("height", "40")
         .attr("width", "40")
         .attr("x", -20)
         .attr("y", -20)
    
     var texts = node.append("text")
         .style("fill", "black")
         .attr("dx", 20)
         .attr("dy", 8)
         .text(function(d) {
             return d.id;
         });
    
     simulation.nodes(nodes);
     simulation.force("link")
         .links(edges);
    
    simulation.on("tick", function() { 
         links.attr("x1", function(d) {
                 return d.source.x;
             })
             .attr("y1", function(d) {
                 return d.source.y;
             })
             .attr("x2", function(d) {
                 return d.target.x;
             })
             .attr("y2", function(d) {
                 return d.target.y;
             })
    
         node.attr("transform", (d) => "translate(" + d.x + "," + d.y + ")")
    
    
     });
    
     function dragstarted(d) {
         if (!d3.event.active) simulation.alphaTarget(0.3).restart();
         d.fx = d.x;
         d.fy = d.y;
     }
    
     function dragged(d) {
         d.fx = d3.event.x;
         d.fy = d3.event.y;
     }
    
     function dragended(d) {
         if (!d3.event.active) simulation.alphaTarget(0);
         d.fx = null;
         d.fy = null;
     }
    <script src="https://d3js.org/d3.v4.min.js"></script>

    【讨论】:

    • 如果我从edges 列表中删除边缘并离开没有任何边缘的节点 - 它不会出现。即使节点没有任何边,我应该怎么做才能看到它们?
    • 感谢这个很棒的答案!你能解释一下这里的什么属性改变了处于静止状态的节点之间的距离吗?我认为这可能是一种力量,但它不会影响他们彼此之间的距离。
    • forceManyBody
    猜你喜欢
    • 2014-02-27
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 2013-06-30
    • 2019-04-23
    • 2012-12-12
    • 1970-01-01
    相关资源
    最近更新 更多