openfree commited on
Commit
6618e95
Β·
verified Β·
1 Parent(s): df6a4c8

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +92 -106
index.html CHANGED
@@ -3,131 +3,117 @@
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Pulsar Mini – Touch Reactive</title>
7
-
8
- <!-- Tailwind CDN: ν”„λ‘œν† νƒ€μž…μš©, ν•„μš” μ‹œ 둜컬 λΉŒλ“œλ‘œ ꡐ체 -->
9
  <script src="https://cdn.tailwindcss.com"></script>
10
  <style>
11
- body {
12
- @apply bg-gray-900 text-gray-100 flex flex-col items-center justify-center min-h-screen gap-6 p-4 select-none;
13
- }
14
- canvas {
15
- image-rendering: pixelated;
16
- @apply border border-gray-700 rounded shadow-lg;
17
- }
18
  </style>
19
  </head>
20
  <body>
21
- <h1 class="text-3xl font-bold mb-2">Pulsar Mini</h1>
22
- <p class="text-sm text-gray-400 mb-4 text-center">μΊ”λ²„μŠ€λ₯Ό νƒ­ν•˜κ±°λ‚˜ 클릭할 λ•Œλ§ˆλ‹€ μƒˆλ‘œμš΄ λ¬΄μž‘μœ„ νŒ¨ν„΄μ΄ μž¬μƒλ©λ‹ˆλ‹€.</p>
23
-
24
  <canvas id="canvas"></canvas>
25
 
26
- <div class="flex gap-3">
27
- <button id="play" class="px-4 py-1.5 rounded bg-green-600 text-sm">β–Ά μž¬μƒ</button>
28
- <button id="pause" class="px-4 py-1.5 rounded bg-red-600 text-sm hidden">❚❚ μΌμ‹œμ •μ§€</button>
29
- <button id="random" class="px-4 py-1.5 rounded bg-blue-600 text-sm">🎲 랜덀</button>
 
30
  </div>
31
 
32
- <script>
33
- const DPR = window.devicePixelRatio || 1;
34
- const canvas = document.getElementById('canvas');
35
- const ctx = canvas.getContext('2d');
36
- const playBtn = document.getElementById('play');
37
- const pauseBtn = document.getElementById('pause');
38
- const rndBtn = document.getElementById('random');
39
 
40
- // 10κ°€μ§€ 예제 + λ§€ ν˜ΈμΆœλ§ˆλ‹€ λ§€κ°œλ³€μˆ˜λ₯Ό 랜덀으둜 μ„žμŒ
41
- const BASE_PATTERNS = [
42
- '(x,y,t)=>Math.sin((x+y+t)*$FREQ)',
43
- '(x,y,t)=>Math.cos((x-y+t)*$FREQ)',
44
- '(x,y,t)=>Math.sin(Math.hypot(x-0.5,y-0.5)*$FREQ - t*3)',
45
- '(x,y,t)=>Math.sin(x*$FREQ+t)+Math.cos(y*$FREQ+t)',
46
- '(x,y,t)=>Math.sin((x*$FREQ+y*$FREQ+t*2))*Math.cos((x*$FREQ-y*$FREQ+t))',
47
- '(x,y,t)=>Math.sin((x+y)*$FREQ + t*5)*0.5+0.5',
48
- '(x,y,t)=>Math.sin(Math.atan2(y-0.5,x-0.5)*$FREQ + t*2)',
49
- '(x,y,t)=>((Math.sin(x*$FREQ)+Math.cos(y*$FREQ+t))*0.5)+0.5',
50
- '(x,y,t)=>Math.sin(((x-0.5)**2+(y-0.5)**2)*$FREQ - t*4)',
51
- '(x,y,t)=>Math.sin((x*x - y*y)*$FREQ + t*3)'
52
- ];
 
 
 
 
53
 
54
- function pickRandomFormula() {
55
- const tmpl = BASE_PATTERNS[Math.floor(Math.random()*BASE_PATTERNS.length)];
56
- const freq = (Math.random()*30 + 10).toFixed(1); // 10~40 사이 주파수
57
- return tmpl.replaceAll('$FREQ', freq);
58
- }
 
 
 
 
 
 
59
 
60
- let formulaSrc = pickRandomFormula();
61
- let fn = compile(formulaSrc);
62
- let playing = true;
63
- let start = performance.now();
64
 
65
- function resizeCanvas() {
66
- const size = Math.min(window.innerWidth, window.innerHeight) * 0.8;
67
- canvas.style.width = size + 'px';
68
- canvas.style.height = size + 'px';
69
- canvas.width = size * DPR;
70
- canvas.height = size * DPR;
71
- ctx.scale(DPR, DPR);
72
- }
73
- resizeCanvas();
74
- window.addEventListener('resize', resizeCanvas);
75
 
76
- function compile(src) {
77
- try {
78
- return eval(src);
79
- } catch (e) {
80
- console.error(e);
81
- return () => 0;
82
- }
83
- }
84
 
85
- function draw(time) {
86
- const t = (time - start) / 1000;
87
- const w = canvas.width / DPR;
88
- const h = canvas.height / DPR;
89
 
90
- const img = ctx.createImageData(w, h);
91
- const data = img.data;
92
- let i = 0;
93
- for (let y = 0; y < h; y++) {
94
- for (let x = 0; x < w; x++) {
95
- const v = Math.max(0, Math.min(1, fn(x / w, y / h, t, i)));
96
- const c = v * 255;
97
- data[i++] = c; // R
98
- data[i++] = c; // G
99
- data[i++] = c; // B
100
- data[i++] = 255; // A
101
- }
 
 
 
 
 
102
  }
103
- ctx.putImageData(img, 0, 0);
104
- if (playing) requestAnimationFrame(draw);
105
  }
106
- requestAnimationFrame(draw);
107
-
108
- function randomize() {
109
- formulaSrc = pickRandomFormula();
110
- fn = compile(formulaSrc);
111
- start = performance.now();
112
- }
113
-
114
- // λ²„νŠΌ 이벀트
115
- playBtn.addEventListener('click', () => {
116
- playing = true;
117
- playBtn.classList.add('hidden');
118
- pauseBtn.classList.remove('hidden');
119
- start = performance.now();
120
- requestAnimationFrame(draw);
121
- });
122
 
123
- pauseBtn.addEventListener('click', () => {
124
- playing = false;
125
- pauseBtn.classList.add('hidden');
126
- playBtn.classList.remove('hidden');
127
- });
128
 
129
- rndBtn.addEventListener('click', randomize);
130
- canvas.addEventListener('pointerdown', randomize); // ν„°μΉ˜Β·ν΄λ¦­ λͺ¨λ‘ λŒ€μ‘
131
- </script>
 
 
 
132
  </body>
133
  </html>
 
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Pulsar Mini – ν’€μŠ€ν¬λ¦° 컬러</title>
 
 
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <style>
9
+ /* κΈ°λ³Έ λ ˆμ΄μ•„μ›ƒ */
10
+ body {@apply m-0 overflow-hidden bg-black text-gray-200 font-sans;}
11
+ canvas {width:100vw;height:100vh;display:block;image-rendering:pixelated;cursor:crosshair;}
12
+ /* μ˜€λ²„λ ˆμ΄ UI */
13
+ #ui {@apply absolute top-3 left-1/2 -translate-x-1/2 flex gap-2 z-50 select-none;}
14
+ #ui button {@apply px-4 py-1.5 rounded text-sm font-semibold shadow bg-gray-800/70 backdrop-blur hover:bg-gray-700;}
 
15
  </style>
16
  </head>
17
  <body>
18
+ <!-- ν’€μŠ€ν¬λ¦° μΊ”λ²„μŠ€ -->
 
 
19
  <canvas id="canvas"></canvas>
20
 
21
+ <!-- UI μ˜€λ²„λ ˆμ΄ -->
22
+ <div id="ui">
23
+ <button id="play">β–Ά μž¬μƒ</button>
24
+ <button id="pause" class="hidden">❚❚ μΌμ‹œμ •μ§€</button>
25
+ <button id="random">🎲 랜덀</button>
26
  </div>
27
 
28
+ <script>
29
+ const DPR = window.devicePixelRatio || 1;
30
+ const canvas = document.getElementById('canvas');
31
+ const ctx = canvas.getContext('2d');
32
+ const playBtn = document.getElementById('play');
33
+ const pauseBtn = document.getElementById('pause');
34
+ const rndBtn = document.getElementById('random');
35
 
36
+ // λ‹€μ–‘ν•œ μˆ˜ν•™ 곡식을 ν™œμš©ν•œ 컬러 νŒ¨ν„΄ ν…œν”Œλ¦Ώ (R,G,B 각각의 식)
37
+ const BASE_PATTERNS = [
38
+ // 1. 사인/코사인 격자
39
+ '(x,y,t)=>{const r=Math.sin((x+$S1)*$F1+t);const g=Math.sin((y+$S2)*$F2-t);const b=Math.cos((x+y)*$F3+t*0.5);return[(r+1)/2,(g+1)/2,(b+1)/2];}',
40
+ // 2. μ›ν˜• νŒŒλ™
41
+ '(x,y,t)=>{const d=Math.hypot(x-0.5,y-0.5);return[0.5+0.5*Math.sin(d*$F1-t*2),0.5+0.5*Math.cos(d*$F2+t),0.5+0.5*Math.sin((x-y)*$F3+t)];}',
42
+ // 3. λ³΅μ†Œν•¨μˆ˜ 기반 νŒ¨ν„΄
43
+ '(x,y,t)=>{return[0.5+0.5*Math.sin((x*x-y*y)*$F1+t),0.5+0.5*Math.cos((x*y)*$F2-t),0.5+0.5*Math.sin((x+y)*$F3)];}',
44
+ // 4. μ ˆλŒ€κ°’ 사인 – 밝고 μ„ λͺ…ν•œ 색
45
+ '(x,y,t)=>{return[Math.abs(Math.sin($F1*x+t)),Math.abs(Math.sin($F2*y-t)),Math.abs(Math.sin(($F3)*(x+y)+t*0.3))];}',
46
+ // 5. κ·Ήμ’Œν‘œ λ¬΄μ§€κ°œ
47
+ '(x,y,t)=>{const a=Math.atan2(y-0.5,x-0.5);const r=(a/Math.PI+1)/2;return[r,0.5+0.5*Math.sin(t+$F1*r*10),1-r];}',
48
+ // 6. 둜즈(μž₯λ―Έ) 컀브 기반
49
+ '(x,y,t)=>{const a=Math.atan2(y-0.5,x-0.5);const k=$K;return[0.5+0.5*Math.sin(k*a+t),0.5+0.5*Math.sin(k*a+t+2*Math.PI/3),0.5+0.5*Math.sin(k*a+t+4*Math.PI/3)];}',
50
+ // 7. 페λ₯΄λ§ˆ λ‚˜μ„  λ…Έμ΄μ¦ˆ
51
+ '(x,y,t)=>{const r=Math.hypot(x-0.5,y-0.5);const phi=r*10+$F1;return[0.5+0.5*Math.sin(phi+t),0.5+0.5*Math.cos(phi*1.3-t),0.5+0.5*Math.sin(phi*0.7+t*0.5)];}',
52
+ ];
53
 
54
+ function rand(min,max){return Math.random()*(max-min)+min;}
55
+ function pickRandomFormula(){
56
+ const tmpl=BASE_PATTERNS[Math.floor(Math.random()*BASE_PATTERNS.length)];
57
+ return tmpl
58
+ .replaceAll('$F1',rand(5,30).toFixed(2))
59
+ .replaceAll('$F2',rand(5,30).toFixed(2))
60
+ .replaceAll('$F3',rand(5,30).toFixed(2))
61
+ .replaceAll('$S1',Math.random().toFixed(2))
62
+ .replaceAll('$S2',Math.random().toFixed(2))
63
+ .replaceAll('$K',Math.floor(rand(3,9))); // μ •μˆ˜ κ½ƒμžŽ 수
64
+ }
65
 
66
+ let formulaSrc = pickRandomFormula();
67
+ let fn = compile(formulaSrc);
68
+ let playing = true;
69
+ let start = performance.now();
70
 
71
+ function resizeCanvas(){
72
+ canvas.width = window.innerWidth * DPR;
73
+ canvas.height = window.innerHeight * DPR;
74
+ ctx.setTransform(DPR,0,0,DPR,0,0);
75
+ }
76
+ resizeCanvas();
77
+ window.addEventListener('resize',resizeCanvas);
 
 
 
78
 
79
+ function compile(src){
80
+ try{ return eval(src); }
81
+ catch(e){ console.error(e); return ()=>[0,0,0]; }
82
+ }
 
 
 
 
83
 
84
+ function clamp01(v){ return v<0?0:v>1?1:v; }
 
 
 
85
 
86
+ function draw(time){
87
+ const t = (time - start)/1000;
88
+ const w = canvas.width/DPR;
89
+ const h = canvas.height/DPR;
90
+ const img = ctx.createImageData(w,h);
91
+ const data = img.data;
92
+ let idx=0;
93
+ for(let y=0;y<h;y++){
94
+ for(let x=0;x<w;x++){
95
+ const c = fn(x/w,y/h,t,idx);
96
+ const r = clamp01(c[0])*255;
97
+ const g = clamp01(c[1])*255;
98
+ const b = clamp01(c[2])*255;
99
+ data[idx++] = r;
100
+ data[idx++] = g;
101
+ data[idx++] = b;
102
+ data[idx++] = 255;
103
  }
 
 
104
  }
105
+ ctx.putImageData(img,0,0);
106
+ if(playing) requestAnimationFrame(draw);
107
+ }
108
+ requestAnimationFrame(draw);
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
+ function randomize(){ formulaSrc = pickRandomFormula(); fn = compile(formulaSrc); start = performance.now(); }
 
 
 
 
111
 
112
+ // UI 이벀트
113
+ playBtn.addEventListener('click',()=>{playing=true;playBtn.classList.add('hidden');pauseBtn.classList.remove('hidden');start=performance.now();requestAnimationFrame(draw);} );
114
+ pauseBtn.addEventListener('click',()=>{playing=false;pauseBtn.classList.add('hidden');playBtn.classList.remove('hidden');});
115
+ rndBtn.addEventListener('click',randomize);
116
+ canvas.addEventListener('pointerdown',randomize);
117
+ </script>
118
  </body>
119
  </html>