D3弧 - cornerRadius在接近360度时出现故障

时间:2015-09-22 13:07:13

标签: d3.js svg

我设法创建了一个带圆角的动画弧,但是只有在使用圆角时才会出现错误。

删除过渡并没有什么不同。

左边是351度,右边是350度正确。

enter image description here enter image description here

CODEPEN here

var angle = 350; // Change to 351 to see the bug
var width = 150;
var height = 150;
var innerRadius = width / 2 * 0.85;
var outerRadius = width / 2;
var color = '#45C600';
var colorBackground = '#EFEFEF';

var arc = d3.svg.arc()
  .innerRadius(innerRadius)
  .outerRadius(outerRadius)
  .cornerRadius(20)
  .startAngle(0);

var svg = d3.select("#chart").append("svg")
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")

var background = svg.append("path")
  .datum({
    endAngle: 360 * (Math.PI) / 180
  })
  .style("fill", colorBackground)
  .attr("d", arc);

var foreground = svg.append("path")
  .datum({
    endAngle: (Math.PI) / 180
  })
  .style("fill", color)
  .attr("d", arc);

foreground.transition()
  .duration(750)
  .call(arcTween, angle * (Math.PI) / 180);

function arcTween(transition, newAngle) {
  transition.attrTween("d", function(d) {
    var interpolate = d3.interpolate(d.endAngle, newAngle);

    return function(t) {
      d.endAngle = interpolate(t);
      return arc(d);
    };
  });
}

1 个答案:

答案 0 :(得分:2)

我修复了这个问题,并且我将这个答案发布给将来遇到这个bug的人,而且还没有修复。

事实证明,这是d3.js中的一个错误:

GitHub Issue

解决方案:

下载d3.js的详细版本:https://raw.githubusercontent.com/mbostock/d3/master/d3.js

第7989-8003行应如下所示:

      if (rc === rc1) {
        path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]);
      } else {
        path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]);
      }
    } else {
      path.push("M", x0, ",", y0);
    }
    if (x3 != null) {
      var rc0 = Math.min(rc, (r0 - lc) / (kc - 1)), t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw);
      if (rc === rc0) {
        path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
      } else {
        path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
      }

注释掉第7989,7991,7992,7993,7999,8001,8002和8003行

这应该是这样的:

    //   if (rc === rc1) {
        path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]);
    //   } else {
    //     path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]);
    //   }
    } else {
      path.push("M", x0, ",", y0);
    }
    if (x3 != null) {
      var rc0 = Math.min(rc, (r0 - lc) / (kc - 1)), t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw);
    //   if (rc === rc0) {
        path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
    //   } else {
    //     path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
    //   }