javascript - 圆环图中一个段中的多个段?

标签 javascript d3.js charts donut-chart sunburst-diagram

我正在寻找单个段中的多段。

每个段可以有不同的配色方案类别。

我正在寻找这样的东西:

Dounut chart that I want

我试过谷歌搜索,我找不到任何针对一个分割市场的多分割市场的解决方案。

顺便说一句,我正在创建 PowerBi 自定义视觉。

这是我使用 d3 的代码

<!DOCTYPE html>

    <head>
        <script src="https://d3js.org/d3.v4.min.js"></script>
    </head>

    <body>
        <svg></svg>
    </body>

    <script>
        // JSON data
        var nodeData = {
            "name": "TOPICS", "children": [{
                "name": "Active Members",
                "children": [{ "name": "Delta", "size": 230000 }, { "name": "United", "size": 400000 },{ "name": "American", "size": 750000 },{ "name": "Alaska", "size": 250000 }]
            }, {
                "name": "No of customers",
                "children": [{ "name": "Amex", "size": 204300 }, { "name": "Visa", "size": 300000 },{ "name": "Paypal", "size": 400000 },{ "name": "Others", "size": 120000 },{ "name": "Mastercard", "size": 110440 },{ "name": "Discover", "size": 400000 }]
            }, {
                "name": "No of claims Paid",
                "children": [{ "name": "Hospital 1", "size": 150000 }, { "name": "Hospital 2", "size": 200000 }, { "name": "Hospital 3", "size": 300000 }, { "name": "Hospital 4", "size": 500000 }]
            }, {
                "name": "no of amount paid",
                "children": [{ "name": "Pizza", "size": 500000 }, { "name": "Burger", "size": 300000 }, { "name": "Sandwich", "size": 450000 }, { "name": "Toast", "size": 250000 }]
            },
            {
                "name": "Medical Paid",
                "children": [{ "name": "Doctor 1", "size": 300000 }, { "name": "Doctor 2", "size": 200000 }]
            }, {
                "name": "Pharmacy Paid",
                "children": [{ "name": "CVS", "size": 200000 }, { "name": "Walgreens", "size": 100000 }, { "name": "Walrmart", "size": 200000 }, { "name": "Others", "size": 100000 }],
            }]
        };

        // Variables
        var width = 500;
        var height = 500;
        var radius = Math.min(width, height) / 3;
        var color = d3.scaleOrdinal(d3.schemeCategory10);
        var donutWidth = 25;

        // 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(radius - donutWidth)
            .outerRadius(radius)
            // .innerRadius(function (d) { return d.y0 })
            // .outerRadius(function (d) { return d.y1 })
            .padAngle(0.04);

        // 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>

最佳答案

您需要对代码进行 2 次更新才能实现此目的。

1)为每个主题创建一个色标,以便每个子节点在其段内获得唯一的颜色。

2) 由于填充适用于圆环图中的每个段,您可以通过插入带有值的虚拟数据,然后用白色填充这些段来创建父段之间存在间隙的错觉。

     
      
        var nodeData = {
            "name": "TOPICS", "children": [{
                "name": "Active Members",
                "children": [{ "name": "Delta", "size": 230000 }, { "name": "United", "size": 400000 },{ "name": "American", "size": 750000 },{ "name": "Alaska", "size": 250000 }]
            }, {
                "name": "No of customers",
                "children": [{ "name": "Amex", "size": 204300 }, { "name": "Visa", "size": 300000 },{ "name": "Paypal", "size": 400000 },{ "name": "Others", "size": 120000 },{ "name": "Mastercard", "size": 110440 },{ "name": "Discover", "size": 400000 }]
            }, {
                "name": "No of claims Paid",
                "children": [{ "name": "Hospital 1", "size": 150000 }, { "name": "Hospital 2", "size": 200000 }, { "name": "Hospital 3", "size": 300000 }, { "name": "Hospital 4", "size": 500000 }]
            }, {
                "name": "no of amount paid",
                "children": [{ "name": "Pizza", "size": 500000 }, { "name": "Burger", "size": 300000 }, { "name": "Sandwich", "size": 450000 }, { "name": "Toast", "size": 250000 }]
            },
            {
                "name": "Medical Paid",
                "children": [{ "name": "Doctor 1", "size": 300000 }, { "name": "Doctor 2", "size": 200000 }]
            }, {
                "name": "Pharmacy Paid",
                "children": [{ "name": "CVS", "size": 200000 }, { "name": "Walgreens", "size": 100000 }, { "name": "Walrmart", "size": 200000 }, { "name": "Others", "size": 100000 }],
            }]
        };

        // Variables
        var width = 500;
        var height = 500;
        var radius = Math.min(width, height) / 3;
        //var color = d3.scaleOrdinal(d3.schemeCategory10);
        var donutWidth = 25;
      	
      	//CREATE A COLOUR SCALE PER CHILD TOPIC
      	var colourScale = {}
      	nodeData.children.forEach(function(d){
          colourScale[d.name] = d3.scaleOrdinal(d3.schemeCategory10);
        })
     
        //INSERT DATA INTO ARRAY TO CREATE GAPS IN THE DONUT CHART
      	var n = nodeData.children.length
        for (var i = 0; i < n; i++) {
          var position = (i * 2) + 1
          var parentName = "Gap" + i
          var childName = "GapChild"
          var gapData = {"name": parentName, "children": [{"name": childName, "size": 100000}]} //choose a size which gives the desired gap
          nodeData.children.splice(position, 0, gapData)
        }
      
        // 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(radius - donutWidth)
            .outerRadius(radius)
            .padAngle(0.001);

        // Put it all together
        g.selectAll('path')
            .data(root.descendants())
            .enter().append('path')
            .attr("visibility", function (d) { return d.depth == 2 ? "visible" : "hidden"; })
            .attr("d", arc)
            .style('stroke', '#fff')
            .style("fill", function (d) {
								// if the data is for "gap" child element or a parent node, then fill with white, else fill with categorical colour
          			if (d.data.name == "GapChild") {
                  	return "white"
                } else if (d.children) {
                  	return "white"
                } else {
                  	return colourScale[d.parent.data.name](d.data.name); 
                }
          	    
        		});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>


<body>
 <svg></svg>
 </body>

关于javascript - 圆环图中一个段中的多个段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58275633/

相关文章:

d3.js - 在 D3 中加载 TopoJSON 文件时的随机行

javascript - d3.js 具有相同父 Node 的树 Node

java - Java 中的组织结构图/树

javascript - 在 chrome 中缩小到 25% 时,div 中的元素超出范围(不在 div 内)

javascript - 创建可变长度幻灯片显示的幻灯片

javascript - 在表格完成之前,如何禁用 Stripe 付款请求按钮?

javascript - Twitter登录cordova android应用程序

javascript - 如何停止 Shift + 鼠标单击在 Firefox 中打开新窗口

javascript - Chart.js 无法在我的页面上运行?

java - 如何让图表内容区域占据其可用的最大区域?