Преобразование только определенных узлов в диаграмме Санки D3 из прямоугольника в круг

Я хотел бы воспроизвести процесс из Диаграмма Санки D3 использует узел круга вместо узла прямоугольника, однако я хотел бы выбрать только определенные узлы, чтобы перейти от прямоугольников к кругам.

Например, в этом jsfiddle, используемом в примере, как бы вы выбрали только Node 4 и Node 7 для преобразования в круг?

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


person Clayton    schedule 03.10.2014    source источник


Ответы (2)


Я обновил вашу скрипту.

По сути, вам просто нужно каким-то образом выбрать узлы, которые вы хотите сделать разными. Я использовал уникальное имя класса, чтобы вы также могли стилизовать их с помощью CSS. Мне не хотелось писать код для выбора только 4 и 7 (мне лень), поэтому вместо этого я просто выбрал все четные узлы.

// add in the nodes
var node = svg.append("g").selectAll(".node")
    .data(graph.nodes)
    .enter().append("g")
    .attr("class", function (d, i) { return i % 2 ? "node rect" : "node circle";
})

Затем вы можете использовать это, чтобы выбрать узлы и добавить круги вместо прямоугольников.

svg.selectAll(".node.circle").append("circle")
    .attr("r", sankey.nodeWidth() / 2)
    .attr("cy", function(d) { return d.dy/2; })
    .attr("cx", sankey.nodeWidth() / 2)
    .style("fill", function (d) {
person Bill    schedule 19.12.2014

Существует также другой подобный подход, показанный в следующем jsfiddle.

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


Я начал с этой скрипки (из другого ТАКОЙ вопрос, который вы упомянули)), где все узлы уже были преобразованы в круги:

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

Затем я изменил существующий и добавил новый код, который включает фильтрацию при создании кругов:

// add the circles for "node4" and "node7"
node
    .filter(function(d){ return (d.name == "node4") || (d.name == "node7"); })
    .append("circle")
    .attr("cx", sankey.nodeWidth()/2)
    .attr("cy", function (d) {
        return d.dy/2;
    })
    .attr("r", function (d) {
        return Math.sqrt(d.dy);
    })
    .style("fill", function (d) {
        return d.color = color(d.name.replace(/ .*/, ""));
    })
    .style("fill-opacity", ".9")
    .style("shape-rendering", "crispEdges")
    .style("stroke", function (d) {
        return d3.rgb(d.color).darker(2);
    })
    .append("title")
    .text(function (d) {
        return d.name + "\n" + format(d.value);
    });

// add the rectangles for the rest of the nodes
node
    .filter(function(d){ return !((d.name == "node4") || (d.name == "node7")); })
    .append("rect")
    .attr("y", function (d) {
        return d.dy/2 - Math.sqrt(d.dy)/2;
    })
    .attr("height", function (d) {
        return Math.sqrt(d.dy);
    })
    .attr("width", sankey.nodeWidth())
    .style("fill", function (d) {
        return d.color = color(d.name.replace(/ .*/, ""));
    })
    .style("fill-opacity", ".9")
    .style("shape-rendering", "crispEdges")
    .style("stroke", function (d) {
        return d3.rgb(d.color).darker(2);
    })
    .append("title")
    .text(function (d) {
        return d.name + "\n" + format(d.value);
    });

Аналогичный код пришлось модифицировать для точного позиционирования текста рядом с прямоугольниками.

Я считаю, что окончательный результат выглядит естественным, даже несмотря на то, что он потерял некоторые качества оригинального Sankey (например, более широкие связи).

person VividD    schedule 19.12.2014