Pulsar-Display / index.html
openfree's picture
Update index.html
9d4c549 verified
raw
history blame
3.54 kB
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Pulsar Mini</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Tailwind CDN (λΉ λ₯Έ ν”„λ‘œν† νƒ€μ΄ν•‘μš©) -->
<script src="https://cdn.tailwindcss.com"></script>
<style>
/* custom utility μ‘°ν•© */
body { @apply bg-gray-900 text-gray-100 flex flex-col items-center py-6 gap-6; }
canvas { image-rendering: pixelated; }
</style>
</head>
<body>
<h1 class="text-3xl font-bold">Pulsar Mini</h1>
<div class="flex flex-wrap gap-4 max-w-4xl w-full justify-center">
<!-- Canvas μ˜μ—­ -->
<canvas id="canvas" width="320" height="320" class="border border-gray-700 rounded"></canvas>
<!-- 컨트둀 -->
<div class="flex flex-col gap-3 w-80">
<label class="text-sm font-mono">μ½”λ“œ:</label>
<textarea
id="code"
rows="4"
maxlength="300"
class="w-full p-2 rounded bg-gray-800 font-mono text-xs resize-none outline-none"
>(x,y,t)=>Math.sin(x*10+t)+Math.cos(y*10+t)</textarea>
<div class="flex gap-2">
<button id="play" class="px-3 py-1 rounded bg-green-600 text-sm">β–Ά Play</button>
<button id="pause" class="px-3 py-1 rounded bg-red-600 text-sm hidden">❚❚ Pause</button>
<button id="random" class="px-3 py-1 rounded bg-blue-600 text-sm">🎲 Random</button>
</div>
<p class="text-[11px] text-gray-400 leading-snug">
ν•¨μˆ˜λŠ” <code>(x,y,t,i) =&gt; κ°’</code> ν˜•μ‹μ΄μ–΄μ•Ό ν•©λ‹ˆλ‹€.<br>
<code>x</code>, <code>y</code> λŠ” 0~1 μ’Œν‘œ, <code>t</code> λŠ” 초, <code>i</code>λŠ” ν”½μ…€ μΈλ±μŠ€μž…λ‹ˆλ‹€.<br>
λ°˜ν™˜κ°’μ€ 0~1 λ²”μœ„λ‘œ ν΄λž¨ν”„λ˜μ–΄ κ·Έλ ˆμ΄μŠ€μΌ€μΌ 밝기둜 ν‘œν˜„λ©λ‹ˆλ‹€.
</p>
</div>
</div>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const codeEl = document.getElementById('code');
const playBtn = document.getElementById('play');
const pauseBtn= document.getElementById('pause');
const rndBtn = document.getElementById('random');
const EXAMPLES = [
'(x,y,t)=>Math.sin((x+y+t)*6)',
'(x,y,t)=>Math.sin(x*10+t)+Math.cos(y*10+t)',
'(x,y,t)=>Math.sin(Math.hypot(x-0.5,y-0.5)*20-t*2)',
];
let fn = compile(codeEl.value);
let playing = false;
let start = performance.now();
function compile(src){
try { return eval(src); }
catch(e){ console.error(e); return ()=>0; }
}
function draw(time){
const t = (time - start) / 1000;
const w = canvas.width;
const h = canvas.height;
const img = ctx.getImageData(0,0,w,h);
const data = img.data;
for(let y=0; y<h; y++){
for(let x=0; x<w; x++){
const idx = (y*w + x) * 4;
const v = Math.max(0, Math.min(1, fn(x/w, y/h, t, idx)));
const c = v * 255;
data[idx] = data[idx+1] = data[idx+2] = c;
data[idx+3] = 255;
}
}
ctx.putImageData(img,0,0);
if(playing) requestAnimationFrame(draw);
}
draw(start);
// event handlers
playBtn.addEventListener('click', () => {
playing = true;
playBtn.classList.add('hidden');
pauseBtn.classList.remove('hidden');
requestAnimationFrame(draw);
});
pauseBtn.addEventListener('click', () => {
playing = false;
pauseBtn.classList.add('hidden');
playBtn.classList.remove('hidden');
});
codeEl.addEventListener('input', () => {
fn = compile(codeEl.value);
});
rndBtn.addEventListener('click', () => {
codeEl.value = EXAMPLES[Math.floor(Math.random()*EXAMPLES.length)];
fn = compile(codeEl.value);
});
</script>
</body>
</html>