diff options
Diffstat (limited to 'docs/prototypes')
| -rw-r--r-- | docs/prototypes/panel-widget-gallery.html | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/docs/prototypes/panel-widget-gallery.html b/docs/prototypes/panel-widget-gallery.html index ac2af6a..815fc3c 100644 --- a/docs/prototypes/panel-widget-gallery.html +++ b/docs/prototypes/panel-widget-gallery.html @@ -879,6 +879,9 @@ card(I,'R11','Warning flag window', card(I,'R25','Fourteen-segment display', `<svg id="seg14" class="rsvg press" viewBox="0 0 130 54" width="130" height="54"></svg>`, '<b>segments that spell.</b> The starburst alphanumeric — diagonals and split bars let it write words, not just digits. Click to cycle the word. After a pedal preset display.'); +card(I,'R26','Response graph', + `<svg id="rgraph" class="rsvg" viewBox="0 0 190 110" width="190" height="110"></svg>`, + '<b>a curve on labeled axes.</b> Log frequency across, dB up the side, and the amber peak is yours to place — drag it anywhere on the plot. After the response display of a mastering processor.'); /* ============ CONTROL WIRING ============ */ /* 01 toggle */ @@ -1927,6 +1930,50 @@ function setSeg14(i){seg14I=i;const word=SEG14_WORDS[i].padEnd(4,' '); setRd('R25',SEG14_WORDS[i]);} setSeg14(0); +/* R26 response graph: log-frequency axes, a draggable amber peak */ +const RG={x0:30,x1:182,y0:8,y1:86,fLo:Math.log10(32),fHi:Math.log10(16000),db:12}; +let rgFc=1200,rgGain=6.5,rgCurve=null,rgGlowLine=null,rgHandle=null; +(function(){const s=$('rgraph'); + svgEl(s,'rect',{x:1,y:1,width:188,height:108,rx:5,fill:'#0d1410',stroke:'#22301f','stroke-width':2}); + const FREQS=[32,64,128,250,500,1000,2000,4000,8000,16000]; + FREQS.forEach(f=>{const x=RG.x0+(Math.log10(f)-RG.fLo)/(RG.fHi-RG.fLo)*(RG.x1-RG.x0); + svgEl(s,'line',{x1:x,y1:RG.y0,x2:x,y2:RG.y1,stroke:'#22301f','stroke-width':.6}); + svgEl(s,'text',{x,y:RG.y1+9,'text-anchor':'middle','font-size':4.8,'font-family':'var(--mono)', + fill:'var(--steel)'}).textContent=f<1000?f:(f/1000)+'k';}); + for(const db of [12,6,0,-6,-12]){const y=RG.y0+(RG.db-db)/(2*RG.db)*(RG.y1-RG.y0); + svgEl(s,'line',{x1:RG.x0,y1:y,x2:RG.x1,y2:y,stroke:'#22301f','stroke-width':db===0?1:.6}); + svgEl(s,'text',{x:RG.x0-4,y:y+2,'text-anchor':'end','font-size':4.8,'font-family':'var(--mono)', + fill:'var(--steel)'}).textContent=(db>0?'+':'')+db;} + rgGlowLine=svgEl(s,'polyline',{points:'',fill:'none',stroke:'var(--gold-hi)','stroke-width':3, + opacity:.35,filter:'url(#avGlow)'}); + rgCurve=svgEl(s,'polyline',{points:'',fill:'none',stroke:'var(--gold)','stroke-width':1.6}); + rgHandle=svgEl(s,'circle',{r:4,fill:'var(--gold-hi)',stroke:'#7d5c16','stroke-width':1}); + rgHandle.style.cursor='move'; + // 2D drag: the handle (and the plot) place the peak in both axes at once + s.style.touchAction='none'; + s.addEventListener('pointerdown',e=>{s.setPointerCapture(e.pointerId); + const move=ev=>{const r=s.getBoundingClientRect(),sx=190/r.width,sy=110/r.height; + const px=(ev.clientX-r.left)*sx,py=(ev.clientY-r.top)*sy; + const lf=RG.fLo+Math.max(0,Math.min(1,(px-RG.x0)/(RG.x1-RG.x0)))*(RG.fHi-RG.fLo); + const g=RG.db-Math.max(0,Math.min(1,(py-RG.y0)/(RG.y1-RG.y0)))*2*RG.db; + setRgraph(Math.pow(10,lf),g);}; + move(e); + const up=()=>{s.removeEventListener('pointermove',move);s.removeEventListener('pointerup',up);s.removeEventListener('pointercancel',up);}; + s.addEventListener('pointermove',move);s.addEventListener('pointerup',up);s.addEventListener('pointercancel',up); + e.preventDefault();});})(); +function setRgraph(fc,gain){rgFc=Math.max(32,Math.min(16000,fc));rgGain=Math.max(-12,Math.min(12,gain)); + const xOf=f=>RG.x0+(Math.log10(f)-RG.fLo)/(RG.fHi-RG.fLo)*(RG.x1-RG.x0); + const yOf=db=>RG.y0+(RG.db-db)/(2*RG.db)*(RG.y1-RG.y0); + const sigma=0.28;let pts=''; + for(let i=0;i<=76;i++){const lf=RG.fLo+i/76*(RG.fHi-RG.fLo); + const db=rgGain*Math.exp(-Math.pow(lf-Math.log10(rgFc),2)/(2*sigma*sigma)); + pts+=`${xOf(Math.pow(10,lf)).toFixed(1)},${yOf(db).toFixed(1)} `;} + rgCurve.setAttribute('points',pts.trim());rgGlowLine.setAttribute('points',pts.trim()); + rgHandle.setAttribute('cx',xOf(rgFc));rgHandle.setAttribute('cy',yOf(rgGain)); + const fLbl=rgFc<1000?Math.round(rgFc)+' Hz':(rgFc/1000).toFixed(1)+' kHz'; + setRd('R26',`${fLbl} · ${rgGain>=0?'+':''}${rgGain.toFixed(1)} dB`);} +setRgraph(1200,6.5); + /* ============ LIVE SIGNAL LOOPS ============ */ buildBars($('vuL'),16);buildBars($('vuR'),16);$('mini').innerHTML='<i></i><i></i><i></i><i></i>'; (function(){const eq=$('eq');for(let b=0;b<11;b++){const band=document.createElement('span');band.className='band'; |
