演示
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" > © 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" > © 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>