Направленный граф D3 (v4) не принимает img в качестве узлов - PullRequest
0 голосов
/ 20 мая 2018

Я пытаюсь сгенерировать силовой ориентированный граф.Я могу добиться этого, если я использую «круг / прямоугольник» для рисования узлов.Но я хочу использовать изображение вместо.Что я делаю не так?

Вот как я создаю и преобразовываю узлы (я использую 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>

Ответы [ 2 ]

0 голосов
/ 20 мая 2018

Я был сбит с толку между 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"; });
  }

Наличие img внутри svg не работает.

Полное решение можно найти здесь:

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;
}
.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);
}
<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>
0 голосов
/ 20 мая 2018

Чтобы включить элемент изображения, вы должны использовать .append("image") вместо .append("img").

Кроме того, само изображение должно быть указано с атрибутом xlink:href.Например, вы можете предоставить ссылку на изображение.

Эти 2 комбинированных пункта дают следующий фрагмент:

.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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...