2016-04-24 11 views
0

私はHTML5キャンバスを初めて使いました。レイヤを使用しようとしています。私はそれらを実装する方法を探しましたが、私がしようとしていることに役立つものは何も持っていません。私は火山噴火のアニメーションを作ろうとしています。私は、火山と背景の空色を1つの層に、空から降りる溶岩を第2の層に、灰色の雲を第3の層に配置したいと考えています。レイヤーを見つけたときに私はすでにこれに取り組んでいました。だから私は物事が不調であることを知っています。私の質問は、層を実装することについては正しい道のりですか?レイヤーを使用するHTML5 Canvasの初心者ですか?

<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> 
</body> 

<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"); 
    layer3 = document.getElementById("layer3"); 
    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"; 
    ctx1t.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() { 
    animationHandler(); 
    timer = setInterval(moveParticles, 60); 
    //timerRestart = setInterval(makeParticles, 4000); 
} 

編集:だから私の問題の前に、私はレイヤーを使用しようとし始めた理由溶岩のアニメーションがキャンバスブラックアウトになるためでした。だから私はすべてを別のレイヤーに分けるとキャンバスを黒くすることはないと思った。答えにSergioのコードを実装しましたが、これは私が達成しようとしているものに近いですが、私は以前から問題を取り上げています。私は噴火アニメーションのコードを参照していましたが、それはアニメーション自体がどのように機能するかです。私はおそらくこれを別の質問に入れるべきだと思いますが、溶岩を今でも同じ効果がある場所に作用させるための別の方法はありますが、キャンバスの不透明度が低下している場所下の層? これは、アニメーションが行われる場所です。

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"; 
+0

これはデバッグするのに大変です!特に動作していないものはありますか? – Noah

+0

あなたは本当に質問をしていません...あなたのコードがどのように動作し、どのように動作させるかを説明してください。 – markE

答えて

1

あなたは正しいパスにいます。しかし、いくつかの問題があります。最初にwindows.loadの を呼び出すと、init()を呼び出すことなく、animationHandlerを呼び出すことから始めます。その結果、多くのエラーが発生します。 canvasという変数には多くの参照がありますが、これは定義されていません。あなたがそれをコメントアウトしました。 1つまたは2つの型付きエラー(drawVolcano()に型付きエラーがあります)があり、コードの実行を妨げます。

いくつかのバグを修正し、windows.loadにinitを追加すると、動作するアニメーションが表示されます。これを試してみてください。 もしそうなら、あなたはそれを正しく行いました。ちょっとした小さなバグがありました。

<body> 
<div id="canvasesdiv" style="position:relative; width:800px; height:500px"> 
<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> 
</body> 

ただし、粒子は上から下に移動しました。あなたが火山効果を望むならば。それは円弧状に動かなければならない。火山から撮影して落下した。しかし、正しい軌道に乗っているので、ちょっとだけコードを変更する必要があります。

Iコードがクリーンアップされていない

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html> 
<head> 
<title>Untitled Document</title> 
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> 
</head> 

<body> 
<div id="canvasesdiv" style="position:relative; width:800px; height:500px"> 
<canvas id="layer1" style="z-index: 1; position:absolute; left:0px; top:0px;" width="800" height="500"></canvas> 
<canvas id="layer1f" 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="layer2f" 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"); 
    layer1f = document.getElementById("layer1f"); 
    f1 = layer1f.getContext("2d"); 
    layer2 = document.getElementById("layer2"); 
    ctx2 = layer2.getContext("2d"); 
    layer2f = document.getElementById("layer2f"); 
    f2 = layer2f.getContext("2d"); 
    canvas=layer3 = document.getElementById("layer3"); 
    context=ctx3 = layer3.getContext("2d"); 

} 

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


var cloud = new Image(); 
cloud.src='http://www.dominicanvoice.com/test/volcano/cloud.png'; 

var fireball = new Image(); 
fireball.src='http://www.dominicanvoice.com/test/volcano/fireball.png'; 

function drawVolcano(){ 

    img = new Image(); 
    img.src='http://www.dominicanvoice.com/test/volcano/layer2.png'; 
    img.onload = function() { ctx1.drawImage(this,0,0);}; 

    img2 = new Image(); 
    img2.src="http://www.dominicanvoice.com/test/volcano/front.png"; 
    img2.onload = function() { ctx2.drawImage(this,0,0);}; 
} 

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 = 160; 
    this.vx = Math.random()*16-8; 
    this.vy = Math.random()*25; 
    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 
    f1.clearRect(0, 0, canvas.width, canvas.height); 
    f2.clearRect(0, 0, canvas.width, canvas.height); 
    for(var i = 0; i < particles.length; i++) 
    { 
     var p = particles[i]; 
     f=(p.vy>0) ?f1:f2; 
     if (p.vy>0) f.drawImage(cloud,Math.floor((25-p.vy)/2)*128,0,128,128,p.x-64,p.y,128,128) 
     else ctx3.drawImage(cloud,1536,0,128,128,p.x-Math.random()*5-64,-20+Math.random()*10,128,128); 

     if (p.y<500) { 

     f.drawImage(fireball,Math.floor(-p.vy/2)*128,0,128,64,p.x-64,p.y,128,64); 

    //  f.beginPath(); 
    // f.arc(p.x, p.y, p.radius, 0, degreesToRadians(360), true); 
    // f.fillStyle = p.color; 
    // f.fill(); 
     p.x += p.vx; 
     p.y -= p.vy; 
     p.vy-=1; 
     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; 
     }; 
    } 

} 


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

http://www.dominicanvoice.com/test/volcano.php)。火の玉のアーク型の運動を追加し、そしていくつかのスプライトを使用するように、数分前に、もう少しコードを修正または最適化されていますが、それを修正して再生することができます。 ここでは動作しています。http://www.dominicanvoice.com/test/volcano.php 注:このコードはMacでテストしませんでした。窓でしかうまく動作しませんでした。

+0

'setInterval'はアニメーションに危険な方法です。望ましくないタイミングを作り、呼び出しスタックオーバーフローでページ全体をクラッシュさえします。奇妙なタイミングが本当に必要な場合は、 'requestAnimationFrame'(ディスプレイハードウェアとの同期を保つことが望ましい)または' setTimeout'を使用する必要があります。 – Blindman67

+0

あなたはいつもコードを改良することができますが、彼のコードは正常に動作します。 –

+0

ええ、私はそれにも弧を実装しようと考えていた。しかし、それは私が探していたものです!今私は画面が黒くならずにアニメーションを起こさせて火山自体と空を見ることができないようにする方法を見つけようとしています。私は噴火で欲しかった効果を得るためのコードを参照していましたが、実行される方法によって画面が黒くなると思います。 – intoitoverit