当我使用每个圆圈的fill()逐个绘制相同颜色的圆圈时。当它们重叠时,常见的是颜色较暗(饱和)。 参见示例1(左)in JS Bin。
如果我创建长路径,然后对这个公共路径使用fill(),它有奇怪的工件(是的,当然它被复杂的路径弄糊涂,不知道我想要绘制的是什么) 参见示例2(右)in JS Bin。
如何实现具有相同颜色的圆形公共区域未饱和,它应该不会比具有相同颜色的其他圆圈更暗。 (正是我有in JS Bin右侧,但没有疯狂的文物)
如果具有不同颜色的圆圈具有公共区域,则颜色应该是饱和的。
答案 0 :(得分:1)
关于您的.getImageData
解决方案......
使用合成而不是.getImageData
来混合颜色会更快。
这是一个组合重叠的半透明圆圈而不会使重叠变暗的功能。
context.globalCompositeOperation='source-in'
会导致新图形替换现有像素。结果是一组没有变暗效果的重叠圆圈。
function uniformColorCircles(circles){
var PI2=Math.PI*2;
tempctx.globalCompositeOperation='source-over';
tempctx.clearRect(0,0,cw,ch);
tempctx.beginPath();
for(var i=0;i<circles.length;i++){
var c=circles[i];
tempctx.arc(c.x,c.y,c.radius,0,PI2);
}
tempctx.fillStyle='black';
tempctx.fill();
tempctx.globalCompositeOperation='source-in';
tempctx.fillStyle=circles[0].rgba;
tempctx.fill();
}
以下是示例代码和涉及多组半透明圆圈的演示:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
ctx.fillRect(0,0,120,220);
var tempCanvas=canvas.cloneNode();
var tempctx=tempCanvas.getContext('2d');
var c1={x:100,y:200,radius:50,rgba:'rgba(255,0,0,0.5)'};
var c2={x:100,y:240,radius:35,rgba:'rgba(255,0,0,0.5)'};
var c3={x:140,y:200,radius:50,rgba:'rgba(0,255,255,0.5)'};
var c4={x:140,y:240,radius:35,rgba:'rgba(0,255,255,0.5)'};
var c5={x:120,y:140,radius:50,rgba:'rgba(255,255,0,0.5)'};
uniformColorCircles([c1,c2]);
ctx.drawImage(tempCanvas,0,0);
uniformColorCircles([c3,c4]);
ctx.drawImage(tempCanvas,0,0);
uniformColorCircles([c5]);
ctx.drawImage(tempCanvas,0,0);
function uniformColorCircles(circles){
var PI2=Math.PI*2;
tempctx.globalCompositeOperation='source-over';
tempctx.clearRect(0,0,cw,ch);
tempctx.beginPath();
for(var i=0;i<circles.length;i++){
var c=circles[i];
tempctx.arc(c.x,c.y,c.radius,0,PI2);
}
tempctx.fillStyle='black';
tempctx.fill();
tempctx.globalCompositeOperation='source-in';
tempctx.fillStyle=circles[0].rgba;
tempctx.fill();
}
body{ background-color:white; }
#canvas{border:1px solid red; }
<canvas id="canvas" width=512 height=512></canvas>
答案 1 :(得分:0)
我使用辅助画布和画布图像数据处理解决了这个问题。
有数据数组,其中包含坐标和值,用于确定我们需要使用哪种颜色。
我在其自己的图层中绘制每个圆圈颜色,然后使用preventSaturation函数处理每个图层。然后将所有图层添加到原始画布中。
如果有人知道更好的方式让我知道。
如果有人不理解我需要做的事情,那就是: 1)我有this 2)我试图this
var canvas = document.getElementById('circles');
var ctx = canvas.getContext('2d');
var radius = 30;
var opacity = .7;
var data = [
{
x: 200,
y: 200,
v: 10
},
{
x: 230,
y: 230,
v: 20
},
{
x: 250,
y: 210,
v: 30
},
{
x: 270,
y: 190,
v: 40
},
{
x: 300,
y: 220,
v: 100
},
{
x: 300,
y: 260,
v: 200
},
{
x: 320,
y: 210,
v: 300
},
{
x: 300,
y: 160,
v: 200
},
{
x: 380,
y: 160,
v: 3000
},
{
x: 380,
y: 110,
v: 3000
},
{
x: 320,
y: 190,
v: 3000
}
];
var styles = {
blue: {
edgeValue: 0,
color: [0, 0, 255, 0.7]
},
green: {
edgeValue: 100,
color: [0, 255, 0, 0.7]
},
red: {
edgeValue: 1000,
color: [255, 0, 0, 0.7]
}
};
var layers = {};
for (var prop in styles) {
if(styles.hasOwnProperty(prop)) {
var c = document.createElement('canvas');
c.width = canvas.width;
c.height = canvas.height;
var cx = c.getContext('2d');
var cc = document.createElement('canvas');
cc.width = radius * 2;
cc.height = radius * 2;
var ccx = cc.getContext('2d');
var cColor = styles[prop].color;
ccx.fillStyle = 'rgba(' + cColor[0] + ',' + cColor[1] + ',' + cColor[2] + ',' + cColor[3] + ')';
ccx.beginPath();
ccx.arc(radius, radius, radius, 0, Math.PI * 2, true);
ccx.closePath();
ccx.fill();
layers[prop] = {
color: styles[prop].color,
edgeValue: styles[prop].edgeValue,
canvas: c,
ctx: cx,
canvasC: cc,
ctxC: ccx,
objects: []
};
}
}
data.forEach(function(o) {
var layer = o.v < styles.green.edgeValue ? layers.blue : o.v < styles.red.edgeValue ? layers.green : layers.red;
layer.ctx.drawImage(layer.canvasC, o.x, o.y);
layer.objects.push(o);
});
for(prop in layers) {
if(layers.hasOwnProperty(prop)) {
var image = layers[prop].ctx
.getImageData(0, 0, layers[prop].canvas.width, layers[prop].canvas.height);
preventColorSaturation(image.data, layers[prop].color);
layers[prop].ctx.putImageData(image, 0, 0);
ctx.drawImage(layers[prop].canvas, 0, 0);
}
}
function preventSaturation (d, s) {
var rgb255 = raRGBA255(s);
for (var i = 0; i < d.length; i += 4) {
d[i] = Math.min(d[i], rgb255[0]);
d[i + 1] = Math.min(d[i + 1], rgb255[1]);
d[i + 2] = Math.min(d[i + 2], rgb255[2]);
d[i + 3] = Math.min(d[i + 3], rgb255[3]);
}
}
function raRGBA255 (s) {
return [
s[0],
s[1],
s[2],
255 * s[3]
];
}
function raHexToRGB (s) {
var hexREGEXP = /^#([0-9A-Za-z]{3,6})$/;
var parsedHEX = s.match(hexREGEXP);
if (!parsedHEX) {
return [0, 0, 0];
}
return [
parseInt(parsedHEX[1].slice(0, 2), 16),
parseInt(parsedHEX[1].slice(2, 4), 16),
parseInt(parsedHEX[1].slice(4), 16)
];
}