帮助:沙盒
沙盒(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>