HTML5 Canvas粗线宽椭圆有奇怪的空白

时间:2015-12-26 07:28:13

标签: javascript html5 html5-canvas

我正在使用html5画布制作绘图应用。 用户可以绘制椭圆并选择线条颜色和填充颜色。 (包括透明色)
当选择的颜色不透明时,它可以正常工作。 但是当选择透明色并且边框线宽很厚时,会出现问题。(Q1和Q2)

这是图像
http://tinypic.com/view.php?pic=28ry4z&s=9#.VoRs7U8jHSg

我正在使用下面的drawEllipse()方法 the relation of the bezier Curve and ellipse?

有没有人解决这个问题? 任何帮助将不胜感激。

[Q1] 当lineWidth大于椭圆的宽度时,椭圆中有一个奇怪的空白,而lineWidth非常薄。 Internet Explorer工作正常,但Firefox和Safari Web浏览器都存在此问题。 如何将空白区域更改为蓝色?

[Q2] 我使用的是透明色,我想用2种颜色绘制椭圆 (笔划为蓝色,填充为红色) 但是笔触颜色和填充颜色混合在一起,椭圆中有洋红色区域。 如何用2种颜色绘制椭圆?
(我想将洋红色区域改为蓝色)
在可能的情况下,首选填充一次。

这是我的代码

// this method is from
// https://stackoverflow.com/questions/14169234/the-relation-of-the-bezier-curve-and-ellipse
function _drawEllipse(ctx, x, y, w, h) {
  var width_over_2 = w / 2;
  var width_two_thirds = w * 2 / 3;
  var height_over_2 = h / 2;

  ctx.beginPath();
  ctx.moveTo(x, y - height_over_2);
  ctx.bezierCurveTo(x + width_two_thirds, y - height_over_2, x + width_two_thirds, y + height_over_2, x, y + height_over_2);
  ctx.bezierCurveTo(x - width_two_thirds, y + height_over_2, x - width_two_thirds, y - height_over_2, x, y - height_over_2);
  ctx.closePath();
  ctx.stroke();
}

function ellipse_test() {
  var canvas = document.getElementById('sample1');
  var ctx = canvas.getContext('2d');

  var x = 100;
  var y = 100;
  var w = 40;
  var h = 100;
  ctx.lineWidth = 30;
  ctx.fillStyle = "rgba(255,0,0,0.5)";
  ctx.strokeStyle = "rgba(0,0,255,0.5)";
  ctx.globalCompositeOperation = "source-over";

  for (var r = 0; r < 50; r++) {
    _drawEllipse(ctx, x, y, r, r * 2);
    ctx.fill();
    x += 60;

    if (x > 1000) {
      x = 100;
      y += 200;
    }
  }
}

ellipse_test();
<canvas id="sample1" style="border:1px solid blue; background:black;" width="1200" height="800"></canvas>

this is the image on firefox

1 个答案:

答案 0 :(得分:1)

这两个问题都是由于一个区域上的多个笔划/填充半透明颜色会导致该区域变成颜色混合(很像艺术家混合多种颜色)。

您可以通过将半透明颜色转换为不透明颜色来解决这两个问题:

function RGBAtoRGB(r, g, b, a, backgroundR,backgroundG,backgroundB){
  var r3 = Math.round(((1 - a) * backgroundR) + (a * r))
  var g3 = Math.round(((1 - a) * backgroundG) + (a * g))
  var b3 = Math.round(((1 - a) * backgroundB) + (a * b))
  return "rgb("+r3+","+g3+","+b3+")";
} 

// convert 50%-red foreground fill + 100% black background into opaque (=="red-brownish")
ctx.fillStyle = RGBAtoRGB(255,0,0,0.50, 0,0,0,1); // "rgba(255,0,0,0.5)";

// convert 50%-blue foreground stroke + 100% black background into opaque (=="blueish")
ctx.strokeStyle = RGBAtoRGB(0,0,255,0.50, 0,0,0,1); // "rgba(0,0,255,0.5)";

enter image description here

重构的示例代码使用不透明填充&am​​p;笔

&#13;
&#13;
ellipse_test();

// this method is from
// http://stackoverflow.com/questions/14169234/the-relation-of-the-bezier-curve-and-ellipse
function _drawEllipse(ctx, x, y, w, h) {
  var width_over_2 = w / 2;
  var width_two_thirds = w * 2 / 3;
  var height_over_2 = h / 2;

  ctx.beginPath();
  ctx.moveTo(x, y - height_over_2);
  ctx.bezierCurveTo(x + width_two_thirds, y - height_over_2, x + width_two_thirds, y + height_over_2, x, y + height_over_2);
  ctx.bezierCurveTo(x - width_two_thirds, y + height_over_2, x - width_two_thirds, y - height_over_2, x, y - height_over_2);
  ctx.closePath();
}

function ellipse_test() {
  var canvas = document.getElementById('sample1');
  var ctx = canvas.getContext('2d');

  var x = 100;
  var y = 100;
  var w = 40;
  var h = 100;
  ctx.lineWidth = 30;

  ctx.fillStyle = 'black';
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  ctx.fillStyle = RGBAtoRGB(255, 0, 0, 0.50, 0, 0, 0, 1); // "rgba(255,0,0,0.5)";
  ctx.strokeStyle = RGBAtoRGB(0, 0, 255, 0.50, 0, 0, 0, 1); // "rgba(0,0,255,0.5)";


  ctx.globalCompositeOperation = "source-over";

  for (var r = 0; r < 50; r++) {
    _drawEllipse(ctx, x, y, r, r * 2);
    ctx.stroke();
    ctx.fill();
    x += 60;

    if (x > 1000) {
      x = 100;
      y += 200;
    }
  }
}


function RGBAtoRGB(r, g, b, a, backgroundR, backgroundG, backgroundB) {
  var r3 = Math.round(((1 - a) * backgroundR) + (a * r))
  var g3 = Math.round(((1 - a) * backgroundG) + (a * g))
  var b3 = Math.round(((1 - a) * backgroundB) + (a * b))
  return "rgb(" + r3 + "," + g3 + "," + b3 + ")";
}
&#13;
body {
  background-color: ivory;
}
#canvas {
  border: 1px solid red;
  background-color=black;
}
&#13;
<canvas id="sample1" width=1200 height=800></canvas>
&#13;
&#13;
&#13;

<强>重叠

......显然,如果你将椭圆非常接近地绘制,它们最终会重叠。这是导致Q1线路变薄的原因。