立刻就要過春節了,大城市裏依然是不許燃放煙花這種空氣污染的東西的,想念小時候在自家院子裏放花的快樂時光,大城市裏的小朋友們是體會不到這種快樂了。但做爲前端工程師,這難不倒咱們,下面就教你們如何用JS在網頁裏放煙花。javascript
在 codepen 裏搜索 「fireworks」 能夠搜到各類使用JS完成的煙花效果。我今天分享的代碼,也是參考自其中一個。前端
這分代碼經我修改後,已經植入到「我愛掘金」的蝌蚪池塘中,只要發送「新年快樂」,「春節快樂」,就能夠在池塘裏放煙花了。java
這篇文章看完,保證你在任何平臺,用任何語言均可以寫出來放煙花的效果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
動起來其實就是不斷的去繪製一個值從小變大的圓心半徑...能明白吧,不斷的繪製有兩種方法,setInterval
和requestAnimationFrame
,兩種方法均可以。前端工程師
優勢:能夠比較容易的設定動畫的繪製頻率。app
var radius = 0;//圓心半徑
function fire(x,y){
function tick() {
drawFireworks(x,y);//繪製煙花
radius++;//半徑不斷變大
}
setInterval(tick,30);//每30毫秒繪製一次
}
複製代碼
優勢:繪製頻率跟瀏覽器畫面的繪製同步。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
」 獲取源碼連接
一個玩轉各類大前端技術的老程序猿
近期文章(感謝掘友的鼓勵與支持🌹🌹🌹)