HTML实现动态旋转字母背景

news2025/2/27 23:01:57

演示

在这里插入图片描述

css

html, body {
        background: radial-gradient(#181818, #000000);
        margin: 0;
        padding: 0;
        border: 0;
        -ms-overflow-style: none;
    }
    ::-webkit-scrollbar {
        width: 0.5em;
        height: 0.5em;
        background-color: #c7c7c7;
    }

    /*定义滚动条轨道 内阴影+圆角*/
    ::-webkit-scrollbar-track {
        -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
        border-radius: 10px;
        background-color: #181818;
    }

    /*定义滑块 内阴影+圆角*/
    ::-webkit-scrollbar-thumb {
        border-radius: 3px;
        -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
        background-color: #c7c7c7;
    }

画布

<!--背景-->
<canvas style="position: fixed;"></canvas>

<!--底部版权信息-->
<div style="position: fixed; bottom: 10px;width: 100%;text-align: center;-moz-user-select: none; -khtml-user-select: none; user-select: none;">
        <span style="color: #666666;font-size:0.5em"> &copy; All rights reserved by
            <a href="javascript:void(0)" onclick="authors()" style="color: #0082ff;text-decoration: none;"
               title="查看作者">微信号:onlyoneshun</a>
        </span>
</div>

script

window.onload = function () {
        //背景
        const CANVAS = document.getElementsByTagName("canvas")[0];
        const CTX = CANVAS.getContext("2d");
        const CHARS = [];
        const MAX_CHARS = 400;
        const SEPARATION = 2;
        let ww, wh, camera;

        class Vector {
            constructor(x, y, z) {
                this.x = x;
                this.y = y;
                this.z = z;
            }

            rotate(dir, ang) {
                const X = this.x;
                const Y = this.y;
                const Z = this.z;

                const SIN = Math.sin(ang);
                const COS = Math.cos(ang);

                if (dir === "x") {
                    this.y = Y * COS - Z * SIN;
                    this.z = Y * SIN + Z * COS;
                } else if (dir === "y") {
                    this.x = X * COS - Z * SIN;
                    this.z = X * SIN + Z * COS;
                }
            }

            project() {
                const ZP = this.z + camera.z;
                const DIV = ZP / 600;
                const XP = (this.x + camera.x) / DIV;
                const YP = (this.y + camera.y) / DIV;
                const CENTER = getCenter();
                return [XP + CENTER[0], YP + CENTER[1], ZP];
            }
        }

        class Char {
            constructor(letter, pos) {
                this.letter = letter;
                this.pos = pos;
            }

            rotate(dir, ang) {
                this.pos.rotate(dir, ang);
            }

            render() {
                const PIXEL = this.pos.project();
                const XP = PIXEL[0];
                const YP = PIXEL[1];
                const MAX_SIZE = 50;
                const SIZE = (1 / PIXEL[2] * MAX_SIZE) | 0;
                const BRIGHTNESS = SIZE / MAX_SIZE;
                const COL = `rgba(255, 255, ${100 * BRIGHTNESS | 0 + 150}, ${BRIGHTNESS})`;

                CTX.beginPath();
                CTX.fillStyle = COL;
                CTX.font = SIZE + "px monospace";
                CTX.fillText(this.letter, XP, YP);
                CTX.fill();
                CTX.closePath();
            }
        }

        function getCenter() {
            return [ww / 2, wh / 2];
        }

        function signedRandom() {
            return Math.random() - Math.random();
        }

        function render() {
            for (let i = 0; i < CHARS.length; i++) {
                CHARS[i].render();
            }
        }

        let time = 0;

        function update() {
            CTX.clearRect(0, 0, ww, wh);
            for (let i = 0; i < CHARS.length; i++) {
                const DX = 0.005 * Math.sin(time * 0.001);
                const DY = 0.005 * Math.cos(time * 0.001);
                CHARS[i].rotate("x", DX);
                CHARS[i].rotate("y", DY);
            }
            ++time;
        }

        function loop() {
            window.requestAnimationFrame(loop);
            update();
            render();
        }

        function getRandomInt(min, max) {
            return Math.floor(Math.random() * (max - min + 1)) + min;
        };

        function createChars() {
            for (let i = 0; i < MAX_CHARS; i++) {
                const CHARACTER = String.fromCharCode((Math.random() * 93 + 34) | 0);
                const X = signedRandom() * SEPARATION;
                const Y = signedRandom() * SEPARATION;
                const Z = signedRandom() * SEPARATION;
                const POS = new Vector(X, Y, Z);
                const CHAR = new Char(CHARACTER, POS);
                CHARS.push(CHAR);
            }
        }

        function setDim() {
            ww = window.innerWidth;
            wh = window.innerHeight;
            CANVAS.width = ww;
            CANVAS.height = wh;
        }

        function initCamera() {
            camera = new Vector(0, 0, SEPARATION + 1);
        }

        window.onresize = setDim;
        (() => {
            setDim();
            initCamera();
            createChars();
            loop();
        })();
    }

完整HTML

<html xmlns="http://www.w3.org/1999/html">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title><・)))><<</title>
    <link rel="shortcut icon" href="favicon.ico">
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <meta name="viewport"
          content="width=device-width,initial-scale=1.0,user-scalable=no,minimum-scale=1,maximum-scale=1">
    <META HTTP-EQUIV="pragma" content="no-cache">
    <META HTTP-EQUIV="Cache-Control" content="no-cache, must-revalidate">
    <META HTTP-EQUIV="expires" content="0">
    <meta name="viewport"
          content="width=device-width,initial-scale=1,minimum-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover"/>
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@600;900&display=swap" rel="stylesheet">

</head>
<style>
    html, body {
        background: radial-gradient(#181818, #000000);
        margin: 0;
        padding: 0;
        border: 0;
        -ms-overflow-style: none;
    }
    ::-webkit-scrollbar {
        width: 0.5em;
        height: 0.5em;
        background-color: #c7c7c7;
    }

    /*定义滚动条轨道 内阴影+圆角*/
    ::-webkit-scrollbar-track {
        -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
        border-radius: 10px;
        background-color: #181818;
    }

    /*定义滑块 内阴影+圆角*/
    ::-webkit-scrollbar-thumb {
        border-radius: 3px;
        -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
        background-color: #c7c7c7;
    }
</style>
<body>
<!--背景-->
<canvas style="position: fixed;"></canvas>

<!--底部版权信息-->
<div style="position: fixed; bottom: 10px;width: 100%;text-align: center;-moz-user-select: none; -khtml-user-select: none; user-select: none;">
        <span style="color: #666666;font-size:0.5em"> &copy; All rights reserved by
            <a href="javascript:void(0)" onclick="authors()" style="color: #0082ff;text-decoration: none;"
               title="查看作者">微信号:onlyoneshun</a>
        </span>
</div>
<script>
    window.onload = function () {
        //背景
        const CANVAS = document.getElementsByTagName("canvas")[0];
        const CTX = CANVAS.getContext("2d");
        const CHARS = [];
        const MAX_CHARS = 400;
        const SEPARATION = 2;
        let ww, wh, camera;

        class Vector {
            constructor(x, y, z) {
                this.x = x;
                this.y = y;
                this.z = z;
            }

            rotate(dir, ang) {
                const X = this.x;
                const Y = this.y;
                const Z = this.z;

                const SIN = Math.sin(ang);
                const COS = Math.cos(ang);

                if (dir === "x") {
                    this.y = Y * COS - Z * SIN;
                    this.z = Y * SIN + Z * COS;
                } else if (dir === "y") {
                    this.x = X * COS - Z * SIN;
                    this.z = X * SIN + Z * COS;
                }
            }

            project() {
                const ZP = this.z + camera.z;
                const DIV = ZP / 600;
                const XP = (this.x + camera.x) / DIV;
                const YP = (this.y + camera.y) / DIV;
                const CENTER = getCenter();
                return [XP + CENTER[0], YP + CENTER[1], ZP];
            }
        }

        class Char {
            constructor(letter, pos) {
                this.letter = letter;
                this.pos = pos;
            }

            rotate(dir, ang) {
                this.pos.rotate(dir, ang);
            }

            render() {
                const PIXEL = this.pos.project();
                const XP = PIXEL[0];
                const YP = PIXEL[1];
                const MAX_SIZE = 50;
                const SIZE = (1 / PIXEL[2] * MAX_SIZE) | 0;
                const BRIGHTNESS = SIZE / MAX_SIZE;
                const COL = `rgba(255, 255, ${100 * BRIGHTNESS | 0 + 150}, ${BRIGHTNESS})`;

                CTX.beginPath();
                CTX.fillStyle = COL;
                CTX.font = SIZE + "px monospace";
                CTX.fillText(this.letter, XP, YP);
                CTX.fill();
                CTX.closePath();
            }
        }

        function getCenter() {
            return [ww / 2, wh / 2];
        }

        function signedRandom() {
            return Math.random() - Math.random();
        }

        function render() {
            for (let i = 0; i < CHARS.length; i++) {
                CHARS[i].render();
            }
        }

        let time = 0;

        function update() {
            CTX.clearRect(0, 0, ww, wh);
            for (let i = 0; i < CHARS.length; i++) {
                const DX = 0.005 * Math.sin(time * 0.001);
                const DY = 0.005 * Math.cos(time * 0.001);
                CHARS[i].rotate("x", DX);
                CHARS[i].rotate("y", DY);
            }
            ++time;
        }

        function loop() {
            window.requestAnimationFrame(loop);
            update();
            render();
        }

        function getRandomInt(min, max) {
            return Math.floor(Math.random() * (max - min + 1)) + min;
        };

        function createChars() {
            for (let i = 0; i < MAX_CHARS; i++) {
                const CHARACTER = String.fromCharCode((Math.random() * 93 + 34) | 0);
                const X = signedRandom() * SEPARATION;
                const Y = signedRandom() * SEPARATION;
                const Z = signedRandom() * SEPARATION;
                const POS = new Vector(X, Y, Z);
                const CHAR = new Char(CHARACTER, POS);
                CHARS.push(CHAR);
            }
        }

        function setDim() {
            ww = window.innerWidth;
            wh = window.innerHeight;
            CANVAS.width = ww;
            CANVAS.height = wh;
        }

        function initCamera() {
            camera = new Vector(0, 0, SEPARATION + 1);
        }

        window.onresize = setDim;
        (() => {
            setDim();
            initCamera();
            createChars();
            loop();
        })();
    }
</script>
</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/146165.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据分析之数据相关性分析

相关性分析 作者&#xff1a;学者科技 时间&#xff1a;2022/12/25 应用场景 发现数据之间的关联性 比如 啤酒 和 尿布 删减统计指标 比如 城市里的温度传感器&#xff0c;相关性强的可以去掉以节约成本 挑选回归建模的变量 选择与因变量相关性高的自变量自变量间如果有高度…

数字漫画行业繁花似锦,国漫扎根本土文化“向外生长”?

2022年&#xff0c;一半是寒冰&#xff0c;一半是烈火。这一年&#xff0c;我们遇到了消费互联网的降温&#xff0c;包括互联网大厂降本增效潮到来&#xff0c;电商大促节不再公布销售额。同样&#xff0c;我们也见证了经济迸发的新活力&#xff0c;比如元宇宙、虚拟人掀起的热…

配置Domino解决CORS跨域问题

大家好&#xff0c;才是真的好。 前面我们讲过几篇Web应用开发的简单示例&#xff0c;主要功能是同一个站点的同一个应用里里面查看和搜索文档。如果对数据进行操作&#xff0c;可能多少会遇到网页跨域访问问题。 跨域&#xff0c;简单来说&#xff0c;就是浏览器对javascrip…

【知识图谱导论-浙大】第二章:知识图谱的表示

前文&#xff1a; 【知识图谱导论-浙大】第一章&#xff1a;知识图谱概论 本节内容的视频讲解如下&#xff1a; 【知识图谱理论】&#xff08;浙大2022知识图谱课程&#xff09;第二讲-知识图谱的表示什么是知识表示 简而言之&#xff0c;知识表示&#xff08;Knowledge Rep…

【HTML】纯CSS居然能做出这种效果,一款宝藏网页分享(超详细讲解 | 附源码)

&#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读&#xff0c;同时任汉硕云&#xff08;广东&#xff09;科技有限公司ABAP开发顾问。在学习工作中&#xff0c;我通常使用偏后…

【ASP.NET】家乡网站设计作业「历史」「人文」「自然」「美食」「高中」

文章目录作业描述结果展示代码MasterPage.master(母版页)首页历史页人文页美食页景观页高中页完整资源链接上学期其中ASP.NET网站设计老师布置的作业&#xff0c;在此记录一下&#xff1b;作业描述 为自己的家乡设计一个网站&#xff1a; 要求&#xff1a; 1.网站主要是展示和…

TYPE-C和USB-C接口有什么区别?

USB-C接口全称为USB Type-C&#xff0c;属于USB 3.0下一代接口&#xff0c;其亮点在于更加纤薄的设计、更快的传输速度&#xff08;最高可达10Gbps&#xff09;、更强的电力传输&#xff08;最高100W&#xff09;&#xff0c;此外USB-C接口还支持双面插入&#xff0c;正反面随便…

【NCC】之三:FFT(DFT)加速协方差的计算

FFT加速计算两个图的协方差文章目录<center> FFT加速计算两个图的协方差1. 傅里叶变换和卷积1.1 卷积定理1.2 空域卷积和频域乘积的复杂度2. opencv中的DFT3. FFT用于NCC4. 测试结果部分代码1. 傅里叶变换和卷积 1.1 卷积定理 图片来源 在空域上的卷积就是上面的动图所展…

再学C语言27:输入和输出——缓冲区

I/O函数&#xff1a;输入/输出函数 I/O函数将信息传输至程序并从程序中传出信息&#xff0c;如printf()、scanf()、getchar()、putchar()等函数 getchar()和putchar()每次输入/输出一个字符 示例代码&#xff1a; #include <stdio.h> int main(void) {char c;// 输入回…

Vivado综合设置之-resource_sharing

-​resource_sharing用于对算数运算&#xff08;加法、减法和乘法&#xff09;实现资源共享&#xff0c;以节约LUT资源&#xff0c;有3个值&#xff1a;auto、off和on&#xff0c;默认是auto。 默认情况下&#xff0c;将resource_sharing设置为auto即可。 本文验证-resource_…

[Leetcode] 将二叉搜索树变平衡

将二叉搜索树变平衡&#xff1a;https://leetcode.cn/problems/balance-a-binary-search-tree/给你一棵二叉搜索树&#xff0c;请你返回一棵 平衡后的二叉搜索树&#xff0c;新生成的树应该与原来的树有着相同的节点值。如果有多种构造方法&#xff0c;请你返回任意一种。如果一…

Codeforces Round #842 (Div. 2)-C. Elemental Decompress

题目&#xff1a; 题目大意&#xff1a; 给定一个数列t&#xff0c;你构造两个数列a和b&#xff0c;使得max(a[i],b[i])t[i] 核心思想&#xff1a; 1、先根据给出的数组进行放置&#xff0c;优先放到a数组中&#xff0c;如果这个数已经在a数组中出现了&#xff0c;再去放到b数…

sentinel的使用

一、sentinel控制台的使用1、sentinel控制台jar包地址&#xff1a;Releases alibaba/Sentinel GitHub账号密码都为sentinel控制台访问地址&#xff1a;http://localhost:80802、sentinel的maven坐标<dependency><groupId>com.alibaba.cloud</groupId><a…

Android基础入门教程——2.2 LinearLayout(线性布局)

总结图片2. weight权重白色占总数量的2份&#xff0c;绿色占总数的1份。<?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.co…

树莓派最新版系统烧写和网络配置

树莓派笔记1.树莓派烧写篇2.树莓派WIFI配置篇3.树莓派ping外网4.树莓派git篇5.参考1.树莓派烧写篇 目前烧写最新版本32位系统(2022-09-22发布的)&#xff0c;默认移除了pi用户&#xff0c;没有用户就无法SSH登录(无屏幕)&#xff0c;建议使用raspberry pi imager烧写工具&…

通过USB转TTL串口下载stm32程序

文章目录前言一、硬件及其接线二、使用步骤1.主芯片STM32F103C8T6开发板2.转串口模块接线3.CH340驱动及安装方法4.CH340驱动及安装方法4.下载测试5.0.91寸OLED 接口演示例程前言 前期我们下载程序都是使用STlink进行下载的&#xff0c;现在给大家提供一种新的程序下载方法&…

5G小基站国产化超五成,美国芯片仅占1%,难怪美国芯片难卖了

日前日媒拆解中国某科技企业的5G小基站&#xff0c;发现它的中国零部件占比达到55%&#xff0c;而来自美国的零部件占比仅为1%&#xff0c;显示出这家企业在去美化取得了重大进展&#xff0c;如此也就能理解为何如今美国芯片难卖了。日媒指出该科技企业的5G小基站国产化零部件占…

动态规划 完全背包问题

目录 LintCode 炼码完全背包问题 【解法一】 【解法二】 完全背包问题 【解法一】 解释&#xff1a; 第一个for循环表示从第一个物品开始遍历 第二个for循环表示逆向 从背包容量为m时开始处理&#xff08;滚动数组&#xff09; 第三个for循环表示装入k个该物品&#xff0c;装…

【前端】Vue项目:旅游App-(9)city:固定tab栏、内容中显示数据

文章目录目标过程与代码Tab一直显示的两种方法方法1&#xff1a;fixed定位方法2&#xff1a;设置height和overflow-y&#xff08;效果不好&#xff09;content显示数据效果总代码city.vue相关参考目标 上一篇获取了服务器中的数据&#xff1a;【前端】Vue项目&#xff1a;旅游…

【数据结构】完全二叉树——啊堆堆堆

一、树概念及结构树的概念树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n > 0&#xff09;个有限节点组成的一个具有层次关系的集合。把它叫做树是因为他看起来像是一颗倒挂起来的树&#xff0c;也就是说它是根朝上&#xff0c;而叶子朝下的。-> 有一个特殊的…