我正在尝试使用globalAlpha'淡出'我的画布的顶层,陶醉中间层图像和纯色背景。我正在使用下面的代码,它成功淡出了黑色层。但是,我似乎无法阻止蓝色背景层也逐渐淡出。
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="600" height="500"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var img;
img = new Image();
img.src = "img/background4x3.png";
var i = 1;
function test1() {
ctx.fillStyle = "#4DB8FF";
ctx.fillRect(0, 0, 600, 500);
ctx.globalAlpha = 1;
ctx.drawImage(img, 0, 0, 600, 500);
if (i > 0) {
ctx.globalAlpha = i;
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, 600, 500);
setTimeout(test2, 100);
}
}
function test2() {
ctx.clearRect(0, 0, 600, 500);
i -= 0.01;
test1();
}
img.onload = function () {
test1();
}
</script>
有没有人有任何建议?我试图使用基于globalAlpha的if和while语句,但到目前为止还没有运气。
答案 0 :(得分:1)
希望我做对了。图像从黑色渐变而背景蓝/青色不受影响。
您需要使用ctx.globalCompositeOperation
(GCO),这有点直观。
source-over
这是默认设置并绘制所有像素
从源(你正在绘制的东西)上的所有像素
当然,目的地(画布)除了透明像素。globalAlpha
设置为淡入淡出级别。globalAlpha
设置为1 destination-atop
,这意味着来自源的所有像素
(图像)不是不透明的,目标像素出现在上面
最佳。因此,图像中只有不透明/半透明像素将具有顶部绘制的最后一个绘制的黑色像素destination-over
,这意味着所有像素来自
画布上的最后一次绘制(黑色渐变的图像)
出现在将要绘制的青色矩形上方。所有其他像素将
获取源像素(青色背景)全部完成。
当fadeIn === 0
GCO destination-atop
失败时,因为所有像素在黑色背景中都是透明的。因此,请确保通过代码中演示的第二种方法绘制图像。
jsFiddle的一个工作示例
奇怪的是,如果作为Stack Overflow Snippet
插入,下面的代码不起作用代码。
// set up canvas and context
var canvas = document.getElementById("canV");
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height); // why? Just habbit;
// create image
var img;
img = new Image();
var fadeIn = 1;
function update() {
if(fadeIn <= 0){ // when fade done draw normally
ctx.globalAlpha = 1; // set alpha
ctx.globalCompositeOperation = "source-over"; // default blend mode
ctx.fillStyle = "#4DB8FF"; // background
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// do it all again in 4 secs.
setTimeout(function(){
fadeIn = 1;
window.requestAnimationFrame(update);
}, 4000); // do it again in four seconds
}else{
// first draw the black fading out
ctx.globalCompositeOperation = "source-over";
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.globalAlpha = fadeIn;
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// now draw the image with destination-atop
// this means that for each visible pixel (alpha > 0)
// draw the destination pixels (what is already on the canvas)
// over the top
ctx.globalCompositeOperation = "destination-atop";
ctx.globalAlpha = 1;
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
// and last draw the background with destination over.
// which means only draw pixels where the destination
// pixels are transparent.
ctx.globalCompositeOperation = "destination-over";
ctx.fillStyle = "#4DB8FF";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// decrease fade
fadeIn -= 0.02;
// call next frame
window.requestAnimationFrame(update)
}
}
// start it all happening.
img.onload = function () {
window.requestAnimationFrame(update)
}
// load the image.
img.src = "http://i.stack.imgur.com/ysINC.png";
希望这有帮助。
答案 1 :(得分:0)
您可以使用画布来创建图层。
我们的想法是每个图层都是一个离屏画布,您将在主要的屏幕画布上以正确的顺序绘制。
使用您的代码,它会提供类似的内容:
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var img;
img = new Image();
img.src = "http://i.stack.imgur.com/ysINC.png";
// an array containing our canvases' contexts
var layers = [];
for( var i=0; i<3; i++){
// we can only save the contexts
// since we've got a reference to their canvas in it
layers.push(canvas.cloneNode(true).getContext('2d'));
}
// the alpha values for layer2 and layer1
var i = 1;
var k = 1;
function test1() {
// layer0 is our background
layers[0].fillStyle = "#4DB8FF";
layers[0].fillRect(0, 0, 600, 500);
// the middle image
layers[1].globalAlpha = k;
layers[1].drawImage(img, 0, 0, 600, 500);
if (i > 0) {
// the top black layer
layers[2].globalAlpha = i;
layers[2].fillStyle = "#000000";
layers[2].fillRect(0, 0, 600, 500);
setTimeout(test2, 100);
}
else{
test3();
}
// draw each of our layers's canvas on the main one
for(var j=0; j<layers.length; j++){
ctx.drawImage(layers[j].canvas, 0,0);
layers[j].clearRect(0,0, canvas.width, canvas.height);
}
}
function test2() {
ctx.clearRect(0, 0, 600, 500);
i -= 0.01;
test1();
}
function test3() {
if(k>0){
k -= 0.1;
setTimeout(test2, 100);
}
}
img.onload = function () {
test1();
}
<canvas id="myCanvas" width="600" height="500"></canvas>
如果@ Blindman67正确地得到你想要的东西,你仍然可以使用这种层次的想法,只设置你的一个上下文的gCO:
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var img;
img = new Image();
img.src = "http://i.stack.imgur.com/ysINC.png";
// an array containing our canvases' contexts
var layers = [];
for( var i=0; i<3; i++){
// we can only save the contexts
// since we've got a reference to their canvas in it
layers.push(canvas.cloneNode(true).getContext('2d'));
}
// the alpha values for layer2 and layer1
var i = 1;
function test1() {
// layer0 is our background
layers[0].fillStyle = "#4DB8FF";
layers[0].fillRect(0, 0, 600, 500);
// the middle image
layers[1].drawImage(img, 0, 0, 600, 500);
if (i > 0) {
// the top black layer
layers[2].globalAlpha = i;
layers[2].fillStyle = "#000000";
layers[2].fillRect(0, 0, 600, 500);
setTimeout(test2, 100);
}
// change our image layer's gCO
layers[1].globalCompositeOperation="source-atop";
// draw the black layer on it
layers[1].drawImage(layers[2].canvas, 0,0);
// reset image layer's gCO
layers[1].globalCompositeOperation="source-over";
// draw each of our layers's canvas on the main one
for(var j=0; j<layers.length; j++){
// don't draw the black layer since it's already on the image's one
if(j!==2)
ctx.drawImage(layers[j].canvas, 0,0);
layers[j].clearRect(0,0, canvas.width, canvas.height);
}
}
function test2() {
ctx.clearRect(0, 0, 600, 500);
i -= 0.01;
test1();
}
img.onload = function () {
test1();
}
<canvas id="myCanvas" width="600" height="500"></canvas>