2016-04-24 9 views
0

私はキャンバスを新しくしており、どのように動作するかをまだ把握しています。私は火山噴火のアニメーションを作ろうとしています。私は火山と空を1つの層に分け、2番目の層の噴火と3番目の層に灰の雲を分けました。私は噴火アニメーションの例を参照していましたが、書かれている方法ではキャンバスを黒くしています。すでに行っているのと同じ効果を達成する別の方法はありますか?レイヤーの不透明度がすべて下がっているので、噴火の下にある火山と空を見ることができますか?ここに私のコードだ:アニメーションが起こる場所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)を塗りつぶして繰り返し「ディミングする」のではなく、新しいフレームごとに個々のパーティクルのアルファを減らすことができます。

これは、各粒子の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>

は、パフォーマンスを向上させるために、あなたはバッチで同じアルファ値を持つすべての粒子を描くことができます。この方法では、各パーティクルのrgbaを変更するのではなく、context.globalAlphaを使用してパーティクルのバッチを描画します。

+0

さて、あなたが言っていることは間違いありません。私の次の質問は、各パーティクルのアルファ値をどのように変更するのですか?私が試みてきたやり方は、粒子が黒く黒くなってきたことです... – intoitoverit

+1

@intoitoverit。パーティクルのアルファを徐々に減らす方法を示すデモを追加しました。あなたのプロジェクトに幸運を祈る! – markE

+0

ctx.globalAlphaは非常に速く、レンダリングするたびに常に使用します。レンダリングのパフォーマンスには何の影響もなく、文字列置換を呼び出すよりもはるかに高速です。また、グラデーション、パターンまたはイメージを使用している場合はフェージングを行う唯一の実用的な方法です。 – Blindman67

関連する問題