【问题标题】:D3: Sunburst chart with root node on the outside ringD3:外环上有根节点的旭日图
【发布时间】:2018-10-18 20:57:11
【问题描述】:

我正在研究如何在我的公司中简化营销图形的创建。

特别是一个旭日图,它是在 Illustrator 中生成的(难以更新),我想将其切换为 D3 图形(通过 JSON 或 CSV 文件轻松更新)。问题是旭日形图的顺序是倒序...根节点在外环上,数据向内流动。 注意:我不能交换数据的顺序,它必须这样。

是否可以在 D3 中翻转旭日形图的绘制顺序?我一直在尝试排序功能...它按预期翻转了树根图的排序顺序...但似乎不会影响旭日图的排序顺序。

这是我正在使用的旭日形图(来自here):

    // JSON data
    var nodeData = {
        "name": "TOPICS", "children": [{
            "name": "Topic A",
            "children": [{"name": "Sub A1", "size": 4}, {"name": "Sub A2", "size": 4}]
        }, {
            "name": "Topic B",
            "children": [{"name": "Sub B1", "size": 3}, {"name": "Sub B2", "size": 3}, {
                "name": "Sub B3", "size": 3}]
        }, {
            "name": "Topic C",
            "children": [{"name": "Sub A1", "size": 4}, {"name": "Sub A2", "size": 4}]
        }]
    };

    // Variables
    var width = 500;
    var height = 500;
    var radius = Math.min(width, height) / 2;
    var color = d3.scaleOrdinal(d3.schemeCategory20b);

    // Create primary <g> element
    var g = d3.select('svg')
        .attr('width', width)
        .attr('height', height)
        .append('g')
        .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');

    // Data strucure
    var partition = d3.partition()
        .size([2 * Math.PI, radius]);

    // Find data root
    var root = d3.hierarchy(nodeData)
        .sum(function (d) { return d.size});

    // Size arcs
    partition(root);
    var arc = d3.arc()
        .startAngle(function (d) { return d.x0 })
        .endAngle(function (d) { return d.x1 })
        .innerRadius(function (d) { return d.y0 })
        .outerRadius(function (d) { return d.y1 });

    // Put it all together
    g.selectAll('path')
        .data(root.descendants())
        .enter().append('path')
        .attr("display", function (d) { return d.depth ? null : "none"; })
        .attr("d", arc)
        .style('stroke', '#fff')
        .style("fill", function (d) { return color((d.children ? d : d.parent).data.name); });
<script src="https://d3js.org/d3.v4.min.js"></script>
 <svg></svg>
 

非常感谢! jB

【问题讨论】:

  • 是的,有可能。最终形式取决于您的代码。它可以像交换决定弧半径的比例范围的值一样简单(简单的example 基于this,未针对缩放进行修改)。但是如果不共享您的代码,就很难提供具体的解决方案。
  • 安德鲁...非常感谢您的帮助。现在,我正在尝试使用此处找到的 Sunburst 构建示例...bl.ocks.org/denjn5/e1cdbbe586ac31747b4a304f8f86efa5我正在研究概念验证以出售图形利益相关者。我可能会与 coder 联系以构建最终版本……我的编码技能有点生疏。 ;-)

标签: javascript d3.js sunburst-diagram


【解决方案1】:

这应该很简单,每个圆弧的内半径和外半径都需要修改。在原版中,它们设置在这里:

var arc = d3.arc()
    .startAngle(function (d) { return d.x0 })
    .endAngle(function (d) { return d.x1 })
    .innerRadius(function (d) { return d.y0 })
    .outerRadius(function (d) { return d.y1 });

我们不需要将 d.y0 和 d.y1 作为内半径和外半径,而是需要将这些值从旭日形的最终半径中减去。缩放旭日形大小时会找到半径:

var partition = d3.partition()
    .size([2 * Math.PI, radius]);

所以,我们可以使用:

var arc = d3.arc()
    .startAngle(function (d) { return d.x0 })
    .endAngle(function (d) { return d.x1 })
    .innerRadius(function (d) { return radius - d.y1 })
    .outerRadius(function (d) { return radius - d.y0 });

这将父母置于孩子之外。

我把 d.y1 和 d.y0 互换了,因为 d.y0 是指正常向外移动时的内半径,但返回值等于 radius-d.y0,现在是用于定义外半径

这是一个例子:

    // JSON data
    var nodeData = {
        "name": "TOPICS", "children": [{
            "name": "Topic A",
            "children": [{"name": "Sub A1", "size": 4}, {"name": "Sub A2", "size": 4}]
        }, {
            "name": "Topic B",
            "children": [{"name": "Sub B1", "size": 3}, {"name": "Sub B2", "size": 3}, {
                "name": "Sub B3", "size": 3}]
        }, {
            "name": "Topic C",
            "children": [{"name": "Sub A1", "size": 4}, {"name": "Sub A2", "size": 4}]
        }]
    };

    // Variables
    var width = 500;
    var height = 500;
    var radius = Math.min(width, height) / 2;
    var color = d3.scaleOrdinal(d3.schemeCategory20b);

    // Create primary <g> element
    var g = d3.select('svg')
        .attr('width', width)
        .attr('height', height)
        .append('g')
        .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');

    // Data strucure
    var partition = d3.partition()
        .size([2 * Math.PI, radius]);

    // Find data root
    var root = d3.hierarchy(nodeData)
        .sum(function (d) { return d.size});

    // Size arcs
    partition(root);

    var arc = d3.arc()
        .startAngle(function (d) { return d.x0 })
        .endAngle(function (d) { return d.x1 })
        .innerRadius(function (d) { return radius - d.y1; })
        .outerRadius(function (d) { return radius - d.y0; });

    // Put it all together
    g.selectAll('path')
        .data(root.descendants())
        .enter().append('path')
        .attr("d", arc)
        .style('stroke', '#fff')
        .style("fill", function (d) { return color((d.children ? d : d.parent).data.name); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
<svg></svg>

注意,我在这里显示的是根节点,在原始版本中它没有显示(创建一个甜甜圈)。如果你想保持甜甜圈效果,我们可以继续隐藏根,但在半径值上添加一些填充:

  // JSON data
    var nodeData = {
        "name": "TOPICS", "children": [{
            "name": "Topic A",
            "children": [{"name": "Sub A1", "size": 4}, {"name": "Sub A2", "size": 4}]
        }, {
            "name": "Topic B",
            "children": [{"name": "Sub B1", "size": 3}, {"name": "Sub B2", "size": 3}, {
                "name": "Sub B3", "size": 3}]
        }, {
            "name": "Topic C",
            "children": [{"name": "Sub A1", "size": 4}, {"name": "Sub A2", "size": 4}]
        }]
    };

    // Variables
    var width = 500;
    var height = 500;
    var radius = Math.min(width, height) / 2;
    var color = d3.scaleOrdinal(d3.schemeCategory20b);

    // Create primary <g> element
    var g = d3.select('svg')
        .attr('width', width)
        .attr('height', height)
        .append('g')
        .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');

    // Data strucure
    var partition = d3.partition()
        .size([2 * Math.PI, radius]);

    // Find data root
    var root = d3.hierarchy(nodeData)
        .sum(function (d) { return d.size});

    // Size arcs
    partition(root);
    var arc = d3.arc()
        .startAngle(function (d) { return d.x0 })
        .endAngle(function (d) { return d.x1 })
        .innerRadius(function (d) { return radius - d.y1 + root.y1; })
        .outerRadius(function (d) { return radius - d.y0 + root.y1; });

    // Put it all together
    g.selectAll('path')
        .data(root.descendants())
        .enter().append('path')
        .attr("display", function (d) { return d.depth ? null : "none"; })
        .attr("d", arc)
        .style('stroke', '#fff')
        .style("fill", function (d) { return color((d.children ? d : d.parent).data.name); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
<svg></svg>

这里我只是将根节点的外半径(即圆弧的宽度,因为内半径为 0)添加到半径值。请注意,如果要维护甜甜圈并显示根节点,则需要适当调整旭日图的大小。虽然我更倾向于称之为太阳内爆图。

【讨论】:

    猜你喜欢
    • 2016-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-09
    • 2014-10-28
    • 1970-01-01
    • 2014-08-21
    相关资源
    最近更新 更多