快過年了,用JS讓你的網頁放🎆煙花吧

立刻就要過春節了,大城市裏依然是不許燃放煙花這種空氣污染的東西的,想念小時候在自家院子裏放花的快樂時光,大城市裏的小朋友們是體會不到這種快樂了。但做爲前端工程師,這難不倒咱們,下面就教你們如何用JS在網頁裏放煙花。javascript

codepen 裏搜索 「fireworks」 能夠搜到各類使用JS完成的煙花效果。我今天分享的代碼,也是參考自其中一個。前端

這分代碼經我修改後,已經植入到「我愛掘金」的蝌蚪池塘中,只要發送「新年快樂」,「春節快樂」,就能夠在池塘裏放煙花了。java

這篇文章看完,保證你在任何平臺,用任何語言均可以寫出來放煙花的效果canvas

如何實現的?

先建立一個Canvas

先新建一個和網頁可視區大小同樣的canvas,而且經過監聽顯示區的resize事件,來改變canvas的大小。瀏覽器

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');

function resizeCanvas() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
}

function clearCanvas(){
	context.fillStyle = '#ffffff';
	context.fillRect(0,0,canvas.width, canvas.height);
}

window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
複製代碼

放煙花以前的練習

煙花都是從一個點爆炸,伴隨着不一樣的弧度散開,因此咱們先繪製幾個小圓點,環繞着一個圓心。有點像loading的小圈圈。這其實就是煙花最開始的狀態...微信

function mouseDownHandler(e) {
    var x = e.clientX;
    var y = e.clientY;

    drawFireworks(x,y);
}

function drawFireworks(sx,sy) {
    var count = 10;//煙花粒子數量
    var radius = 10;//煙花環繞半徑

    for(var i = 0 ;i<count;i++){
        var angle = 360/count*i;//煙花粒子角度
        var radians = angle * Math.PI / 180;//煙花粒子弧度

        var vx = sx+Math.cos(radians) * radius;
        var vy = sy+Math.sin(radians) * radius;

        var size = 2;
        context.beginPath();
        context.arc(vx, vy, size, 0, Math.PI*2, false)
        context.closePath();
        context.fillStyle = "#ff0000";
        context.fill();
    }
}

document.addEventListener('mousedown', mouseDownHandler, false);
複製代碼

以上代碼的含義你們應該都懂對不對?但如今沒有動畫,一點也不像煙花。彆着急,咱們立刻就讓它們動起來。markdown

動起來

動起來其實就是不斷的去繪製一個值從小變大的圓心半徑...能明白吧,不斷的繪製有兩種方法,setIntervalrequestAnimationFrame,兩種方法均可以。前端工程師

  1. setInterval

優勢:能夠比較容易的設定動畫的繪製頻率。app

var radius = 0;//圓心半徑
function fire(x,y){
    function tick() {
        drawFireworks(x,y);//繪製煙花
        radius++;//半徑不斷變大
    }
    setInterval(tick,30);//每30毫秒繪製一次
}
複製代碼
  1. requestAnimationFrame

優勢:繪製頻率跟瀏覽器畫面的繪製同步。dom

var radius = 0;
function fire(x,y){
    function tick() {
        drawFireworks(x,y);
        radius++;
        requestAnimationFrame(tick);
    }
    tick();
}
複製代碼

是否是已經有點感受了?

更像煙花一點

但真實的煙花確定不會這麼聽話,規規矩矩的保持弧度和速度,因此咱們要加入一些隨機因子。

var rid;
function fire(x,y){
    createFireworks(x,y);

    function tick() {
        drawFireworks();
        rid=requestAnimationFrame(tick);
    }
    cancelAnimationFrame(rid);
    tick();
}

var particles=[];
function createFireworks(sx,sy){
    particles=[];

    var hue = Math.floor(Math.random()*51)+150;
    var hueVariance = 30;
    var count = 100;

    for(var i = 0 ;i<count;i++){
        var p = {};

        var angle = Math.floor(Math.random()*360);
        p.radians = angle * Math.PI / 180;
        p.radius = 0;

        p.sx = sx;
        p.sy = sy;

        p.speed = (Math.random()*5)+.4;

        p.size = Math.floor(Math.random()*3)+1;

        p.hue = Math.floor(Math.random()*((hue+hueVariance)-(hue-hueVariance)))+(hue-hueVariance);
        p.brightness = Math.floor(Math.random()*31)+50;
        p.alpha = (Math.floor(Math.random()*61)+40)/100;

        particles.push(p);
    }
}

function drawFireworks() {
    clearCanvas();

    for(var i = 0 ;i<particles.length;i++){
        var p = particles[i];

        p.vx = p.sx+Math.cos(p.radians) * p.radius;
        p.vy = p.sy+Math.sin(p.radians) * p.radius;

        p.radius += 1+p.speed;

        context.beginPath();
        context.arc(p.vx, p.vy, p.size, 0, Math.PI*2, false);
        context.closePath();

        context.fillStyle = 'hsla('+p.hue+', 100%, '+p.brightness+'%, '+100+')';
        context.fill();
    }
}
複製代碼

很絢麗的對不對?如今咱們再給它加入一點菸霧拖尾的效果~

function tick() {
	//tips:注意新加入的這4行代碼
	context.globalCompositeOperation = 'destination-out';
	context.fillStyle = 'rgba(0,0,0,'+10/100+')';
	context.fillRect(0,0,canvas.width,canvas.height);
	context.globalCompositeOperation = 'lighter';
	//tipsend
	drawFireworks();
	rid=requestAnimationFrame(tick);
}
複製代碼

爲了更寫實,咱們繼續升級

如今加入一些重力的影響,讓煙花粒子的移動速度愈來愈慢而且慢慢下落消失

var vx = Math.cos(p.radians) * p.radius;
var vy = Math.sin(p.radians) * p.radius + 0.4;

p.x += vx;
p.y += vy;

p.radius *= 1 - p.speed/100;

p.alpha -= 0.005;
複製代碼

如今這個煙花看起來是否是就頗有煙花的感受了,固然各類參數你還能夠更細緻的加入一些變量。好比繪製一個炮竹,從炮竹處向天空發射。最後纔是煙花...這些就交給你們本身去實現吧。

在任意網頁上放煙花

在Chrome裏新建一個書籤,複製如下代碼,粘貼到網址一欄,而後保存。

javascript:!(function() {var cdom = document.createElement("canvas");cdom.id = "myCanvas";cdom.style.position="fixed";cdom.style.left = "0";cdom.style.top = "0";cdom.style.zIndex=-1;document.body.appendChild(cdom);var canvas = document.getElementById('myCanvas');var context = canvas.getContext('2d');function resizeCanvas() {canvas.width = window.innerWidth;canvas.height = window.innerHeight;}window.addEventListener('resize', resizeCanvas, false);resizeCanvas();clearCanvas();function clearCanvas(){context.fillStyle = '#000000';context.fillRect(0,0,canvas.width, canvas.height);}function mouseDownHandler(e) {var x = e.clientX;var y = e.clientY;fire(x,y);}var rid;function fire(x,y){createFireworks(x,y);function tick() {context.globalCompositeOperation = 'destination-out';    context.fillStyle = 'rgba(0,0,0,'+10/100+')';    context.fillRect(0,0,canvas.width,canvas.height);    context.globalCompositeOperation = 'lighter';drawFireworks();rid=requestAnimationFrame(tick);}cancelAnimationFrame(rid);tick();}var particles=[];function createFireworks(sx,sy){particles=[];var hue = Math.floor(Math.random()*51)+150;var hueVariance = 30;var count = 100;for(var i = 0 ;i<count;i++){var p = {};var angle = Math.floor(Math.random()*360);p.radians = angle * Math.PI / 180;p.x = sx;p.y = sy;p.speed = (Math.random()*5)+.4;p.radius = p.speed;p.size = Math.floor(Math.random()*3)+1;p.hue = Math.floor(Math.random()*((hue+hueVariance)-(hue-hueVariance)))+(hue-hueVariance);p.brightness = Math.floor(Math.random()*31)+50;p.alpha = (Math.floor(Math.random()*61)+40)/100;particles.push(p);}}function drawFireworks() {clearCanvas();for(var i = 0 ;i<particles.length;i++){var p = particles[i];var vx = Math.cos(p.radians) * p.radius;var vy = Math.sin(p.radians) * p.radius + 0.4;p.x += vx;p.y += vy;p.radius *= 1 - p.speed/100;p.alpha -= 0.005;context.beginPath();context.arc(p.x, p.y, p.size, 0, Math.PI*2, false);context.closePath();context.fillStyle = 'hsla('+p.hue+', 100%, '+p.brightness+'%, '+p.alpha+')';context.fill();}}document.addEventListener('mousedown', mouseDownHandler, false);})();
複製代碼

源碼下載

微信搜索 「ezfullstack」 關注並回復 「fireworks」 獲取源碼連接

關注大帥

一個玩轉各類大前端技術的老程序猿


近期文章(感謝掘友的鼓勵與支持🌹🌹🌹)

相關文章
相關標籤/搜索