firobeid's picture
Upload index.html
31ae020 verified
<style>
.wave-wrap { font-family: var(--font-sans); padding: 0.5rem 0 1rem; }
.wave-controls { display: flex; gap: 20px; flex-wrap: wrap; align-items: center; margin-bottom: 12px; }
.wave-label { font-size: 12px; color: var(--color-text-secondary); min-width: 120px; }
.wave-val { font-size: 12px; font-weight: 500; color: var(--color-text-primary); min-width: 28px; }
.panel-row { display: flex; gap: 12px; }
.panel { flex: 1; background: var(--color-background-secondary); border-radius: 8px; padding: 10px 12px; }
.panel-head { font-size: 12px; font-weight: 500; color: var(--color-text-primary); margin-bottom: 6px; }
.panel-note { font-size: 11px; color: var(--color-text-secondary); margin-top: 4px; }
</style>
<div class="wave-wrap">
<div class="wave-controls">
<div style="display:flex;align-items:center;gap:8px">
<span class="wave-label" style="color:#1D9E75;font-weight:500">pos (word index)</span>
<input type="range" min="0" max="49" value="10" id="sl-pos" style="width:120px" oninput="update()">
<span class="wave-val" id="lbl-pos">10</span>
</div>
<div style="display:flex;align-items:center;gap:8px">
<span class="wave-label" style="color:#BA7517;font-weight:500">highlight dim i</span>
<input type="range" min="0" max="255" value="0" id="sl-dim" style="width:120px" oninput="update()">
<span class="wave-val" id="lbl-dim">0</span>
</div>
</div>
<div class="panel-row" style="margin-bottom:10px">
<div class="panel">
<div class="panel-head">Looking <em>across</em> one row → (horizontal slice at selected pos)</div>
<canvas id="hcv" style="width:100%;display:block"></canvas>
<div class="panel-note" id="hnote"></div>
</div>
<div class="panel">
<div class="panel-head">Looking <em>down</em> one column ↓ (vertical slice at selected dim i)</div>
<canvas id="vcv" style="width:100%;display:block"></canvas>
<div class="panel-note" id="vnote"></div>
</div>
</div>
</div>
<script>
const ROWS=50, COLS=256, D=512;
function pe(pos,i){
const d=Math.pow(10000,(2*Math.floor(i/2))/D);
return (i%2===0)?Math.sin(pos/d):Math.cos(pos/d);
}
const isDark = matchMedia('(prefers-color-scheme: dark)').matches;
const teal = '#1D9E75', amber = '#BA7517';
const textCol = isDark ? 'rgba(200,198,190,0.9)' : 'rgba(60,60,58,0.9)';
const gridCol = isDark ? 'rgba(255,255,255,0.07)' : 'rgba(0,0,0,0.07)';
function drawLine(cvs, data, color, hlIdx, xLabel, showFreq) {
const dpr = window.devicePixelRatio||1;
const w = cvs.offsetWidth||300;
const h = 110;
cvs.width = w*dpr; cvs.height = h*dpr;
cvs.style.height = h+'px';
const ctx = cvs.getContext('2d');
ctx.scale(dpr, dpr);
const pad = {l:6, r:6, t:10, b:20};
const pw = w - pad.l - pad.r;
const ph = h - pad.t - pad.b;
const n = data.length;
ctx.clearRect(0,0,w,h);
// grid
ctx.strokeStyle = gridCol; ctx.lineWidth = 0.5;
[0.25, 0.5, 0.75].forEach(f => {
const y = pad.t + f*ph;
ctx.beginPath(); ctx.moveTo(pad.l, y); ctx.lineTo(pad.l+pw, y); ctx.stroke();
});
// zero line
ctx.strokeStyle = isDark ? 'rgba(255,255,255,0.18)' : 'rgba(0,0,0,0.18)';
ctx.lineWidth = 1;
ctx.beginPath(); ctx.moveTo(pad.l, pad.t+ph/2); ctx.lineTo(pad.l+pw, pad.t+ph/2); ctx.stroke();
// data path
ctx.strokeStyle = color; ctx.lineWidth = 1.5; ctx.lineJoin = 'round';
ctx.beginPath();
data.forEach((v, i) => {
const x = pad.l + (i/(n-1))*pw;
const y = pad.t + (1-(v+1)/2)*ph;
i===0 ? ctx.moveTo(x,y) : ctx.lineTo(x,y);
});
ctx.stroke();
// highlight dot
if (hlIdx >= 0 && hlIdx < n) {
const x = pad.l + (hlIdx/(n-1))*pw;
const y = pad.t + (1-(data[hlIdx]+1)/2)*ph;
ctx.fillStyle = amber;
ctx.beginPath(); ctx.arc(x,y,4,0,Math.PI*2); ctx.fill();
// value label
ctx.fillStyle = amber;
ctx.font = `500 11px var(--font-sans)`;
ctx.textAlign = 'center';
ctx.fillText(data[hlIdx].toFixed(3), Math.min(Math.max(x,30),pw-20), y > pad.t+12 ? y-7 : y+14);
}
// x-axis ticks
ctx.fillStyle = textCol; ctx.font = `10px var(--font-sans)`;
ctx.textAlign = 'center';
[0, Math.floor(n/2), n-1].forEach(i => {
const x = pad.l + (i/(n-1))*pw;
ctx.fillText(xLabel(i), x, h-4);
});
// y labels
ctx.textAlign = 'right';
ctx.fillText('+1', pad.l-1, pad.t+5);
ctx.fillText('−1', pad.l-1, pad.t+ph+4);
}
function update() {
const pos = +document.getElementById('sl-pos').value;
const dim = +document.getElementById('sl-dim').value;
document.getElementById('lbl-pos').textContent = pos;
document.getElementById('lbl-dim').textContent = dim;
// horizontal: values across dims for fixed pos
const hdata = Array.from({length:COLS}, (_,i) => pe(pos,i));
drawLine(document.getElementById('hcv'), hdata, teal, dim, i => i===0?'i=0':i===127?'128':i===255?'255':'', true);
// vertical: values across positions for fixed dim
const vdata = Array.from({length:ROWS}, (_,r) => pe(r,dim));
drawLine(document.getElementById('vcv'), vdata, amber, pos, r => r===0?'pos=0':r===24?'24':r===49?'49':'', false);
// notes
const wl = (2*Math.PI*Math.pow(10000, dim/D)).toFixed(0);
const speed = dim < 20 ? '⚡ very fast' : dim < 80 ? '⚡ fast' : dim < 160 ? '~ moderate' : '🐢 slow';
document.getElementById('hnote').innerHTML = `Left = high-frequency oscillations. Right = nearly flat. Highlighted dot at <b>i=${dim}</b> = ${hdata[dim].toFixed(3)}.`;
document.getElementById('vnote').innerHTML = `Dimension i=${dim} (${speed}, wavelength≈${wl}). Highlighted dot at <b>pos=${pos}</b> = ${vdata[pos].toFixed(3)}.`;
}
setTimeout(update, 60);
window.addEventListener('resize', update);
</script>