D3力导向图(v4)不接受img作为节点

时间:2018-05-20 16:09:05

标签: d3.js svg

我正在尝试生成一个力导向图。如果我使用' circle / rect'我能够实现它。绘制节点。但我想用图像代替。我做错了什么?

以下是我创建和转换节点的方法(我使用的是d3 v4):

  var node = svg.append("g")
  .attr("class", "nodes f32")
  .selectAll("img")
  .data(json.nodes)
  .enter().append("img")
  .attr("class","flag ar")
  .call(d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended));


function ticked() {
    link
    .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
    .style("left", function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
    .style("top", function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); });
}

这是我到目前为止的演示:



var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height"),
    radius=5;

var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d,index) { return d.id; }).distance(10))
    .force("charge", d3.forceManyBody().distanceMin(10).distanceMax(120))
    .force("center", d3.forceCenter(width / 2, height / 2));

d3.json("https://raw.githubusercontent.com/DealPete/forceDirected/master/countries.json",function(json ) {
  json.nodes.forEach(function(d,i){
    d.id = i;
  })
  
  var link = svg.append("g")
      .attr("class", "links")
    .selectAll("line")
    .data(json.links)
    .enter().append("line")
  .attr("stroke-width","1");
  
    var node = svg.append("g")
      .attr("class", "nodes f32")
    .selectAll("img")
    .data(json.nodes)
    .enter().append("img")
      .attr("class","flag ar")
      .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended));


  function ticked() {
    link
        .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
    
        .style("left", function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
        .style("top", function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); });
  }

  simulation
      .nodes(json.nodes)
      .on("tick", ticked);
  
  simulation.force("link")
      .links(json.links);
});

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

.links line {
    stroke: #999;
    stroke-opacity: 0.6;
}
h1{
  font-family: arial;
}
body{
  display:flex;
  justify-content:center;
  align-items:center;
      flex-direction: column;
    background:#d64d4d;
}
.fdd{
 width:1000px;
  height:500px;
  background: white;
  
}

<script src="https://d3js.org/d3.v4.min.js"></script>
<h1>Force Directed Graph of State Contiguity</h1>
<div class="fdd">
  <svg width="1000" height="500"></svg>
</div>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:3)

要包含图片元素,您应使用.append("image")代替.append("img")

此外,需要使用xlink:href属性指定图像本身。例如,您可以提供图像链接。

这两个点合起来给出了以下片段:

.append("image")
  .attr("class","flag ar")
  .attr("xlink:href", "https://cdn.sstatic.net/Sites/stackoverflow/img/favicon.ico")

此外,节点的位置似乎已关闭;你可以这样设置他们的位置(翻译它们):

node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })

这是一个演示:

var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height"),
    radius=5;

var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d,index) { return d.id; }).distance(10))
    .force("charge", d3.forceManyBody().distanceMin(10).distanceMax(120))
    .force("center", d3.forceCenter(width / 2, height / 2));

d3.json("https://raw.githubusercontent.com/DealPete/forceDirected/master/countries.json",function(json ) {
  json.nodes.forEach(function(d,i){
    d.id = i;
  })
  
  var link = svg.append("g")
      .attr("class", "links")
    .selectAll("line")
    .data(json.links)
    .enter().append("line")
  .attr("stroke-width","1");
  
    var node = svg.append("g")
      .attr("class", "nodes f32")
    .selectAll("image")
    .data(json.nodes)
    .enter().append("image")
      .attr("class","flag ar")
      .attr("xlink:href", "https://cdn.sstatic.net/Sites/stackoverflow/img/favicon.ico")
      .attr("height", "32") // width/height (are necessary in Firefox to make the image appear)
      .attr("width", "32")
      .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended));


  function ticked() {
    link
        .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; });

    // -16 is half the width/height of the image I used:
    node
      .attr("transform", function(d) { return "translate(" + (d.x - 16) + "," + (d.y - 16) + ")"; })
  }

  simulation
      .nodes(json.nodes)
      .on("tick", ticked);
  
  simulation.force("link")
      .links(json.links);
});

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;
}
.links line {
    stroke: #999;
    stroke-opacity: 0.6;
}
h1{
  font-family: arial;
}
body{
  display:flex;
  justify-content:center;
  align-items:center;
      flex-direction: column;
    background:#d64d4d;
}
.fdd{
 width:1000px;
  height:500px;
  background: white;
  
}
<script src="https://d3js.org/d3.v4.min.js"></script>

<h1>Force Directed Graph of State Contiguity</h1>
<div class="fdd">
  <svg width="1000" height="500"></svg>
</div>

答案 1 :(得分:-1)

我对img和svg:image感到困惑。

var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height"),
    radius=5;
var graph = d3.select(".fdd")
    .append("div")
    .style("width", width + "px")
    .style("height", height + "px")
    .attr('class',"countries f16")


var node = graph
.selectAll("img")
.data(json.nodes)
.enter().append("img")
  .attr("class",function(d){return "flag " +d.code} )
  .call(d3.drag()
      .on("start", dragstarted)
      .on("drag", dragged)
      .on("end", dragended))

  function ticked() {
    link
        .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
        .style("top", function(d) { return d.y + "px"; } )
        .style("left", function(d) { return d.x + "px"; });
  }

在svg中使用img是不行的。

完整的解决方案可以在这里找到:

&#13;
&#13;
var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height"),
    radius=5;
  var graph = d3.select(".fdd")
    .append("div")
    .style("width", width + "px")
    .style("height", height + "px")
    .attr('class',"countries f16")

var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d,index) { return d.id; }).distance(10))
    .force("charge", d3.forceManyBody().distanceMin(10).distanceMax(120))
    .force("center", d3.forceCenter(width / 2, height / 2));

d3.json("https://raw.githubusercontent.com/DealPete/forceDirected/master/countries.json",function(json ) {
  json.nodes.forEach(function(d,i){
    d.id = i;
  })
  
  var link = svg.append("g")
      .attr("class", "links")
    .selectAll("line")
    .data(json.links)
    .enter().append("line")
  .attr("stroke-width","1");
  
    var node = graph
    .selectAll("img")
    .data(json.nodes)
    .enter().append("img")
      .attr("class",function(d){return "flag " +d.code} )
      .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended))
          .on("mouseover", function(data,a){
              return tooltip
              .style("visibility", "visible")
              .attr('class', 'd3-tip')
                .html("<div class='data'>"+data.country+"</div>")
            .style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");})
          .on("mouseout", function(){ 
                    return tooltip.style("visibility", "hidden");});

    var tooltip = d3.select("body")
      .append("div")
      .style("position", "absolute")
      .style("z-index", "100000")
      .style("visibility", "hidden")
      .text("a simple tooltip");     

  function ticked() {
    link
        .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
        .style("top", function(d) { return d.y + "px"; } )
        .style("left", function(d) { return d.x + "px"; });

  }

  simulation
      .nodes(json.nodes)
      .on("tick", ticked);
  
  simulation.force("link")
      .links(json.links);
});

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;
}
&#13;
.links line {
    stroke: #999;
    stroke-opacity: 0.6;
}
svg{
  position:absolute;
}
.countries{
      width: 100%;
    height:100%;
    position: relative;
    margin: 0 auto;
}
h1{
  font-family: arial;
}
body{
  display:flex;
  justify-content:center;
  align-items:center;
      flex-direction: column;
    background:#d64d4d;
}
.fdd{
 width:1000px;
  height:500px;
  background: white;
  
}
.flag{
 position:absolute; 
 border-radius: 50%;
 border: 0;
 transform: translate(-8px,-8px);
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<link href="https://github.com/downloads/lafeber/world-flags-sprite/flags16.css" rel="stylesheet"/>
<h1>Force Directed Graph of State Contiguity</h1>
<div class="fdd">
  <svg width="1000" height="500"></svg>
</div>
&#13;
&#13;
&#13;