我正在使用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>
答案 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)";
重构的示例代码使用不透明填充&amp;笔强>
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;
<强>重叠强>
......显然,如果你将椭圆非常接近地绘制,它们最终会重叠。这是导致Q1线路变薄的原因。