<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>代码生成蒙娜丽莎</title>
<style>
html,
body {
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head>
<body>
<canvas id="c" />
<script>
const c = document.querySelector('#c');
const ctx = c.getContext('2d');
const ratio = window.innerHeight / window.innerWidth;
const width = window.innerWidth;
const height = window.innerHeight;
c.height = Math.max(900, window.innerHeight);
c.width = c.height / ratio;
c.style.width = '100vw';
c.style.height = '100vh';
function pseudoRandom(seed) {
return Math.sin(seed) * 10000 - Math.floor(Math.sin(seed) * 10000);
}
function noise(x, y) {
const seed = x * 137 + y * 149;
return pseudoRandom(seed) % 1;
}
const stepAngle = (Math.PI * 2) / 3;
const getThread = (i) => {
return {
lastPoint: {
x: c.width / 2 + Math.cos((Math.PI / 10) * i) * i * 3,
y: c.height / 2 + Math.sin((Math.PI / 10) * i) * i * 3,
},
angle: Math.PI / 3 + stepAngle * i,
};
};
const threads = [];
for (let i = 0; i < 256; i++) {
threads.push(getThread(i));
}
const palette = [
'#80FFDB',
'#72EFDD',
'#64DFDF',
'#56CFE1',
'#48BFE3',
'#4EA8DE',
'#5390D9',
'#5E60CE',
'#6930C3',
'#7400B8',
];
const monaLisa = `
_______
_,,ad8888888888bba,_
,ad88888I888888888888888ba,
,88888888I88888888888888888888a,
,d888888888I8888888888888888888888b,
d88888PP"""" ""YY88888888888888888888b,
,d88"'__,,--------,,,,.;ZZZY8888888888888,
,8IIl'" ;;l"ZZZIII8888888888,
,I88l;' ;lZZZZZ888III8888888,
,II88Zl;. ;llZZZZZ888888I888888,
,II888Zl;. .;;;;;lllZZZ888888I8888b
,II8888Z;; ';;;;;''llZZ8888888I8888,
II88888Z;' .;lZZZ8888888I888b
II88888Z; _,aaa, .,aaaaa,__.l;llZZZ88888888I888
II88888IZZZZZZZZZ, .ZZZZZZZZZZZZZZ;llZZ88888888I888,
II88888IZZ<'(@@>Z| |ZZZ<'(@@>ZZZZ;;llZZ888888888I88I
,II88888; '""" ;| |ZZ; '""" ;;llZ8888888888I888
II888888l ';; .;llZZ8888888888I888,
,II888888Z; ;;; .;;llZZZ8888888888I888I
III888888Zl; .., ';; ,;;lllZZZ88888888888I888
II88888888Z;;...;(_ _) ,;;;llZZZZ88888888888I888,
II88888888Zl;;;;;' '--'Z;. .,;;;;llZZZZ88888888888I888b
]I888888888Z;;;;' ";llllll;..;;;lllZZZZ88888888888I8888,
II888888888Zl.;;"Y88bd888P";;,..;lllZZZZZ88888888888I8888I
II8888888888Zl;.; '"PPP";;;,..;lllZZZZZZZ88888888888I88888
II888888888888Zl;;. ';;;l;;;;lllZZZZZZZZW88888888888I88888
'II8888888888888Zl;. ,;;lllZZZZZZZZWMZ88888888888I88888
II8888888888888888ZbaalllZZZZZZZZZWWMZZZ8888888888I888888,
'II88888888888888888b"WWZZZZZWWWMMZZZZZZI888888888I888888b
'II88888888888888888;ZZMMMMMMZZZZZZZZllI888888888I8888888
'II8888888888888888 ';lZZZZZZZZZZZlllll888888888I8888888,
II8888888888888888, ';lllZZZZllllll;;.Y88888888I8888888b,
,II8888888888888888b .;;lllllll;;;.;..88888888I88888888b,
II888888888888888PZI;. .';;;.;;;..; ...88888888I8888888888,
II888888888888PZ;;';;. ;. .;. .;. .. Y8888888I88888888888b,
,II888888888PZ;;' '8888888I8888888888888b,
II888888888' 888888I8888888888888888b
,II888888888 ,888888I88888888888888888
,d88888888888 d888888I8888888888ZZZZZZZ
,ad888888888888I 8888888I8888ZZZZZZZZZZZZZ
,d888888888888888' 888888IZZZZZZZZZZZZZZZZZZ
,d888888888888P'8P' Y888ZZZZZZZZZZZZZZZZZZZZZ
,8888888888888, " ,ZZZZZZZZZZZZZZZZZZZZZZZZ
d888888888888888, ,ZZZZZZZZZZZZZZZZZZZZZZZZZZZ
888888888888888888a, _ ,ZZZZZZZZZZZZZZZZZZZZ888888888
888888888888888888888ba,_d' ,ZZZZZZZZZZZZZZZZZ88888888888888
8888888888888888888888888888bbbaaa,,,______,ZZZZZZZZZZZZZZZ888888888888888888
88888888888888888888888888888888888888888ZZZZZZZZZZZZZZZ888888888888888888888
8888888888888888888888888888888888888888ZZZZZZZZZZZZZZ88888888888888888888888
888888888888888888888888888888888888888ZZZZZZZZZZZZZZ888888888888888888888888
8888888888888888888888888888888888888ZZZZZZZZZZZZZZ88888888888888888888888888
88888888888888888888888888888888888ZZZZZZZZZZZZZZ8888888888888888888888888888
8888888888888888888888888888888888ZZZZZZZZZZZZZZ88888888888888888888888888888
88888888888888888888888888888888ZZZZZZZZZZZZZZ8888888888888888888888888888888
8888888888888888888888888888888ZZZZZZZZZZZZZZ88888888888888888888888888888888
`
.split('\n')
.slice(1);
const symbols = ` .-'":_,^=;><+!rc*/z?sLTv)J7(|Fi{C}fI31tlu[neoZ5Yxjya]2ESwqkP6h9d4VpPOGbUAKXHm8RD#$Bg0MNWQ%&@`;
ctx.fillStyle = 'rgba(0, 0, 0, 1)';
ctx.fillRect(0, 0, c.width, c.height);
const animate = (time) => {
requestAnimationFrame(animate);
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, c.width, c.height);
ctx.lineWidth = 1;
let prevColor = '#000000';
for (let y = 1; y < monaLisa.length; y++) {
for (let x = 0; x < 76; x++) {
const padding = (c.width - 760) / 2;
const letter = monaLisa[y][x] ?? ' ';
const level = 1.256 - symbols.indexOf(letter) / symbols.length;
const size = 20;
ctx.beginPath();
const colors = [65, 85, 105, 125, 145, 165];
const e =
Math.cos((x + time / 10000) * 10) +
Math.sin((y + time / 10000) * 10);
const deg = 220 + colors[Math.floor(e * colors.length)];
ctx.arc(padding + x * 10, y * 20, level * 5, 0, Math.PI * 2);
ctx.fillStyle = `hsl(${deg}deg, 60%, ${20 + level * 40}%)`;
ctx.fill();
prevColor = ctx.fillStyle;
}
}
};
animate(0);
</script>
</body>
</html>