前言
结合gameCanvas插件实现的电子烟花
代码
[index.html]
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8" />
- <title>2024龙年大吉</title>
- </head>
-
- <body>
- <script src="js/gameCanvas-4.0.js"></script>
- <script src="js/script.js"></script>
- <!--live2d-->
- <script src="https://blog-static.cnblogs.com/files/zouwangblog/autoload.js"></script>
- <!--live2dend-->
-
- <!--放大图片-->
- <link rel="stylesheet" type="text/css" href="https://blog-static.cnblogs.com/files/zouwangblog/zoom.css" />
- <script src="https://cdn.bootcss.com/jquery/1.8.3/jquery.min.js"></script>
- <script src="https://cdn.bootcss.com/bootstrap/3.2.0/js/transition.js"></script>
- <script src="https://blog-static.cnblogs.com/files/zouwangblog/zoom.js"></script>
- <script type="text/javascript">
- $("#cnblogs_post_body img").attr("data-action", "zoom");
- </script>
- <!--放大图片end-->
-
- <!--鼠标特效-->
- <script src="https://blog-static.cnblogs.com/files/zouwangblog/mouse-click.js"></script>
- <canvas width="1777" height="841" style="
- position: fixed;
- left: 0px;
- top: 0px;
- z-index: 2147483647;
- pointer-events: none;
- "></canvas>
- <!--鼠标特效 end-->
-
- <!-- require APlayer -->
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css" />
- <script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
- <!-- require MetingJS -->
- <script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script>
- <meting-js id="2829883282" lrc-type="0" server="netease" order="random" type="playlist" fixed="true" autoplay="false"
- list-olded="true">
- </meting-js>
-
- <!-- 随机线条 -->
- <script>
- !(function () {
- function n(n, e, t) {
- return n.getAttribute(e) || t;
- }
- function e(n) {
- return document.getElementsByTagName(n);
- }
- function t() {
- var t = e("script"),
- o = t.length,
- i = t[o - 1];
- return {
- l: o,
- z: n(i, "zIndex", -1),
- o: n(i, "opacity", 0.6),
- c: n(i, "color", "148,0,211"),
- n: n(i, "count", 99),
- };
- }
- function o() {
- (a = m.width =
- window.innerWidth ||
- document.documentElement.clientWidth ||
- document.body.clientWidth),
- (c = m.height =
- window.innerHeight ||
- document.documentElement.clientHeight ||
- document.body.clientHeight);
- }
- function i() {
- r.clearRect(0, 0, a, c);
- var n, e, t, o, m, l;
- s.forEach(function (i, x) {
- for (
- i.x += i.xa,
- i.y += i.ya,
- i.xa *= i.x > a || i.x < 0 ? -1 : 1,
- i.ya *= i.y > c || i.y < 0 ? -1 : 1,
- r.fillRect(i.x - 0.5, i.y - 0.5, 1, 1),
- e = x + 1;
- e < u.length;
- e++
- )
- (n = u[e]),
- null !== n.x &&
- null !== n.y &&
- ((o = i.x - n.x),
- (m = i.y - n.y),
- (l = o * o + m * m),
- l < n.max &&
- (n === y &&
- l >= n.max / 2 &&
- ((i.x -= 0.03 * o), (i.y -= 0.03 * m)),
- (t = (n.max - l) / n.max),
- r.beginPath(),
- (r.lineWidth = t / 2),
- (r.strokeStyle = "rgba(" + d.c + "," + (t + 0.2) + ")"),
- r.moveTo(i.x, i.y),
- r.lineTo(n.x, n.y),
- r.stroke()));
- }),
- x(i);
- }
- var a,
- c,
- u,
- m = document.createElement("canvas"),
- d = t(),
- l = "c_n" + d.l,
- r = m.getContext("2d"),
- x =
- window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.oRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- function (n) {
- window.setTimeout(n, 1e3 / 45);
- },
- w = Math.random,
- y = { x: null, y: null, max: 2e4 };
- (m.id = l),
- (m.style.cssText =
- "position:fixed;top:0;left:0;z-index:" + d.z + ";opacity:" + d.o),
- e("body")[0].appendChild(m),
- o(),
- (window.onresize = o),
- (window.onmousemove = function (n) {
- (n = n || window.event), (y.x = n.clientX), (y.y = n.clientY);
- }),
- (window.onmouseout = function () {
- (y.x = null), (y.y = null);
- });
- for (var s = [], f = 0; d.n > f; f++) {
- var h = w() * a,
- g = w() * c,
- v = 2 * w() - 1,
- p = 2 * w() - 1;
- s.push({ x: h, y: g, xa: v, ya: p, max: 6e3 });
- }
- (u = s.concat([y])),
- setTimeout(function () {
- i();
- }, 100);
- })();
- </script>
-
- <!-- 雪花特效 -->
- <script type="text/javascript">
- (function ($) {
- $.fn.snow = function (options) {
- var $flake = $('<div id="snowbox" />')
- .css({ position: "absolute", "z-index": "9999", top: "-50px" })
- .html("❄"),
- documentHeight = $(document).height(),
- documentWidth = $(document).width(),
- defaults = {
- minSize: 10,
- maxSize: 20,
- newOn: 1000,
- flakeColor:
- "#FFFFFF",
- },
- options = $.extend({}, defaults, options);
- var interval = setInterval(function () {
- var startPositionLeft = Math.random() * documentWidth - 100,
- startOpacity = 0.5 + Math.random(),
- sizeFlake = options.minSize + Math.random() * options.maxSize,
- endPositionTop = documentHeight - 200,
- endPositionLeft = startPositionLeft - 500 + Math.random() * 500,
- durationFall = documentHeight * 10 + Math.random() * 5000;
- $flake
- .clone()
- .appendTo("body")
- .css({
- left: startPositionLeft,
- opacity: startOpacity,
- "font-size": sizeFlake,
- color: options.flakeColor,
- })
- .animate(
- {
- top: endPositionTop,
- left: endPositionLeft,
- opacity: 0.2,
- },
- durationFall,
- "linear",
- function () {
- $(this).remove();
- }
- );
- }, options.newOn);
- };
- })(jQuery);
- $(function () {
- $.fn.snow({
- minSize: 5 /* 定义雪花最小尺寸 */,
- maxSize: 80 /* 定义雪花最大尺寸 */,
- newOn: 200 /* 定义密集程度,数字越小越密集 */,
- });
- });
- </script>
- </body>
-
- </html>
[script.js]
- var gc = new GameCanvas();
-
- var points = textToPoints("2024龙年大吉", 20, "Anton");
-
-
- var titleParticles = [];
- var fireworks = [];
- var particles = [];
-
- var gravity = 0.1;
-
- setTimeout(function () {
- setInterval(function () {
- fireworks.push(new Firework(Math.random() * width, height, Math.random() - 0.5, -(Math.random() * 7 + 5)));
- }, 200);
- }, 2000);
-
- fireworks.push(new Firework(width / 2, height, 0, -9.5, 10, "gold", true));
- setInterval(function () {
- fireworks.push(new Firework(width / 2, height, 0, -9.5, 10, "gold", true));
- }, 5000);
-
- for (var i = 0; i < 250; i++) {
- circle(
- Math.random() * width,
- Math.random() * height,
- 1,
- "rgb(200, 200, 200)"
- );
- }
- var starImage = canvasToImage();
-
- background("black");
- loop();
- function loop() {
- gc.ctx.globalCompositeOperation = "source-over";
- background("rgba(0, 0, 0, 0.1)");
- gc.ctx.drawImage(starImage, 0, 0);
- gc.ctx.globalCompositeOperation = "lighter";
-
- for (var i = 0; i < fireworks.length; i++) {
- var firework = fireworks[i];
- firework.update();
- firework.render();
- }
-
- for (var i = 0; i < particles.length; i++) {
- var particle = particles[i];
- particle.update();
- particle.render();
- }
-
- for (var i = 0; i < titleParticles.length; i++) {
- var p = titleParticles[i];
- p.update();
- p.render();
- }
-
- requestAnimationFrame(loop);
- }
-
- function TitleParticle(x, y, vx, vy) {
- this.x = x;
- this.y = y;
- this.vx = vx;
- this.vy = vy;
- this.ay = 0.2;
- this.radius = 4;
- this.maxHealth = 200;
- this.health = 200;
-
- this.update = function () {
- this.x += this.vx;
- this.y += this.vy;
- this.vx *= 0.95;
- this.vy *= 0.95;
- this.vy += this.ay;
- this.ay *= 0.95;
-
- this.radius = (this.health / this.maxHealth) * 4;
- this.health--;
- if (this.health <= 0) {
- titleParticles.splice(titleParticles.indexOf(this), 1);
- }
- }
-
- this.render = function () {
- circle(this.x, this.y, this.radius, "rgba(255, 255, 255, " + (this.health / this.maxHealth) + ")");
- }
- }
-
- function Firework(x, y, vx, vy, radius = 5, color = "white", title = false) {
- this.x = x;
- this.y = y;
- this.vx = vx;
- this.vy = vy;
- this.radius = radius;
- this.title = title;
- this.color = color;
-
- this.update = function () {
- this.x += this.vx;
- this.y += this.vy;
- this.vy += gravity;
-
- if (this.vy >= 0) {
- fireworks.splice(fireworks.indexOf(this), 1);
-
- if (this.title) {
- var scale = 0.3;
- for (var i = 0; i < points.length; i++) {
- var p = points[i];
- var v = {
- x: (p.x - 60) * scale + (Math.random() - 0.5) * 0.1,
- y: (p.y - 20) * scale + (Math.random() - 0.5) * 0.1
- }
- var particle = new TitleParticle(this.x, this.y, v.x, v.y);
- titleParticles.push(particle);
- }
- }
- else {
- var color = [Math.random() * 256 >> 0, Math.random() * 256 >> 0, Math.random() * 256 >> 0];
- for (var i = 0; i < Math.PI * 2; i += 0.1) {
- var power = (Math.random() + 0.5) * 4;
- var vx = Math.cos(i) * power;
- var vy = Math.sin(i) * power;
- particles.push(new Particle(this.x, this.y, vx, vy, Math.random() + 3, color));
- }
- }
- }
- }
-
- this.render = function () {
- circle(this.x, this.y, this.radius, this.color);
- }
- }
-
- function Particle(x, y, vx, vy, radius, color) {
- this.x = x;
- this.y = y;
- this.vx = vx;
- this.vy = vy;
- this.life = 100;
- this.color = color;
- this.radius = radius;
-
- this.update = function () {
- this.x += this.vx;
- this.y += this.vy;
- this.vy += gravity;
-
- this.vx *= 0.95;
- this.vy *= 0.95;
-
- this.life--;
- if (this.life <= 0) {
- particles.splice(particles.indexOf(this), 1);
- }
- }
-
- this.render = function () {
- circle(this.x, this.y, 3 * (this.life / 100), "rgba(" + this.color[0] + ", " + this.color[1] + ", " + this.color[2] + ", " + (this.life / 100) + ")");
- }
- }
-
- function textToPoints(text, textSize, font) {
- var canvas = document.createElement("canvas");
- canvas.width = 1024;
- canvas.height = textSize * 1.3;
- var ctx = canvas.getContext("2d");
-
- ctx.textBaseline = "middle";
- ctx.font = textSize + "px " + font;
- ctx.fillText(text, 0, canvas.height / 2);
-
- var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
- var data = imageData.data;
-
- var points = [];
- var index = (x, y) => (x + canvas.width * y) * 4;
- var threshold = 50;
-
- for (var i = 0; i < data.length; i += 4) {
- if (data[i + 3] > threshold) {
- var p = {
- x: (i / 4) % canvas.width,
- y: (i / 4) / canvas.width >> 0
- };
-
- if (data[index(p.x + 1, p.y) + 3] < threshold ||
- data[index(p.x - 1, p.y) + 3] < threshold ||
- data[index(p.x, p.y + 1) + 3] < threshold ||
- data[index(p.x, p.y - 1) + 3] < threshold) {
- points.push({
- x: (i / 4) % canvas.width,
- y: (i / 4) / canvas.width >> 0
- });
- }
- }
- }
-
- return points;
- }
[gameCanvas-4.0.js]
下载地址:https://wwu.lanpv.com/ilG8t1o6xlbc
最终效果就如开头的效果图一致,可自定义修改爆炸内容(在textToPoints函数内修改即可)