MCBBS Wiki欢迎您共同参与编辑!在参与编辑之前请先阅读Wiki方针。
如果在编辑的过程中遇到了什么问题,可以去讨论板提问。
为了您能够无阻碍地参与编辑 未验证/绑定过邮箱的用户,请尽快绑定/验证。
MCBBS Wiki GitHub群组已上线!
您可以在回声洞中发表吐槽!
服务器状态监控。点击进入
本站由MCBBS用户自行搭建,与MCBBS及东银河系漫游指南(北京)科技有限公司没有从属关系。点此了解 MCBBS Wiki 不是什么>>
帮助:沙盒:修订间差异
跳到导航
跳到搜索
小 (日常清空) |
(// Edit via Wikiplus) |
||
第1行: | 第1行: | ||
{{/handler}} |
{{/handler}} |
||
== 请在这行文字下测试您的编辑 == |
== 请在这行文字下测试您的编辑 == |
||
{{Widget:SaltFirework}} |
2021年1月20日 (三) 14:03的版本
沙盒(Sandbox)是供Wiki内所有贡献者测试编辑效果用的,管理员有义务定期清理。
如果您在此保存的内容被清理了,可以通过右上角的历史找回。
如果您不希望自己的内容被他人覆盖,请在自己的用户页创建沙盒。
请在这行文字下测试您的编辑
<script> /**
- 搬运须知: 您必须在**显眼处**标识来源“MCBBS Wiki”与作者“Salt_lovely”, **不**接受任何形式的简称或不署名。
- Notice: You have to mark origin "MCBBS Wiki" and author "Salt_lovely" in CONSPICUOS PLACE, abbreviation or omissions are NOT allowed.
- 许可证: CC BY-NC-SA 4.0
- License: CC BY-NC-SA 4.0
- 灵感来源: https://codepen.io/jackrugile/pen/acAgx 作者 Jack Rugile
- Inspired By: https://codepen.io/jackrugile/pen/acAgx Author Jack Rugile
- /
"use strict"; (() => {
// src/utils/utils.ts function docReady(fn) { if (document.readyState === "loading") { window.addEventListener("DOMContentLoaded", fn); } else { fn(); } } function randomChoice(arr) { if (arr.length < 1) { return null; } return arr[Math.floor(Math.random() * arr.length)]; }
// widget/SaltFirework/widget.ts if (document.getElementById("saltFireWorkCanvas")) throw new Error("同一页面中只能有一个烟花"); //! 颜色范围 var hueRange; //! 颜色变化区间 var hueDiff; //! 粒子效果数量 var count; var baseRange = [1, 4]; var baseSpeed = [0.3, 2, 3]; var fallSpeed = 1.1 / 60; var fadeSpeed = 0.65; var tail = 15; var canvas = document.createElement("canvas"); var context = canvas.getContext("2d"); var particles = []; var lastLength = 0; var zeroFrame = 0; docReady(init); function init() { const getValue = (id, defaultValue, min, max) => { const e = document.getElementById(id); if (!e) return defaultValue; const c = parseInt(e.textContent || ""); if (isNaN(c) || c < min || c > max) return defaultValue; return c; }; hueRange = (() => { const defaultValue = (() => { var x = []; for (let i = 1; i < 361; i++) x.push(i); return x; })(); const e = document.getElementById("saltFireworkHueRange"); if (!e) return defaultValue; const c = (e.textContent || "").replace(/[\s\n_]+/g, "").replace(/[\;\/\|\/\\,;、\-]+/g, ",").split(",").map((v) => parseInt(v)).filter(Boolean).filter((v) => v > 0 && v < 361); if (!c || c.length < 1 || c.length > 360) return defaultValue; return c; })(); hueDiff = getValue("saltFireworkHueDiff", 30, 0, 180); count = getValue("saltFireworkCount", 110, 1, 500); canvas.id = "saltFireWorkCanvas"; canvas.style.left = "0"; canvas.style.top = "0"; canvas.style.position = "fixed"; canvas.style.pointerEvents = "none"; canvas.style.zIndex = "99999"; document.body.appendChild(canvas); resizeCanvas(); window.addEventListener("resize", resizeCanvas, false); tick(); document.addEventListener("mousedown", function(e) { createFireworks(e.clientX, e.clientY); }); } function resizeCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } function rightRandom(base, size) { return base + (Math.random() * size - Math.random() * size) / 2; } function createFireworks(x, y) { let hue = randomChoice(hueRange); for (let i = 0; i < count; i++) { const spd = rightRandom((baseSpeed[1] + baseSpeed[0]) / 2, baseSpeed[1] - baseSpeed[0]); const rad = Math.random() * 2 * Math.PI; particles.push({ x, y, spdX: Math.cos(rad) * spd, spdY: Math.sin(rad) * spd, spdFall: baseSpeed[2], size: rightRandom((baseRange[1] + baseRange[0]) / 2, baseRange[1] - baseRange[0]), hue: hueRandom(), bright: rightRandom(72, 16), alpha: rightRandom(75, 30) }); } function hueRandom() { let h = Math.floor(rightRandom(hue, hueDiff)); if (h > 360) h -= 360; else if (h < 0) h += 360; return h; } } function drawParticles() { if (!particles.length) return; context.globalCompositeOperation = "lighter"; for (let i = 0; i < particles.length; i++) { let p = particles[i]; if (!p) continue; p.x += p.spdX * p.spdFall; p.y += p.spdY * p.spdFall; p.spdY += fallSpeed; p.spdFall *= 0.978; p.alpha -= fadeSpeed; context.beginPath(); context.arc(p.x, p.y, p.size, 0, Math.PI * 2, false); context.closePath(); context.fillStyle = `hsla(${p.hue},100%,${p.bright}%,${p.alpha / 100})`; context.fill(); //! 标记已经透明到看不见的粒子 if (p.alpha < fadeSpeed) particles[i] = null; } if (lastLength === 0 && particles.length === 0) { zeroFrame += 1; if (zeroFrame === 30) canvas.height = window.innerHeight; } else { zeroFrame = 0; } lastLength = particles.length; } function drawTail() { if (zeroFrame >= 30) return; //! 保留前一刻的图案作为尾迹 context.globalCompositeOperation = "destination-out"; context.fillStyle = `rgba(0,0,0,${1 / tail})`; context.fillRect(0, 0, canvas.width, canvas.height); } function clearParticles() { if (!particles.length) return; let cp = []; for (let p of particles) if (p) cp.push(p); if (cp.length !== particles.length) particles = cp; } function tick() { //! 画尾迹 -> 画这一帧的粒子 -> 删除运算完毕的粒子 drawTail(); drawParticles(); clearParticles(); if (false) { const el = document.getElementById("saltFWInfo"); if (el) { el.innerHTML = particles.map((p) => JSON.stringify(p)).join("
"); } } requestAnimationFrame(tick); }
})(); </script>