画布填充铬的颜色错误

时间:2017-05-05 18:48:59

标签: javascript google-chrome html5-canvas

这是问题的图片。我正在绘制这个色轮,并使用

    var context = canvas.getContext("2d");
    ...
    context.fillStyle = "rgba(" + r + ", " + g + ", " + b + ", 1)";
    context.fill();

对于车轮中每个颜色不同的部分。

这里的浏览器顺序为:
Chrome | Firefox | IE

Chrome | Firefox | IE

无论出于何种原因,它看起来都在Chrome中搞砸了。我甚至不确定如何正确描述这个问题,因此很难看出这是否是一个已知问题。

编辑:这是一个小提琴https://jsfiddle.net/mattlokk/7whrmo8r/3/

编辑2:似乎只发生在Chrome版本58.x中,无论Chrome版本是什么,它在某些机器上都能正常运行。

1 个答案:

答案 0 :(得分:1)

解决方法

是的,有一个接缝是chrome中arc函数的错误(我使用了Canary 60)

第一个解决方法

由于错误不是您可以解决的问题,因此您需要使用解决方法。在这种情况下,一个简单的解决方案是为arc创建一个阴影函数。

// x,y center of arc
// r is radius
// start and end are in radians
// dir (optional) if truthy true draw path anti clock wise.
// returns undefined;
function arcFix (x, y, r, start, end, dir) {
    var ang;
    var step = 1 / r;
    if (dir) {
      end -= step / 2; // end bumped down by half a step to ensure rounding error does not miss end
      for (ang = start; ang > end; ang -= step) {  
          context.lineTo(
              Math.cos(ang) * r + x,
              Math.sin(ang) * r + y,
          );
      }
    } else {
      end += step / 2; // end bumped up half a step to ensure rounding error does not miss end
      for (ang = start; ang < end; ang += step) {  
          context.lineTo(
              Math.cos(ang) * r + x,
              Math.sin(ang) * r + y,
          );
      }
    }    
}

添加上述功能,并在呈现每个颜色段的代码中替换调用上述函数的两个ctx.arc调用

context.beginPath();
context.moveTo(innerX1, innerY1);
context.lineTo(outerX1, outerY1);
// use shadow function
arcFix(centerX, centerY, (outerRadius - 1), startRadians, endRadians);
context.lineTo(innerX2, innerY2);
// use shadow function
arcFix(centerX, centerY, (innerRadius + 1), endRadians, startRadians, true);

请注意,arcFix功能并非arc的完全替代功能,并且仅针对此特定情况进行了测试。如果你在其他地方使用它,你应该测试它(因为你应该测试所有代码)。

第二种解决方法

从半径中删除+1-1也可以解决问题。并不是你错误地使用了2D上下文,因为效果正在创建一个alpha渐变,无论你在哪里添加路径段都不会发生这种情况。

context.lineTo(outerX1, outerY1);
context.arc(centerX, centerY, outerRadius , startRadians, endRadians);
//                                       ^ remove - 1
context.lineTo(innerX2, innerY2);
context.arc(centerX, centerY, innerRadius , endRadians, startRadians, true);
//                                       ^ remove + 1