D3: Замена d3.svg.diagonal() на d3.svg.line()

Я реализовал следующий график с ребрами, отображаемыми с помощью d3.svg.diagonal(). Однако, когда я пытаюсь заменить диагональ на d3.svg.line(), кажется, что она не извлекает целевые и исходные данные. Что мне не хватает? Я что-то не понимаю в d3.svg.line?

введите здесь описание изображения

Ниже приведен код, на который я ссылаюсь, за которым следует полный код:

var line = d3.svg.line()
    .x(function(d) { return d.lx; })
    .y(function(d) { return d.ly; });

...

var link= svg.selectAll("path")
    .data(links)
  .enter().append("path")
    .attr("d",d3.svg.diagonal())
    .attr("class", ".link")
    .attr("stroke", "black")
    .attr("stroke-width", "2px")
    .attr("shape-rendering", "auto")
    .attr("fill", "none"); 

Весь код:

var margin = {top: 20, right: 20, bottom: 20, left: 20},
    width =1500, 
    height = 1500, 
    diameter = Math.min(width, height),
    radius = diameter / 2;


var balloon = d3.layout.balloon()
  .size([width, height])
  .value(function(d) { return d.size; })
  .gap(50)                  

var line = d3.svg.line()
    .x(function(d) { return d.lx; })
    .y(function(d) { return d.ly; });


var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + (margin.left + radius) + "," + (margin.top + radius) + ")")

    root = "flare.json";
    root.y0 = height / 2;
    root.x0 = width / 2;

d3.json("flare.json", function(root) {
  var nodes = balloon.nodes(root),
      links = balloon.links(nodes);


var link= svg.selectAll("path")
    .data(links)
  .enter().append("path")
    .attr("d",d3.svg.diagonal())
    .attr("class", ".link")
    .attr("stroke", "black")
    .attr("stroke-width", "2px")
    .attr("shape-rendering", "auto")
    .attr("fill", "none");   

  var node = svg.selectAll("g.node")
    .data(nodes)
    .enter()
    .append("g")
    .attr("class", "node");

  node.append("circle")
      .attr("r", function(d) { return d.r; })
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });

  node.append("text")
      .attr("dx", function(d) { return d.x })
      .attr("dy", function(d) { return d.y })
      .attr("font-size", "5px")
      .attr("fill", "white")
      .style("text-anchor", function(d) { return d.children ? "middle" : "middle"; })
      .text(function(d) { return d.name; })
});

Сравнение того, как атрибут d в svg исчезает при использовании «линии». введите здесь описание изображениявведите здесь описание изображения


person Jakub Svec    schedule 17.04.2013    source источник
comment
Кажется, вы нигде в коде не используете line. Атрибут d пути по-прежнему устанавливается с помощью d3.svg.diagonal.   -  person Lars Kotthoff    schedule 18.04.2013
comment
Да, но когда я заменяю d3.svg.diagonal()0 строкой, это нарушает видимость. Не могу понять, почему.   -  person Jakub Svec    schedule 19.04.2013
comment
Атрибут d для svg исчезает. Я загружу сравнение выше.   -  person Jakub Svec    schedule 19.04.2013
comment
Вы пробовали только d3.svg.line() без специальных средств доступа для x и y?   -  person Lars Kotthoff    schedule 19.04.2013
comment
У вас есть JSFiddle или что-то подобное?   -  person Ian    schedule 11.12.2014
comment
@JakubSvec Не могли бы вы помочь мне с этим stackoverflow.com/questions/67002241/?   -  person monica    schedule 08.04.2021


Ответы (4)


Вопрос довольно устарел, но поскольку я не вижу ответа и кто-то может столкнуться с той же проблемой, вот он.

Причина, по которой простая замена diagonal на line не работает, заключается в том, что d3.svg.line и d3.svg.diagonal< /em> возвращает разные результаты:

  • d3.svg.diagonal возвращает функцию, которая принимает датум и его индекс и преобразует его в путь, используя проекцию. Другими словами, diagonal.projection определяет, как функция будет получать координаты точек из предоставленных данных.
  • d3.svg.line возвращает функцию, которая принимает массив точек линии и преобразует его в путь. Методы line.x и line.y определяют, как координаты точки извлекаются из одного элемента предоставленного массива.

Справочник по SVG-фигурам D3

Пути SVG и D3.js

Таким образом, вы не можете использовать результат d3.svg.line непосредственно в выборе d3 (по крайней мере, когда вы хотите нарисовать несколько строк).

Вам нужно обернуть его в другую функцию следующим образом:

var line = d3.svg.line()
                 .x( function(point) { return point.lx; })
                 .y( function(point) { return point.ly; });

function lineData(d){
    // i'm assuming here that supplied datum 
    // is a link between 'source' and 'target'
    var points = [
        {lx: d.source.x, ly: d.source.y},
        {lx: d.target.x, ly: d.target.y}
    ];
    return line(points);
}

// usage:
var link= svg.selectAll("path")
    .data(links)
    .enter().append("path")
    .attr("d",lineData)
    .attr("class", ".link")
    .attr("stroke", "black")
    .attr("stroke-width", "2px")
    .attr("shape-rendering", "auto")
    .attr("fill", "none");   

Здесь опубликована рабочая версия jsFiddle mobeets: jsFiddle

person elusive-code    schedule 21.11.2013
comment
Я думаю, что .attr("d", function (d) { return line([ {lx: d.target.x, ly: d.target.y},{lx: d.source.x, ly: d.source.y} ]); }); - лучший способ сделать это вместо того, чтобы обернуть line() в глобальную функцию. - person jkutianski; 23.07.2014
comment
Дополнительные баллы за предоставление замены diagonal для этого контекста, elusive-code, вместо предоставления альтернативного решения. Прошло более полутора лет, и, как вы сказали, кто-то может столкнуться с той же проблемой (я). Я не нашел этого решения в такой простой форме больше нигде, и наверняка найдется много людей, которым оно понадобится. - person Mars; 17.03.2015
comment
@elusive-code Можете ли вы помочь мне с этим stackoverflow.com/questions/67002241/? - person monica; 08.04.2021

У меня была та же проблема... Здесь jsFiddle .

Обратите внимание, что изменение line на diagonal заставит его работать.

person mobeets    schedule 15.07.2013
comment
Мое предложение состояло бы в том, чтобы опубликовать код из jsFiddle здесь, так как он не всегда надежен и работает. Тогда конкретный ответ будет доступен в этом ответе без необходимости перехода на внешний веб-сайт. - person Taryn; 16.07.2013
comment
@mobeets Вы должны передать правильный ввод line(). Вы можете сделать это переносом line() на другую функцию в качестве рекомендуемого @elusive-code или вернуть line() правильные входные значения, как показано на моя модификация вашей скрипки. - person jkutianski; 23.07.2014

Возможно, вам подойдет инкапсуляция диагональной функции и редактирование ее параметров:

var diagonal = d3.svg.diagonal();
var new_diagonal = function (obj, a, b) {
    //Here you may change the reference a bit.
    var nobj = {
        source : {
            x: obj.source.x,
            y: obj.source.y
        },
        target : {
            x: obj.target.x,
            y: obj.target.y
        }
    }
    return diagonal.apply(this, [nobj, a, b]);
}
var link= svg.selectAll("path")
    .data(links)
    .enter().append("path")
    .attr("d",new_diagonal)
    .attr("class", ".link")
    .attr("stroke", "black")
    .attr("stroke-width", "2px")
    .attr("shape-rendering", "auto")
    .attr("fill", "none"); 
person natanael    schedule 28.10.2013

Просто установите атрибут d ссылки на строку:

.attr("d", line)
person Christopher Chiche    schedule 18.04.2013
comment
Да, но когда я заменяю d3.svg.diagonal()0 строкой, это нарушает видимость. - person Jakub Svec; 19.04.2013
comment
Можете ли вы создать небольшой пример на jsFiddle? - person Christopher Chiche; 19.04.2013
comment
Я пытался, но исходный код с макетом шара находится на github, и, похоже, он его не принимает. - person Jakub Svec; 19.04.2013