【问题标题】:HTM5 Canvas, suggestions for changing animation effectHTM5 Canvas,改变动画效果的建议
【发布时间】:2016-08-17 23:18:11
【问题描述】:

所以我是画布的新手,并且仍在弄清楚事情是如何工作的。我正在尝试制作火山喷发的动画。我把火山和天空分成一层,第二层是喷发,第三层是火山灰云。我引用了一个喷发动画的例子,在它的编写方式中,它使画布变黑。是否有不同的方法可以实现它已经产生的相同效果,但是让图层的不透明度一直降低,这样你就可以看到火山喷发下的火山和天空?这是我的代码:

<!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";

【问题讨论】:

    标签: javascript html animation canvas


    【解决方案1】:

    看起来先前绘制的粒子通过使用低 Alpha 填充覆盖整个画布而“变暗”。但是,这也不利地导致下面的火山“变暗”。

    您可以通过使用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

    【讨论】:

    • 好的,我肯定明白你在说什么。我想我的下一个问题是如何改变每个粒子的 alpha 但仍保留它们的颜色?我一直在尝试的方法是让粒子变成纯黑色......
    • @intoitoverit。我添加了一个演示,展示了如何逐步降低粒子的 alpha。祝你的项目好运!
    • ctx.globalAlpha 非常快,我每次调用渲染时都使用它,它对渲染性能没有影响,当然比调用字符串替换要快得多,如果你正在使用渐变、图案或图像,这是进行任何褪色的唯一实用方法。
    猜你喜欢
    • 2013-02-08
    • 2015-03-17
    • 1970-01-01
    • 2011-09-01
    • 1970-01-01
    • 2017-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多