2016-04-24 90 views
0

建議,所以我新的畫布,我仍然搞清楚是如何工作的。我正在嘗試製作火山爆發的動畫。我把火山和天空分成了一層,第二層是噴發,第三層是灰雲。我正在引用一個爆發動畫的例子,並且按照它的寫法,它會畫出畫布。是否有不同的方式實現它已經產生的相同效果,但是爲了讓圖層的不透明度完全消失,您可以看到火山噴發下的火山和天空?這裏是我的代碼:HTM5帆布,改變動畫效果

<!doctype html> 
<html lang='en'> 
<head> 
<style> 
body { 
font-family: Verdana, Helvetica, sans-serif; 
} 
canvas { 
border: 1px solid black;; 
} 
</style> 
</head> 


<body> 
<div id="canvasesdiv" style="position:relative; width:400px; height:300px"> 
<canvas id="layer1" style="z-index: 1; position:absolute; left:0px; top:0px;" width="800" height="500"></canvas> 
<canvas id="layer2" style="z-index: 2; position:absolute; left:0px; top:0px;" width="800" height="500"></canvas> 
<canvas id="layer3" style="z-index: 3; position:absolute; left:0px; top:0px;" width="800" height="500"></canvas> 
</div> 
<script> 

//var canvas = document.getElementById("myCanvas"); 
//var context = canvas.getContext("2d"); 
var layer1; 
var layer2; 
var layer3; 
var particles; 
var eruption; 
var timer; 
var timerRestart; 

function init(){ 
layer1 = document.getElementById("layer1"); 
ctx1 = layer1.getContext("2d"); 
layer2 = document.getElementById("layer2"); 
ctx2 = layer2.getContext("2d"); 
canvas=layer3 = document.getElementById("layer3"); 
context=ctx3 = layer3.getContext("2d"); 

} 

function animationHandler(){ 
fillBackgroundColor(canvas, context); 
drawVolcano(); 
drawClouds(); 
eruption = setTimeout(makeParticles, 10); 
} 

function drawClouds(){ 

ctx3.beginPath(); 
ctx3.moveTo(0, 100); 
ctx3.bezierCurveTo(0, 100, 75, 200, 150, 100); 
ctx3.bezierCurveTo(150, 100, 225, 200, 300, 85); 
ctx3.bezierCurveTo(300, 85, 375, 200, 450, 75); 
ctx3.bezierCurveTo(450, 75, 525, 200, 600, 100); 
ctx3.bezierCurveTo(600, 100, 700, 200, 800, 100); 
ctx3.lineTo(800, 0); 
ctx3.lineTo(0, 0); 
ctx3.closePath(); 

ctx3.fillStyle = "#6f2a2a"; 
ctx3.fill(); 

ctx3.lineWidth = 5; 
ctx3.strokeStyle = "#371515"; 
ctx3.stroke(); 

} 

function drawVolcano(){ 

ctx1.beginPath(); 
ctx1.moveTo(0, 400); 
ctx1.bezierCurveTo(0, 400, 250, 400, 325, 200); 
ctx1.lineTo(425, 200); 
ctx1.bezierCurveTo(425, 200, 450, 400, 800, 400); 
ctx1.lineTo(800, 500); 
ctx1.lineTo(0, 500); 
ctx1.closePath(); 

ctx1.fillStyle = "#802b00"; 
ctx1.fill(); 

ctx1.lineWidth = 5; 
ctx1.strokeStyle = "#b33c00"; 
ctx1.stroke(); 
} 

function fillBackgroundColor(canvas, context){ 
ctx1.fillStyle = "#3399ff" ; 
ctx1.fillRect(0, 0, canvas.width, canvas.height); 
} 

function makeParticles() { 
//create an array of particles for our animation 
particles = []; 
for(var i = 0; i < 100; i++) 
{ 
    particles.push(new Particle()); 
} 

} 

function degreesToRadians(degrees) { 
//converts from degrees to radians and returns 
return (degrees * Math.PI)/180; 
} 

function Particle(){ 
//the constructor for a single particle, with random starting x+y, velocity, color, and radius 
//this.x = Math.random()*canvas.width; 
//this.y = Math.random()*canvas.height; 
this.x = canvas.width/2; 
this.y = (0,0); 
this.vx = Math.random()*16-8; 
this.vy = Math.random()*10; 
var colors = ["red", "#ff6600", "yellow", "#262626"]; 
this.color = colors[Math.floor(Math.random()*colors.length)]; 
this.radius = 50; 
} 

function moveParticles() { 
//partially clear the screen to fade previous circles, and draw a new particle at each new coordinate 
ctx2.globalCompositeOperation = "source-over"; 
ctx2.fillStyle = "rgba(0, 0, 0, 0.3)"; 
ctx2.fillRect(0, 0, canvas.width, canvas.height); 
ctx2.globalCompositeOperation = "lighter"; 
for(var i = 0; i < particles.length; i++) 
{ 
    var p = particles[i]; 
    ctx2.beginPath(); 
    ctx2.arc(p.x, p.y, p.radius, 0, degreesToRadians(360), true); 
    ctx2.fillStyle = p.color; 
    ctx2.fill(); 
    p.x += p.vx; 
    p.y += p.vy; 
    if(p.x < -50) p.x = canvas.width+50; 
    if(p.y < -50) p.y = canvas.height+50; 
    if(p.x > canvas.width+50) p.x = -50; 
    if(p.y > canvas.height+50) p.y = -50; 
    p.radius -= 1; 
} 

} 


function clearScreen(color) { 
//clears the screen and fills with the color of choice 
ctx2.clearRect(0, 0, canvas.width, canvas.height); 
ctx2.fillStyle = color; 
ctx2.fillRect(0, 0, canvas.width, canvas.height); 

} 

window.onload = function() { 
init(); 
animationHandler(); 
timer = setInterval(moveParticles, 60); 
//timerRestart = setInterval(makeParticles, 4000); 
} 

</script> 
</html> 

這就是動畫時:

function moveParticles() { 
//partially clear the screen to fade previous circles, and draw a new particle at each new coordinate 
ctx2.globalCompositeOperation = "source-over"; 
ctx2.fillStyle = "rgba(0, 0, 0, 0.3)"; 
ctx2.fillRect(0, 0, canvas.width, canvas.height); 
ctx2.globalCompositeOperation = "lighter"; 

回答

1

它看起來像以前繪製的顆粒通過用低阿爾法填充覆蓋整個畫布「變暗」。但是,這也不利地導致下伏火山「變暗」。

而不是一再「調光」通過與rgba(0,0,0,0.3)填充整個畫布,你可以減少每個單個顆粒的alpha隨着每一個新的幀。

這可以在粒子水平,通過改變每個粒子的rgba填充來實現。

例子:

var canvas=document.getElementById("canvas"); 
 
var ctx=canvas.getContext("2d"); 
 
var cw=canvas.width; 
 
var ch=canvas.height; 
 

 
var particle={ 
 
    // start with red base color 
 
    // use a token (here @) which will be replaced with alpha 
 
    baseColor:'rgba(255,0,0,@)', 
 
    // start with the particle at full alpha 
 
    // this alpha will be incrementally reduced 
 
    currentAlpha:1.00, 
 
}; 
 

 
requestAnimationFrame(animate); 
 

 
function animate(time){ 
 
    ctx.clearRect(0,0,cw,ch); 
 
    ctx.beginPath(); 
 
    ctx.arc(150,50,20,0,Math.PI*2); 
 
    // change this particle's alpha  
 
    var fill=particle.baseColor.replace('@',particle.currentAlpha); 
 
    particle.currentAlpha-=.01; 
 
    if(particle.currentAlpha<=0){particle.currentAlpha=0;} 
 
    ctx.fillStyle=fill; 
 
    ctx.fill(); 
 
    requestAnimationFrame(animate); 
 
}
body{ background-color: ivory; } 
 
#canvas{border:1px solid red;}
<h4>A particle with reducing rgba alpha</h4> 
 
<canvas id="canvas" width=300 height=300></canvas>

爲了更好的性能,你可以繪製所有的粒子在一個批次相同alpha值。此方法將使用context.globalAlpha繪製一批粒子,而不是更改每個粒子的rgba

+0

好吧,我確實看到你在說什麼。我想我的下一個問題是我將如何更改每個粒子的alpha,但仍保留其顏色?我一直在嘗試的方式已經使粒子變成純黑色... – intoitoverit

+1

@intoitoverit。我已經添加了一個演示,演示如何逐步減少粒子的alpha。祝你的項目好運! – markE

+0

ctx.globalAlpha是非常快的,我用它來與每次調用渲染所有的時間,和它沒有任何效果渲染的性能和肯定比調用字符串替換更快,如果你正在使用漸變,圖案或圖像是唯一可行的方法來做任何褪色。 – Blindman67