<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文字雨</title>
<style>
html, body {
height: 100%;
margin: 0;
overflow: hidden;
}
body {
display: flex;
align-items: center;
justify-content: center;
background: #000;
}
main {
display: flex;
}
p {
line-height: 1;
}
span {
display: block;
width: 2vmax;
height: 2vmax;
font-size: 2vmax;
color: #9bff9b11;
text-align: center;
font-family: "Helvetica Neue", Helvetica, sans-serif;
}
</style>
</head>
<body>
<main></main>
<script>
function r(from, to) {
return ~~(Math.random() * (to - from + 1) + from);
}
function pick() {
return arguments[r(0, arguments.length - 1)];
}
function getChar() {
return String.fromCharCode(pick(
r(0x3041, 0x30ff),
r(0x2000, 0x206f),
r(0x0020, 0x003f)
));
}
function loop(fn, delay) {
let stamp = Date.now();
function _loop() {
if (Date.now() - stamp >= delay) {
fn(); stamp = Date.now();
}
requestAnimationFrame(_loop);
}
requestAnimationFrame(_loop);
}
class Char {
constructor() {
this.element = document.createElement('span');
this.mutate();
}
mutate() {
this.element.textContent = getChar();
}
}
class Trail {
constructor(list = [], options) {
this.list = list;
this.options = Object.assign(
{ size: 10, offset: 0 }, options
);
this.body = [];
this.move();
}
traverse(fn) {
this.body.forEach((n, i) => {
let last = (i == this.body.length - 1);
if (n) fn(n, i, last);
});
}
move() {
this.body = [];
let { offset, size } = this.options;
for (let i = 0; i < size; ++i) {
let item = this.list[offset + i - size + 1];
this.body.push(item);
}
this.options.offset =
(offset + 1) % (this.list.length + size - 1);
}
}
class Rain {
constructor({ target, row }) {
this.element = document.createElement('p');
this.build(row);
if (target) {
target.appendChild(this.element);
}
this.drop();
}
build(row = 20) {
let root = document.createDocumentFragment();
let chars = [];
for (let i = 0; i < row; ++i) {
let c = new Char();
root.appendChild(c.element);
chars.push(c);
if (Math.random() < .5) {
loop(() => c.mutate(), r(1e3, 5e3));
}
}
this.trail = new Trail(chars, {
size: r(10, 30), offset: r(0, 100)
});
this.element.appendChild(root);
}
drop() {
let trail = this.trail;
let len = trail.body.length;
let delay = r(10, 100);
loop(() => {
trail.move();
trail.traverse((c, i, last) => {
c.element.style = `
color: hsl(136, 100%, ${85 / len * (i + 1)}%)
`;
if (last) {
c.mutate();
c.element.style = `
color: hsl(136, 100%, 85%);
text-shadow:
0 0 .5em #fff,
0 0 .5em currentColor;
`;
}
});
}, delay);
}
}
const main = document.querySelector('main');
for (let i = 0; i < 50; ++i) {
new Rain({ target: main, row: 50 });
}
</script>
</body>
</html>
用html实现文字雨
转载请注明出处或者链接地址:https://www.qianduange.cn//article/10246.html
相关文章
-
快速入门:简单几步教你如何打开 JSON 文件
-
惬意上手python —— JSON模块介绍
-
npm run serve与npm run dev的区别
-
解决npm已更换淘宝镜像仍然下载特别慢的问题
-
使用npm、npm和yarn在协作开发时的隐藏危险:版本冲突
-
npm i报错quest to https://registry.npmjs.org/xxx failed,reason: connect ETIMEDOUT 104.16.25.34:443
-
node、npm、pnpm下载安装、卸载、踩坑
-
Node.js之npm单独与批量升级依赖包的方式
-
npm ERR! Invalid dependency type requested: alias解决
-
WHAT - npm 不同版本变化和 pnpm 依赖管理方案
发布的文章
Protobuf 和Json的互转功能在项目中的应用
2024-06-06 10:06:04
一文看懂 json.load()、json.loads()、json.dump()和json.dumps()
2024-06-06 10:06:04
mysql 批量更新json list里的key字段
2024-06-06 10:06:03
json.decoder.JSONDecodeError: Invalid \escape
2024-06-06 10:06:03
Shell 脚本实现自定义解析 Json 数据
2024-06-06 10:06:57
java读取json文件并解析并修改
2024-06-06 10:06:57
快速入门:简单几步教你如何打开 JSON 文件
2024-06-06 10:06:54
JSON&yaml和Properties
2024-06-06 10:06:54
惬意上手python —— JSON模块介绍
2024-06-06 10:06:52
JavaScript中的JSON.stringify()
2024-06-06 10:06:52
大家推荐的文章