使用 PNG 制作类似 D3 的力导向图 [英] Making D3 like Force-Directed Graph with PNGs

查看:34
本文介绍了使用 PNG 制作类似 D3 的力导向图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试使 D3 像 Force-Directed Graph(例如:

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

解决方案

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

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

var node = svg.selectAll("foo").data(节点).进入().append("g").call(d3.drag().on("开始",拖动开始).on("拖动",拖动).on("end", dragended));var nodeCircle = node.append("circle").attr("r", 20).attr(中风",灰色").attr("填充", "无");var nodeImage = node.append("图像").attr("xlink:href", d => d.image).attr("高度", "40").attr("宽度", "40").attr("x", -20).attr("y", -20);

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

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

这是一个演示:

var width = 300;变量高度 = 200;var svg = d3.select("body").append("svg").attr("宽度", 宽度).attr("高度", 高度);var 节点 = [{"id": "铬",图像":https://icons.iconarchive.com/icons/google/chrome/48/Google-Chrome-icon.png"}, {"id": "火狐",图像":https://icons.iconarchive.com/icons/carlosjj/mozilla/48/Firefox-icon.png"}, {"id": "Safari",图像":https://icons.iconarchive.com/icons/johanchaliber/mac-osx-yosemite/48/safari-icon.png"}, {"id": "歌剧",图像":https://icons.iconarchive.com/icons/ampeross/smooth/48/Opera-icon.png"}];无边距 = [{来源":0,目标":1}, {来源":0,目标":2}, {来源":0,目标":3}];var 模拟 = d3.forceSimulation().force("链接", d3.forceLink()).force("charge", d3.forceManyBody().strength(-1000)).force("center", d3.forceCenter(width/2, height/2));var links = svg.selectAll("foo").data(边).进入().append("行").style("stroke", "#ccc").style("笔画宽度", 1);var color = d3.scaleOrdinal(d3.schemeCategory20);var node = svg.selectAll("foo").data(节点).进入().append("g").call(d3.drag().on("开始",拖动开始).on("拖动",拖动).on("end", dragended));var nodeCircle = node.append("circle").attr("r", 20).attr(中风",灰色").attr("笔画宽度", "2px").attr("填充", "白色");var nodeImage = node.append("图像").attr("xlink:href", d => d.image).attr("高度", "40").attr("宽度", "40").attr("x", -20).attr("y", -20)var texts = node.append("text").style("填充", "黑色").attr("dx", 20).attr("dy", 8).text(function(d) {返回 d.id;});模拟节点(节点);模拟.力(链接").links(edges);模拟.on(滴答",函数(){链接.attr(x1",函数(d){返回 d.source.x;}).attr(y1",函数(d){返回 d.source.y;}).attr(x2",函数(d){返回 d.target.x;}).attr(y2",函数(d){返回 d.target.y;})node.attr("transform", (d) => "translate(" + d.x + "," + d.y + ")")});函数拖动开始(d){if (!d3.event.active) simulation.alphaTarget(0.3).restart();d.fx = d.x;d.fy = d.y;}功能拖动(d){d.fx = d3.event.x;d.fy = d3.event.y;}函数被拖拽(d){if (!d3.event.active) simulation.alphaTarget(0);d.fx = 空;d.fy = 空;}

<script src="https://d3js.org/d3.v4.min.js"></script>

I've been trying to make D3 like Force-Directed Graph (example: https://bl.ocks.org/mbostock/4062045) with PNGs (meaning the dots should be pictures).

Here is a visual idea:

A different approach I tried is to map each graphic element into parallax.js (http://matthew.wagerfield.com/parallax/) and draw a line between the center of each graphic element, but I do not know how to do that, just yet.

解决方案

Since you didn't post your code to create the force, I'll provide a general answer. You may have to adapt it according to your specific code.

The basic idea here is appending group elements for each node, and appending both the circles and the images to those groups. Here I'm using 40x40 PNGs:

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);

The url of each image is in the data array of the nodes:

 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"
 }];

Here is a demo:

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>

这篇关于使用 PNG 制作类似 D3 的力导向图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆