【问题标题】:Rotate every arc of pie chart 180 (like sun) with D3 JS. How to calculate translate parameters使用 D3 JS 将饼图的每条弧线旋转 180 度(如太阳)。如何计算平移参数
【发布时间】:2016-08-16 04:26:11
【问题描述】:

我正在使用 d3 js 制作饼图。我想将我的饼图的每条弧线旋转 180 度。我知道我无法完全解释这里是我的小提琴链接。

[fiddle]: https://jsfiddle.net/dsLonquL/ 

如何获取 translate() 函数的动态参数。

【问题讨论】:

    标签: d3.js nvd3.js


    【解决方案1】:

    基本上,您需要计算出每条弧线边缘的中心点。我用这个例子来寻求帮助:How to get coordinates of slices along the edge of a pie chart?

    这工作正常,但我需要旋转点以使它们处于正确的位置。因为它是弧度,所以旋转如下:

     var rotationInRadians = 1.5708 * 1.5;
    

    现在使用我使用路径数据之前的示例,所以开始和结束角度并得到中心点,如下所示:

    var thisAngle = (d.startAngle + rotationInRadians + (d.endAngle + rotationInRadians - d.startAngle + rotationInRadians) / 2);
        var x = centreOfPie[0] + radius * 2 * Math.cos(thisAngle)
        var y = centreOfPie[1] + radius * 2 * Math.sin(thisAngle)
    

    我创建了一个函数来在这些点显示圆圈以澄清:

    function drawCircle(points, colour) {
        svg.append('circle')
          .attr('cx', points[0])
          .attr('cy', points[1])
          .attr('r', 5)
          .attr('fill', colour);
    
      }
    

    在当前函数中这样调用它:

    drawCircle([x, y], color(d.data.label))
    

    然后进行相应的平移和旋转:

    return 'translate(' + (x) + ',' + y + ') rotate(180)';
    

    我添加了一个过渡,以便您可以看到它正在工作。这是最后的小提琴:

    https://jsfiddle.net/thatOneGuy/dsLonquL/7/

    编辑

    在您的 cmets 中,您说您希望将最大的部分保留在中间。因此,我们需要遍历细分市场并获得最大的收益。我还处理了重复项,即如果两个或多个段的大小相同。

    这是添加的代码:

     var biggestSegment = {
        angle: 0,
        index: []
      };
    
     path.each(function(d, i) {
        var thisAngle = (d.endAngle - d.startAngle).toFixed(6);//i had to round them as the numbers after around the 7th or 8th decimal point tend to differ tet theyre suppose to be the same value
        if (i == 0) {
          biggestSegment.angle = thisAngle
        } else {
          if (biggestSegment.angle < thisAngle) {
            biggestSegment.angle = thisAngle;
            biggestSegment.index = [i];
          } else if (biggestSegment.angle == thisAngle) {
          console.log('push')
            biggestSegment.index.push(i);
          }
        }
      })
    

    现在这会检查每个路径是否大于当前值,是否覆盖最大值并记下索引。如果相同,则在索引数组中添加索引。

    现在在转换路径时,您需要对照上面的索引数组检查当前索引,看看它是否需要旋转。像这样:

     if (biggestSegment.index.indexOf(i) > -1) {
          return 'translate(' + (centreOfPie[0]) + ',' + (centreOfPie[1]) + ')' // rotate(180)';
        } else {
          return 'translate(' + (x) + ',' + y + ') rotate(180)';
        }
    

    更新小提琴:https://jsfiddle.net/thatOneGuy/dsLonquL/8/

    我已将 3 个值编辑为与其他值不同。继续改变这些,看看你的想法:)

    【讨论】:

    • 如果这些不在正确的位置,只需在设置 x 和 y 时编辑第一个值。所以此刻它的 centerOfPie[n],centerOfPie 所在的位置,你猜对了,是饼图的中心。
    • 谢谢@thatOneGuy,你给了我希望,我可以完成。这太接近我的需要了。我正在做。问题是,如果有不同大小的不同切片而不是如何管理它。它到处都是,但我们需要该图表附近有附近的切片。
    • 我不确定我是否理解这个问题。我放在一起的代码应该适合不同大小的段。你那边怎么了?
    • 如果我改变了一个数据集的计数值,除了那个切片之外,它的边距很大,远离其他切片。试试这个数据集 { label: 'green', count: 200 },
    • 如果你在那里拥有巨大的价值,你希望它是什么样子?
    【解决方案2】:

    这是一个纯粹的中学几何作业。

    案例一:每个扇形旋转的顶点在圆的外线上

    fiddle

    // ... previous code there
    .attr('fill', function(d, i) {
            return color(d.data.label);
          })
    .attr("transform", function(d, i) {
        var a = (d.endAngle + d.startAngle) / 2, // angle of vertex
            dx = 2 * radius * Math.sin(a),       // shift/translate  is two times of the vertex coordinate
            dy = - 2 * radius * Math.cos(a);     // the same
            return ("translate(" + dx + " " + dy + ") rotate(180)"); // output
          });
    

    案例2:和弦中心的顶点

    fiddle

    // ... previous code there
    .attr('fill', function(d, i) {
            return color(d.data.label);
          })
    .attr("transform", function(d, i) {
        var dx = radius * (Math.sin(d.endAngle) + Math.sin(d.startAngle)), // shift/translation as coordinate of vertex
            dy = - radius * (Math.cos(d.endAngle) + Math.cos(d.startAngle)); // the same for Y
            return ("translate(" + dx + " " + dy + ") rotate(180)"); // output
          });    
    

    【讨论】:

    • 感谢@Ruben Kazumov 一切都很完美,但如果我更改数据,则结构不合适。 fiddle link
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 2020-08-26
    相关资源
    最近更新 更多