27

EDIT:

For anybody who is curious, here is the finished result.

http://jsfiddle.net/Javalsu/vxP5q/743/embedded/result/


I'm building off of the code I found in this link

http://thecodeplayer.com/walkthrough/html5-canvas-snow-effect

I want to make this more of a confetti falling effect than a snow effect, and I would need to make each element a different color. But it seems that the fill color is set for entire canvas at once.

Is there a way to specify a different fill color for each element or am I going about this the entirely wrong way?

Thanks

Update: Here is the finished product if anybody has a need for confetti

http://jsfiddle.net/mj3SM/6/

window.onload = function () {
//canvas init
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

//canvas dimensions
var W = window.innerWidth;
var H = window.innerHeight;
canvas.width = W;
canvas.height = H;

//snowflake particles
var mp = 200; //max particles
var particles = [];
for (var i = 0; i < mp; i++) {
    particles.push({
        x: Math.random() * W, //x-coordinate
        y: Math.random() * H, //y-coordinate
        r: Math.random() * 15 + 1, //radius
        d: Math.random() * mp, //density
        color: "rgba(" + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", 0.8)",
        tilt: Math.floor(Math.random() * 5) - 5
    });
}

//Lets draw the flakes
function draw() {
    ctx.clearRect(0, 0, W, H);



    for (var i = 0; i < mp; i++) {
        var p = particles[i];
        ctx.beginPath();
        ctx.lineWidth = p.r;
        ctx.strokeStyle = p.color; // Green path
        ctx.moveTo(p.x, p.y);
        ctx.lineTo(p.x + p.tilt + p.r / 2, p.y + p.tilt);
        ctx.stroke(); // Draw it
    }

    update();
}

//Function to move the snowflakes
//angle will be an ongoing incremental flag. Sin and Cos functions will be applied to it to create vertical and horizontal movements of the flakes
var angle = 0;

function update() {
    angle += 0.01;
    for (var i = 0; i < mp; i++) {
        var p = particles[i];
        //Updating X and Y coordinates
        //We will add 1 to the cos function to prevent negative values which will lead flakes to move upwards
        //Every particle has its own density which can be used to make the downward movement different for each flake
        //Lets make it more random by adding in the radius
        p.y += Math.cos(angle + p.d) + 1 + p.r / 2;
        p.x += Math.sin(angle) * 2;

        //Sending flakes back from the top when it exits
        //Lets make it a bit more organic and let flakes enter from the left and right also.
        if (p.x > W + 5 || p.x < -5 || p.y > H) {
            if (i % 3 > 0) //66.67% of the flakes
            {
                particles[i] = {
                    x: Math.random() * W,
                    y: -10,
                    r: p.r,
                    d: p.d,
                    color: p.color,
                    tilt: p.tilt
                };
            } else {
                //If the flake is exitting from the right
                if (Math.sin(angle) > 0) {
                    //Enter from the left
                    particles[i] = {
                        x: -5,
                        y: Math.random() * H,
                        r: p.r,
                        d: p.d,
                        color: p.color,
                        tilt: p.tilt
                    };
                } else {
                    //Enter from the right
                    particles[i] = {
                        x: W + 5,
                        y: Math.random() * H,
                        r: p.r,
                        d: p.d,
                        color: p.color,
                        tilt: p.tilt
                    };
                }
            }
        }
    }
}

//animation loop
setInterval(draw, 20);

}

4

4 回答 4

6

试试这样:http: //jsfiddle.net/vxP5q/

JS:

window.onload = function(){
//canvas init
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

//canvas dimensions
var W = window.innerWidth;
var H = window.innerHeight;
canvas.width = W;
canvas.height = H;

//snowflake particles
var mp = 25; //max particles
var particles = [];
for(var i = 0; i < mp; i++)
{
    particles.push({
        x: Math.random()*W, //x-coordinate
        y: Math.random()*H, //y-coordinate
        r: Math.random()*4+1, //radius
        d: Math.random()*mp, //density
        color: "rgba(" + Math.floor((Math.random() * 255)) +", " + Math.floor((Math.random() * 255)) +", " + Math.floor((Math.random() * 255)) + ", 0.8)"
    })
}

//Lets draw the flakes
function draw()
{
    ctx.clearRect(0, 0, W, H);



    for(var i = 0; i < mp; i++)
    { 
        var p = particles[i];
        ctx.beginPath();
        ctx.fillStyle = p.color;
        ctx.moveTo(p.x, p.y);
        ctx.arc(p.x, p.y, p.r, 0, Math.PI*2, true);
        ctx.fill();
    }

    update();
}

//Function to move the snowflakes
//angle will be an ongoing incremental flag. Sin and Cos functions will be applied to it to create vertical and horizontal movements of the flakes
var angle = 0;
function update()
{
    angle += 0.01;
    for(var i = 0; i < mp; i++)
    {
        var p = particles[i];
        //Updating X and Y coordinates
        //We will add 1 to the cos function to prevent negative values which will lead flakes to move upwards
        //Every particle has its own density which can be used to make the downward movement different for each flake
        //Lets make it more random by adding in the radius
        p.y += Math.cos(angle+p.d) + 1 + p.r/2;
        p.x += Math.sin(angle) * 2;

        //Sending flakes back from the top when it exits
        //Lets make it a bit more organic and let flakes enter from the left and right also.
        if(p.x > W+5 || p.x < -5 || p.y > H)
        {
            if(i%3 > 0) //66.67% of the flakes
            {
                particles[i] = {x: Math.random()*W, y: -10, r: p.r, d: p.d, color : p.color};
            }
            else
            {
                //If the flake is exitting from the right
                if(Math.sin(angle) > 0)
                {
                    //Enter from the left
                    particles[i] = {x: -5, y: Math.random()*H, r: p.r, d: p.d, color: p.color};
                }
                else
                {
                    //Enter from the right
                    particles[i] = {x: W+5, y: Math.random()*H, r: p.r, d: p.d, color : p.color};
                }
            }
        }
    }
}

//animation loop
setInterval(draw, 33);
}

我做了什么。在生成像素的地方,我添加了一种独特的(随机)颜色。更新在哪里,我确保颜色已更改,并且我已更改它的绘制位置,以便它将为每个五彩纸屑项目创建一个独特的路径。

于 2013-05-01T17:17:14.853 回答
3

好问题。考虑示例的绘图循环:

ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
ctx.beginPath();
for(var i = 0; i < mp; i++)
{
  var p = particles[i];
  ctx.moveTo(p.x, p.y);
  ctx.arc(p.x, p.y, p.r, 0, Math.PI*2, true);
}
ctx.fill();

它正在制作一条路径,添加许多弧,然后填充一次

要更改它,您需要为每个粒子填充一次。您还需要为每个粒子赋予独特的颜色:

for (var i = 0; i < mp; i++) {
    var p = particles[i];
    ctx.fillStyle = p.color;
    ctx.beginPath();        
    ctx.moveTo(p.x, p.y);
    ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2, true);
    ctx.fill();
}

请注意如何beginPath()fill()现在循环内。这很重要,因为每条弧线都需要自己的路径和填充。这比用一条路径制作它们要慢得多,但如果你想要不同颜色的粒子,这是必要的。

p.color

particles.push({
    x: Math.random() * W, //x-coordinate
    y: Math.random() * H, //y-coordinate
    r: Math.random() * 4 + 1, //radius
    d: Math.random() * mp, //density

    // I'm new!
    color: "rgba(" + Math.floor(Math.random()*255) +
            ", " + Math.floor(Math.random()*255) + ", 255, 0.8)"
})

这是一个工作示例:

http://jsfiddle.net/j4NZK/1/

于 2013-05-01T17:17:57.150 回答
1

这是基于 Niels 的帖子的版本,我想要一个可重用的对象,我可以调用它并添加到任何页面。

用法:

confetti.Init(#IdofContainer(div)#, 50,25,100)

代码:

var confetti = {
angle: 0,
ctx: 0,
H: 0,
W: 0,
mp: 0,
particles: [],
endFunction: '',
Init: function (parent, maxParticles, iCount, speed, endFunct) {
    confetti.stopped = false;
    confetti.runner = null;
    confetti.endFunction = endFunct;
    var canvas = document.getElementById("confettiCanvasId");
    if (canvas) {
        canvas.parentNode.removeChild(canvas);
    }
    canvas = document.createElement('canvas');
    canvas.className = 'confettiCanvas';
    canvas.id = 'confettiCanvasId'
    $id(parent).appendChild(canvas);
    var ctx = canvas.getContext("2d");
    var W = $id(parent).clientHeight;
    var H = $id(parent).clientWidth;
    canvas.width = W;
    canvas.height = H;
    confetti.particles = [];
    for (var i = 0; i < maxParticles; i++) {
        confetti.particles.push({
            x: Math.random() * W,
            y: Math.random() * H,
            r: Math.random() * 4 + 1, //radius
            d: Math.random() * maxParticles, //density
            color: "rgba(" + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", " + Math.floor((Math.random() * 255)) + ", 0.8)"
        });
    }
    myCounter = new confetti.Counter({
        seconds: iCount,
        speed: speed,
        onUpdateStatus: function (sec) {
            $l(Math.random() * 255)
            ctx.clearRect(0, 0, W, H);
            for (var i = 0; i < maxParticles; i++) {
                var p = confetti.particles[i];
                ctx.beginPath();
                ctx.fillStyle = p.color;
                ctx.moveTo(p.x, p.y);
                ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2, true);
                ctx.fill();
            }

            confetti.angle += 0.01;
            for (var i = 0; i < maxParticles; i++) {
                var p = confetti.particles[i];
                p.y += Math.cos(confetti.angle + p.d) + 1 + p.r / 2;
                p.x += Math.sin(confetti.angle) * 2;
                if (p.x > W + 5 || p.x < -5 || p.y > H) {
                    if (i % 3 > 0) //66.67% of the flakes
                    {
                        confetti.particles[i] = {x: Math.random() * W, y: -10, r: p.r, d: p.d, color: p.color};
                    }
                    else {
                        if (Math.sin(confetti.angle) > 0) {
                            confetti.particles[i] = {x: -5, y: Math.random() * H, r: p.r, d: p.d, color: p.color};
                        }
                        else {
                            confetti.particles[i] = {x: W + 5, y: Math.random() * H, r: p.r, d: p.d, color: p.color};
                        }
                    }
                }
            }
        },
        onCounterEnd: function () {
            stopTimer();
            myCounter.stop();
            confetti.Stop();
        }});
    myCounter.start();
},
FadeOut:function fadeOut() {
    var alpha = 1.0;   // full opacity
    for (var i = 0; i < confetti.particles.length; i++) {
        var p = confetti.particles[i];
        interval = setInterval(function () {
            //confetti.canvas.width = confetti.canvas.width; // Clears the canvas
            p.color = "rgba(255, 0, 0, " + alpha + ")";
            alpha = alpha - 0.05; // decrease opacity (fade out)
            if (alpha < 0) {
                //confetti.canvas.width = confetti.canvas.width;
                clearInterval(interval);
            }
        }, 50);


    }
        },
Counter: function Countdown(options) {
    var timer,
        instance = this,
        seconds = options.seconds || 10,
        updateStatus = options.onUpdateStatus || function () {
        },
        counterEnd = options.onCounterEnd || function () {
        };

    function decrementCounter() {
        updateStatus(seconds);
        if (seconds === 0) {
            counterEnd();
            instance.stop();
        }
        seconds--;
    }

    this.start = function () {
        clearInterval(timer);
        timer = 0;
        seconds = options.seconds;
        timer = setInterval(decrementCounter, options.speed);
    };

    this.stop = function () {
        clearInterval(timer);
    };
},
Stop: function stop() {
    $('#confettiCanvasId').fadeOut();
    setTimeout(function(){
        var canvas = document.getElementById("confettiCanvasId");
        if (canvas) {
            canvas.parentNode.removeChild(canvas);
        }
        if (confetti.endFunction) {
            confetti.endFunction();
        }
    },1000);

}
};

CSS:

.confettiCanvas{
overflow: hidden;
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
}
于 2013-10-23T17:28:45.873 回答
0

我认为canvas-confetti比这里的任何其他都更逼真,并且它具有更多功能:五彩纸屑、雪、烟花等。点击这里进行演示!

于 2020-11-08T12:21:32.813 回答