canvas实现烟花爆竹特效
这个 canvas 实现的烟花爆竹特效例子死我在网上收集的,效果很 high,关键是我想通过笨栗子来提高自己的 canvas,好了不多说了,基本的 canvas 语法就不和大家说了,我想看到这篇文章的人,基础已经学过了,所以直接上代码,看人家的思路就可以了。
CSS 代码:
body { background: #000; margin: 0; } canvas { cursor: crosshair; display: block }
HTML 代码:
<canvas id="canvas"></canvas>
Javascript 代码:
// 当在 canvas 上动画时,最好使用 requestAnimationFrame 而不是 setTimeout 或 setInterval window.requestAnimFrame = (function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); }; })(); // 现在我们将为演示设置我们的基本变量 var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), // 全屏尺寸 cw = window.innerWidth, ch = window.innerHeight, //烟花汇集 fireworks = [], // 颗粒收集 particles = [], // 开始调色 hue = 120, // 当点击发射烟花时,限制每 5 个循环一次启动一次 limiterTotal = 5, limiterTick = 0, // 自动启动烟花爆竹,每 80 个循环一次启动一次 timerTotal = 80, timerTick = 0, mousedown = false, // 鼠标 x 坐标,mx, // 鼠标 y 坐标, my; // 设置画布尺寸 canvas.width = cw; canvas.height = ch; //现在我们要为整个演示设置我们的函数占位符 // 获得一个范围内的随机数 function random(min, max) { return Math.random() * (max - min) + min; } // 计算两点之间的距离 function calculateDistance(p1x, p1y, p2x, p2y) { var xDistance = p1x - p2x, yDistance = p1y - p2y; return Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2)); } // 创造烟火 function Firework(sx, sy, tx, ty) { // 实际坐标 this.x = sx; this.y = sy; // 开始坐标 this.sx = sx; this.sy = sy; // 目标坐标 this.tx = tx; this.ty = ty; // 从起点到目标的距离 this.distanceToTarget = calculateDistance(sx, sy, tx, ty); this.distanceTraveled = 0; // 跟踪每个烟花的过去坐标以创建尾迹效果,增加坐标数量以创建更显眼的尾迹 this.coordinates = []; this.coordinateCount = 3; // 用当前坐标填充初始坐标集合 while (this.coordinateCount--) { this.coordinates.push([this.x, this.y]); } this.angle = Math.atan2(ty - sy, tx - sx); this.speed = 2; this.acceleration = 1.05; this.brightness = random(50, 70); // 圆圈目标指标半径 this.targetRadius = 1; } // 更新烟火 Firework.prototype.update = function (index) { // 删除坐标数组中的最后一项 this.coordinates.pop(); // 将当前坐标添加到数组的开头 this.coordinates.unshift([this.x, this.y]); // 循环圆目标指示半径 if (this.targetRadius < 8) { this.targetRadius += 0.3; } else { this.targetRadius = 1; } // 加快烟火 this.speed *= this.acceleration; // 根据角度和速度获取当前速度 var vx = Math.cos(this.angle) * this.speed, vy = Math.sin(this.angle) * this.speed; // 随着速度的施加,烟花会走多远? this.distanceTraveled = calculateDistance(this.sx, this.sy, this.x + vx, this.y + vy); // 如果行进的距离(包括速度)大于到目标的初始距离,则目标已达到 if (this.distanceTraveled >= this.distanceToTarget) { createParticles(this.tx, this.ty); // 删除烟花,使用传入更新函数的索引来确定要删除的内容 fireworks.splice(index, 1); } else { // 目标未达到,继续旅行 this.x += vx; this.y += vy; } } // 画烟花 Firework.prototype.draw = function () { ctx.beginPath(); // 移动到集合中最后一个被跟踪的坐标,然后画一条线到当前的 x 和 y ctx.moveTo(this.coordinates[this.coordinates.length - 1][0], this.coordinates[this.coordinates.length - 1][ 1 ]); ctx.lineTo(this.x, this.y); ctx.strokeStyle = 'hsl(' + hue + ', 100%, ' + this.brightness + '%)'; ctx.stroke(); ctx.beginPath(); // 用脉冲圈画出这个烟花的目标 ctx.arc(this.tx, this.ty, this.targetRadius, 0, Math.PI * 2); ctx.stroke(); } // 创造粒子 function Particle(x, y) { this.x = x; this.y = y; // 跟踪每个粒子的过去坐标以创建一个跟踪效果,增加坐标数量以创建更显眼的轨迹 this.coordinates = []; this.coordinateCount = 5; while (this.coordinateCount--) { this.coordinates.push([this.x, this.y]); } // 在所有可能的方向上以弧度设置一个随机角度 this.angle = random(0, Math.PI * 2); this.speed = random(1, 10); // 摩擦会减慢粒子的速度 this.friction = 0.95; // 重力将被应用并将粒子拉下 this.gravity = 1; // 将色调设置为整个色调变量的随机数字+20 this.hue = random(hue - 20, hue + 20); this.brightness = random(50, 80); this.alpha = 1; // 设置粒子消失的速度 this.decay = random(0.015, 0.03); } // 更新粒子 Particle.prototype.update = function (index) { // 删除坐标数组中的最后一项 this.coordinates.pop(); // 将当前坐标添加到数组的开头 this.coordinates.unshift([this.x, this.y]); // 减慢粒子 this.speed *= this.friction; // 施加速度 this.x += Math.cos(this.angle) * this.speed; this.y += Math.sin(this.angle) * this.speed + this.gravity; // 淡出粒子 this.alpha -= this.decay; // 基于传入的索引,一旦 alpha 足够低,就移除粒子 if (this.alpha <= this.decay) { particles.splice(index, 1); } } // 画出粒子 Particle.prototype.draw = function () { ctx.beginPath(); // 移动到集合中最后一个跟踪的坐标,然后画一条线到当前的 x 和 y ctx.moveTo(this.coordinates[this.coordinates.length - 1][0], this.coordinates[this.coordinates.length - 1][ 1 ]); ctx.lineTo(this.x, this.y); ctx.strokeStyle = 'hsla(' + this.hue + ', 100%, ' + this.brightness + '%, ' + this.alpha + ')'; ctx.stroke(); } // 创建粒子群/爆炸 function createParticles(x, y) { //增加更大的爆炸颗粒数量,但要注意增加颗粒的帆布性能 var particleCount = 30; while (particleCount--) { particles.push(new Particle(x, y)); } } // 主演示循环 function loop() { // 这个函数将在 requestAnimationFrame 中运行 requestAnimFrame(loop); //随着时间的推移,增加色彩以获得不同颜色的烟花 hue += 0.5; // 通常,clearRect()将用于清除画布 // 我们想要创建一个拖尾效果 // 将复合操作设置为 destination-out 将允许我们以特定的不透明度清除画布,而不是完全擦除画布 ctx.globalCompositeOperation = 'destination-out'; // 减少 alpha 属性以创建更显着的路径 ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; ctx.fillRect(0, 0, cw, ch); // 将复合操作更改回主模式 // 当烟火和微粒相互重叠时,打火机会产生明亮的高光点 ctx.globalCompositeOperation = 'lighter'; var text = "HAPPY NEW YEAR !"; ctx.font = "50px sans-serif"; var textData = ctx.measureText(text); ctx.fillStyle = "rgba(" + parseInt(random(0, 255)) + "," + parseInt(random(0, 255)) + "," + parseInt(random(0, 255)) + ",0.3)"; ctx.fillText(text, cw / 2 - textData.width / 2, ch / 2); //循环遍历每个烟花,绘制它,更新它 var i = fireworks.length; while (i--) { fireworks[i].draw(); fireworks[i].update(i); } // 循环遍历每个粒子,绘制它,更新它 var i = particles.length; while (i--) { particles[i].draw(); particles[i].update(i); } //当鼠标未关闭时,自动将烟火发射到随机坐标 if (timerTick >= timerTotal) { if (!mousedown) { // 在屏幕的中下部开始烟火,然后设置随机目标坐标,随机 y 坐标将设置在屏幕上半部分的范围内 for (var h = 0; h < 50; h++) { fireworks.push(new Firework(cw / 2, ch / 2, random(0, cw), random(0, ch))); } timerTick = 0; } } else { timerTick++; } // 限制鼠标关闭时启动烟花的速度 if (limiterTick >= limiterTotal) { if (mousedown) { // 在屏幕底部中间启动烟火,然后将当前鼠标坐标设置为目标 fireworks.push(new Firework(cw / 2, ch / 2, mx, my)); limiterTick = 0; } } else { limiterTick++; } } // 鼠标事件绑定 // 更新 mousemove 上的鼠标坐标 canvas.addEventListener('mousemove', function (e) { mx = e.pageX - canvas.offsetLeft; my = e.pageY - canvas.offsetTop; }); // 切换 mousedown 状态并防止选择画布 canvas.addEventListener('mousedown', function (e) { e.preventDefault(); mousedown = true; }); canvas.addEventListener('mouseup', function (e) { e.preventDefault(); mousedown = false; }); // 一旦窗户加载,我们准备好了一些烟花! window.onload = loop;
结束语
效果很华丽,我只能帮到这里了,接下来就是看你得了,年轻人加油!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » canvas实现烟花爆竹特效
码云笔记 » canvas实现烟花爆竹特效