如何将甜甜圈图分成固定部分

How to divide donut chart into fixed portion

我尝试搜索但找不到解决方案。

我的数据是这样的:

var data =  [
        {   "hour":"10",    
            "percentage":"50"
        },
        {   "hour":"11",    
            "percentage":"20"
        },
        {   "hour":"3", 
        "percentage":"90"
        },
        {   "hour":"55",    
            "percentage":"40"
        },
        {   "hour":"6", 
            "percentage":"70"
        },
        {   "hour":"8", 
            "percentage":"40"
        }
    ];

我根据这个数据绘制圆环图。我需要:

  1. 像时钟一样将图表分成12等份。

  2. 我有颜色范围来描述百分比,但是如果我的小时属性中没有数据怎么办?

我是 D3JS 的新手,我无法理解其中的逻辑。下面是我的圆环图。

在此先致谢。

    var data = [
         { "hour":"10", 
          "percentage":"50"
         },
         { "hour":"11", 
          "percentage":"20"
         },
         { "hour":"3", 
      "percentage":"90"
         },
         { "hour":"55", 
          "percentage":"40"
         },
         { "hour":"6", 
          "percentage":"70"
         },
         { "hour":"8", 
          "percentage":"40"
         }
        ];



    var can =     d3.select("body").append("svg").attr("height",1000).attr("width",1000);
                //var svg = d3.select(can[0]);
                var r =100;
                var p = Math.PI*2;
                var color = d3.scale.linear()
                            .domain([0,100])
                            .range(["white","red"]);
                 var group = can.append("g")
                            .attr("transform","translate(100,100)");

                var arc = d3.svg.arc()
                        .innerRadius(r - 30)
                        .outerRadius(r)
                        //.startAngle(0)
                        .endAngle(p-1);


                var pie = d3.layout.pie()
                        .sort(null)
                        .value(function (d){return d.percentage;});

                 var arcs = group.selectAll(".arc")
                            .data(pie(data))
                            .enter().append("g")
                            .attr("class", "arc")
                            .attr('fill',function(d){return     color(d.data.percentage)})
                            .on("mouseover", function(d){
                                div.style("display", "inline")
                                 .text(d.data.percentage + ", " + d.data.hour)
                                .style("left", (d3.event.pageX - 34) + "px")
                                .style("top", (d3.event.pageY - 12) + "px");
                                     })
                             .on("mouseout", mouseout);


                arcs.append("path")
                                .attr("d", arc)
                                .style("fill", function (d) {
                                return color(d.data.percentage);
                });

                var div = d3.select("body").append("div")
                                                .attr("class", "tooltip")
                                                .style("display", "none");


                 function mouseout() {
                                 div.style("display", "none");
                        }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

如果你想要它们相等,那么你在 pie.value() 中的使用百分比是怎么来的?

Pie.value() 是您拆分饼图的方式。

所以我要做的是创建一个虚拟值来创建相等的部分:

for(i=0;i<data.length;i++){
   data[i].value = 1;
}

现在您将值传递给 pie.value() 而不是百分比:

var pie = d3.layout.pie()
  .sort(null)
  .value(function(d) {
    return d.value
    //return d.percentage
  });

而你的图表没有完全显示的原因是因为这条线:

.endAngle(p-1);

Math.PI 以弧度为单位,因此这就是您设置的角度:

p = 6.28319 radians;

p-1 = 5.28319 radians;

因此

p-1 = 302.7044894 degrees;

把-1拿掉就是一个完整的圆。

这是当前数据:

var data = [{
  "hour": "10",
  "percentage": "50"
}, {
  "hour": "11",
  "percentage": "20"
}, {
  "hour": "3",
  "percentage": "90"
}, {
  "hour": "55",
  "percentage": "40"
}, {
  "hour": "6",
  "percentage": "70"
}, {
  "hour": "8",
  "percentage": "40"
}];

for (i = 0; i < data.length; i++) {
  data[i].value = 1;
}


var can = d3.select("body").append("svg").attr("height", 1000).attr("width", 1000);
//var svg = d3.select(can[0]);
var r = 100;
var p = Math.PI * 2;
var color = d3.scale.linear()
  .domain([0, 100])
  .range(["white", "red"]);
var group = can.append("g")
  .attr("transform", "translate(100,100)");

var arc = d3.svg.arc()
  .innerRadius(r - 30)
  .outerRadius(r)
  //.startAngle(0)
  .endAngle(p );


var pie = d3.layout.pie()
  .sort(null)
  .value(function(d) {
    return d.value
      //return d.percentage
  });

var arcs = group.selectAll(".arc")
  .data(pie(data))
  .enter().append("g")
  .attr("class", "arc")
  .attr('fill', function(d) {
    //console.log(d)
    return color(d.data.percentage)
  })
  .on("mouseover", function(d) {
    div.style("display", "inline")
      .text(d.data.percentage + ", " + d.data.hour)
      .style("left", (d3.event.pageX - 34) + "px")
      .style("top", (d3.event.pageY - 12) + "px");
  })
  .on("mouseout", mouseout);


arcs.append("path")
  .attr("d", arc)
  .style("fill", function(d) {
    return color(d.data.percentage);
  });

var div = d3.select("body").append("div")
  .attr("class", "tooltip")
  .style("display", "none");


function mouseout() {
  div.style("display", "none");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

现在你把问题分成 12 个等份。我认为你需要在这里扩展你想要的东西。你想显示缺失的部分吗?以不同的颜色显示?你想要什么 ?

要解决其中的每一个问题,您将不得不创建数据并将其添加到现有数据中,如下所示:

var newData = [];
for (i = 1; i <= 12; i++) { //go through numbers 1-12 like a clock
  var thisData;
  var inData = false; //bool to check if data exists already
  for (j = 0; j < data.length; j++) { //go through existing data
    if (data[j].hour == i) { //check if data exists
      inData = true; //data exists
      thisData = {
        "hour": data[j].hour, //add data at [i]
        "percentage": data[j].percentage, //add data at [i]
        "value": data[j].value //add data at [i]
      }
      newData.push(thisData) //push into new array
    }
  }
  if (!inData) { //if data doesnt exist
    thisData = {
      "hour": i, //set hour to i
      "percentage": 0, 
      "value": 1
    }
    newData.push(thisData) //push into new data
  }
}
console.log(newData)

这是包含新数据的饼图,其值仍为 1,因此您得到了相等的部分。它们是白色的,因为它们没有百分比,我添加了一笔,这样你就可以分辨出哪个是哪个:)

var data = [{
  "hour": "10",
  "percentage": "50"
}, {
  "hour": "11",
  "percentage": "20"
}, {
  "hour": "3",
  "percentage": "90"
}, {
  "hour": "5",
  "percentage": "40"
}, {
  "hour": "6",
  "percentage": "70"
}, {
  "hour": "8",
  "percentage": "40"
}];

for (i = 0; i < data.length; i++) {
  data[i].value = 1;
}

var newData = [];
for (i = 1; i <= 12; i++) { //go through numbers 1-12 like a clock
  var thisData;
  var inData = false; //bool to check if data exists already
  for (j = 0; j < data.length; j++) { //go through existing data
    if (data[j].hour == i) { //check if data exists
      inData = true; //data exists
      thisData = {
        "hour": data[j].hour, //add data at [i]
        "percentage": data[j].percentage, //add data at [i]
        "value": data[j].value //add data at [i]
      }
      newData.push(thisData) //push into new array
    }
  }
  if (!inData) { //if data doesnt exist
    thisData = {
      "hour": i, //set hour to i
      "percentage": 0, 
      "value": 1
    }
    newData.push(thisData) //push into new data
  }
}
console.log(newData)


var can = d3.select("body").append("svg").attr("height", 1000).attr("width", 1000);
//var svg = d3.select(can[0]);
var r = 100;
var p = Math.PI * 2;
var color = d3.scale.linear()
  .domain([0, 100])
  .range(["white", "red"]);

var group = can.append("g")
  .attr("transform", "translate(100,100)");

var arc = d3.svg.arc()
  .innerRadius(r - 30)
  .outerRadius(r)
  //.startAngle(0)
  .endAngle(p);


var pie = d3.layout.pie()
  .sort(null)
  .value(function(d) {
    return d.value
      //return d.percentage
  });

var arcs = group.selectAll(".arc")
  .data(pie(newData))
  .enter().append("g")
  .attr("class", "arc")
  .attr('fill', function(d) {
    //console.log(d)
    return color(d.data.percentage)
  })
  .style('stroke','black')
  .on("mouseover", function(d) {
    div.style("display", "inline")
      .text(d.data.percentage + ", " + d.data.hour)
      .style("left", (d3.event.pageX - 34) + "px")
      .style("top", (d3.event.pageY - 12) + "px");
  })
  .on("mouseout", mouseout);


arcs.append("path")
  .attr("d", arc)
  .style("fill", function(d) {
    return color(d.data.percentage);
  });

var div = d3.select("body").append("div")
  .attr("class", "tooltip")
  .style("display", "none");


function mouseout() {
  div.style("display", "none");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>