在HTML画布上绘制重叠内容时如何重置透明度? [英] How to reset transparency when drawing overlapping content on HTML canvas?

查看:76
本文介绍了在HTML画布上绘制重叠内容时如何重置透明度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在画布上用半透明的颜色绘制(例如 rgba(255,0,0,0.5))。当我再次在同一区域上绘制时,透明度值似乎正在累加,导致颜色不透明。有没有办法代替光源的透明度值(我用来绘制的半透明颜色)?

I'm drawing with a semi-transparent color (e.g. rgba(255,0,0,0.5)) over a canvas. When I draw over the same region again, the transparency value seems to be adding up resulting in an opaque color. Is there a way to keep the transparency value of the source (the semi-transparent color I'm using to draw) instead?

推荐答案

使用 alpha = 1 绘制到屏幕外的画布上,然后使用 ctx.globalAlpha 设置为您希望的任何值。这样,您可以画图直到太阳下山而无需在alpha中添加任何内容。如果需要,在绘制后也可以轻松更改Alpha。

Draw to an offscreen canvas with alpha = 1.Then just render the off screen canvas to the display canvas with the ctx.globalAlpha set at whatever value you wish. That way you can draw till the sun goes down without adding anything to the alpha. It is also easy to change the alpha after you have drawn if needed.

附加说明

如果图像中包含其他内容,则也必须将其保留在另一层上,因为此方法依赖于将屏幕画布重置为每次更新所需的开始状态。在这段代码中,这只是一个 clearRect 调用。

If you have other content included in the image, you will have to keep that on another layer as well because this method relies on the onscreen canvas being reset to a desired starting state for each update. In the snippet this is just a clearRect call. But can just as well be replaced with another existing layer, or a combination there of.

浏览器可以轻松处理许多屏幕外画布,我刚刚完成了一项工作, 60张全屏画布彼此叠放(请注意,您的GPU需要有RAM来保存图像,否则速度太慢),Chrome甚至没有闪烁。 Firefox和IE一样强大。

The browser can easily handle many off screen canvases, I just finished a job that had 60 full screen canvas stacked on top of each other (Note your GPU needs to have the RAM to hold the images or it's too slow) and Chrome did not even blink. Firefox and IE are just as capable.

更新

我添加了一个片段来演示我的意思。底部相关代码的注释中的详细信息。只是一个简单的绘图界面。

I have added a snippet to demonstrate what I mean. Details in the comments of the relevant code at the bottom. Just a simple drawing interface.

// get canvas set up mouse and do the other things
var canvas = document.getElementById("canV"); 
var ctx = canvas.getContext("2d");
var w = canvas.width;
var h = canvas.height;
var mouse = {
    x:0,
    y:0,
    buttonLastRaw:0, // user modified value 
    buttonRaw:0,
    over:false,
};
function mouseMove(event){
    mouse.x = event.offsetX;  mouse.y = event.offsetY; 
    if(mouse.x === undefined){ mouse.x = event.clientX;  mouse.y = event.clientY;}    
    if(event.type === "mousedown"){ mouse.buttonRaw = 1;
    }else if(event.type === "mouseup"){mouse.buttonRaw = 0;
    }else if(event.type === "mouseout"){ mouse.buttonRaw = 0; mouse.over = false;
    }else if(event.type === "mouseover"){ mouse.over = true; }
    event.preventDefault();
}

canvas.addEventListener('mousemove',mouseMove);
canvas.addEventListener('mousedown',mouseMove);
canvas.addEventListener('mouseup'  ,mouseMove); 
canvas.addEventListener('mouseout'  ,mouseMove); 
canvas.addEventListener('mouseover'  ,mouseMove); 
canvas.addEventListener("contextmenu", function(e){      canvas.preventDefault();}, false);

// create off screen layer that we will draw to
var layer1 = document.createElement("canvas");  
layer1.width = w;   // same size as the onscreen canvas
layer1.height = h; 
layer1.ctx = layer1.getContext("2d"); 
// set up drawing settings
layer1.ctx.lineCap = "round";
layer1.ctx.lineJoin = "round";
layer1.ctx.lineWidth = 16;
layer1.ctx.globalAlpha = 1;  // draw to this layer with alpha set to 1;

// set up onscreen canvas
ctx.globalAlpha = 1;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = "24px Arial black";
var instructions = true;

// colours to show that different layer are overwriting each other
var colours = "#F00,#FF0,#0F0,#0FF,#00F,#F0F".split(",");
var currentCol = 0;

// update on animation frame
function update(){
    ctx.clearRect(0,0,w,h);  // clear onscreen
    var c = layer1.ctx;      // short cut to the later1 context
    if(mouse.buttonRaw){    // if mouse down 
        if(mouse.lastx === undefined){   // is this start of drawing stroke
            mouse.lastx = mouse.x;   // set up drawing stroke
            mouse.lasty = mouse.y;
	        c.strokeStyle = colours[currentCol % colours.length];
            currentCol += 1;
            instructions = false;   // tuen of the instructions as they have worked it out
            ctx.globalAlpha = 0.6;  // should do this near layering but lasy
        }
        // draw the dragged stroke to the offscreen layer
        c.beginPath();
        c.moveTo(mouse.lastx,mouse.lasty);
        c.lineTo(mouse.x,mouse.y);
        c.stroke();
        mouse.lastx = mouse.x;
        mouse.lasty = mouse.y;        
    }else{  // if the mouse button up show drawing brush and instructions if
            // nothing has happened yet
        mouse.lastx = undefined;    // using this as a semaphore for drag start
        ctx.fillStyle = colours[currentCol%colours.length];
        ctx.globalAlpha = 0.6;    // the brush will compound the alpha 
                                   // this can be avoided by drawing it onto
                                   // the offscreen layer, but you will need 
                                   // another layer or some temp store to 
                                   // protect the offscreen layer. Again I am
                                   // to lazy to implement that right now.
        ctx.beginPath();
        ctx.arc(mouse.x,mouse.y,8,0,Math.PI*2);
        ctx.fill();
        if(instructions){         // show instructions if needed
          ctx.fillStyle = "blue";
          ctx.globalAlpha = 1;
          ctx.fillText("Click drag mouse to draw",250,60);
        }
    }
    
    // draw the offscreen layer onto the onscreen canvas at the alpha wanted
    ctx.drawImage(layer1,0,0);
    requestAnimationFrame(update);  // do it all again.
}
mouse.lastx;  // needed to draw lines.
mouse.lasty;
update()

body {    background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAlUlEQVRYR+2WsQ0EIQwEbXpAopbrAZESUhQ1AAkBXVEDAb6jBRP8B0s+yJpklnvvstYizRMRyjmTtVaD096buNYqzjnVB3NOaq3RGEPFhxBwAAzAAAzAAAz8gYFSijCzqmYH+ngyxqj4k3N+nkduep5Sops9wV+T5abnMUa62RM4AAZgAAZgAAZ+b8B7Lzc9PzW82RMvg0g+JLdy9xIAAAAASUVORK5CYII=');


    background-size: 32px 32px;
    background-repeat: repeat;
}
.canC { width:500px;  height:600px;}

<canvas class="canC" id="canV" width=500 height=600></canvas>

这篇关于在HTML画布上绘制重叠内容时如何重置透明度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆