diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-12 01:54:23 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-12 01:54:23 -0500 |
| commit | 52a43ec651cc92c219ef6d2b320b2e77d5b13235 (patch) | |
| tree | 939ab4eeabe576a97bd3028461dd1479d1ba745d | |
| parent | 3c54f2f4c4c29d13730f5c47272cf21eb64a2f94 (diff) | |
| download | archsetup-52a43ec651cc92c219ef6d2b320b2e77d5b13235.tar.gz archsetup-52a43ec651cc92c219ef6d2b320b2e77d5b13235.zip | |
The rotating scan after a radar PPI scope (reference filed in the catalogue's working directory): a beam circles inside a numbered bearing ring, an afterglow wedge trails it, contacts bloom as the beam passes and fade over the next half turn, and range rings sit under it all. Clicking marks the current bearing. The kit's round CRT draws traces; nothing rotated a scan until this.
I verified it in headless Chrome: the sweep rotates, the mark click captures the live bearing, no console exceptions.
| -rw-r--r-- | docs/prototypes/panel-widget-gallery.html | 50 | ||||
| -rw-r--r-- | working/retro-stereo-widgets/references/2026-07-12-radar-ppi.png | bin | 0 -> 169803 bytes |
2 files changed, 50 insertions, 0 deletions
diff --git a/docs/prototypes/panel-widget-gallery.html b/docs/prototypes/panel-widget-gallery.html index ab69855..f8330bb 100644 --- a/docs/prototypes/panel-widget-gallery.html +++ b/docs/prototypes/panel-widget-gallery.html @@ -894,6 +894,9 @@ card(I,'R26','Response graph', card(I,'R30','Telegraph indicator', `<svg id="telind" class="rsvg press" viewBox="0 0 110 110" width="110" height="110"></svg>`, '<b>state on a pie of sectors.</b> The pointer and its little flag name the active state, engine-telegraph style. Click to step the state. After an electric indicator dial.'); +card(I,'R31','Radar sweep', + `<svg id="radar" class="rsvg press" viewBox="0 0 130 130" width="130" height="130"></svg>`, + '<b>the rotating scan.</b> A sweep beam circles the bearing ring, contacts bloom as it passes and fade after. Click to mark the current bearing. After a radar PPI scope.'); /* ============ CONTROL WIRING ============ */ /* 01 toggle */ @@ -2006,6 +2009,53 @@ function setTelind(i){telI=i;const N=TELIND_STATES.length; setRd('R30',TELIND_STATES[i]);} setTelind(0); +/* R31 radar sweep: rotating beam, blooming contacts, click to mark */ +let radarA=210,radarSweep=null,radarBlips=[],radarMark=null; +const RADAR_CONTACTS=[[60,.55],[205,.7],[318,.4]]; +(function(){const s=$('radar'),cx=65,cy=65; + const defs=svgEl(s,'defs',{}); + const clip=svgEl(defs,'clipPath',{id:'radarClip'}); + svgEl(clip,'circle',{cx,cy,r:46}); + svgEl(s,'circle',{cx,cy,r:62,fill:'#1a1714',stroke:'#060505','stroke-width':2}); + svgEl(s,'circle',{cx,cy,r:52,fill:'#120b05',stroke:'#3a2a12','stroke-width':1}); + for(let d=0;d<360;d+=30){const a=d; + const [x1,y1]=polar(cx,cy,51,a),[x2,y2]=polar(cx,cy,47,a); + svgEl(s,'line',{x1,y1,x2,y2,stroke:'var(--gold)','stroke-width':1,opacity:.8}); + const g=svgEl(s,'g',{transform:`rotate(${a},${cx},${cy})`}); + svgEl(g,'text',{x:cx,y:cy-47.5,'text-anchor':'middle','font-size':4.6,'font-family':'var(--mono)', + fill:'var(--gold)',opacity:.9}).textContent=String(d).padStart(3,'0');} + for(let d=0;d<360;d+=10){if(d%30===0)continue; + const [x1,y1]=polar(cx,cy,51,d),[x2,y2]=polar(cx,cy,49,d); + svgEl(s,'line',{x1,y1,x2,y2,stroke:'var(--gold)','stroke-width':.6,opacity:.5});} + const g=svgEl(s,'g',{'clip-path':'url(#radarClip)'}); + svgEl(g,'circle',{cx,cy,r:46,fill:'#0d0803'}); + for(const r of [15,30,45]) + svgEl(g,'circle',{cx,cy,r,fill:'none',stroke:'rgba(226,160,56,.18)','stroke-width':.7}); + radarSweep=svgEl(g,'g',{}); + for(let t=0;t<5;t++){const a0=-14+t*2.8,a1=a0+2.8; + const [x1,y1]=polar(cx,cy,46,a0),[x2,y2]=polar(cx,cy,46,a1); + svgEl(radarSweep,'path',{d:`M ${cx} ${cy} L ${x1} ${y1} A 46 46 0 0 1 ${x2} ${y2} Z`, + fill:`rgba(226,160,56,${(0.04+t*0.045).toFixed(3)})`});} + svgEl(radarSweep,'line',{x1:cx,y1:cy,x2:cx,y2:cy-46,stroke:'var(--gold-hi)','stroke-width':1.4, + transform:`rotate(0,${cx},${cy})`,opacity:.95}); + RADAR_CONTACTS.forEach(([bd,rf])=>{const [x,y]=polar(cx,cy,46*rf,bd); + radarBlips.push(svgEl(g,'circle',{cx:x,cy:y,r:2.2,fill:'var(--gold-hi)',opacity:0}));}); + svgEl(s,'circle',{cx,cy,r:3,fill:'var(--gold)',opacity:.8}); + radarMark=svgEl(s,'text',{x:cx,y:124,'text-anchor':'middle','font-size':6,'letter-spacing':'.12em', + 'font-family':'var(--mono)',fill:'var(--steel)'}); + radarMark.textContent='BEARING —'; + $('radar').onclick=()=>{radarMark.textContent='MARK '+String(Math.round(radarA)%360).padStart(3,'0'); + setRd('R31','mark '+String(Math.round(radarA)%360).padStart(3,'0'));};})(); +function tickRadar(){radarA=(radarA+2.6)%360; + radarSweep.setAttribute('transform',`rotate(${radarA},65,65)`); + RADAR_CONTACTS.forEach(([bd],i)=>{ + let d=(radarA-bd+360)%360; // degrees since beam passed + radarBlips[i].setAttribute('opacity',d<200?Math.max(0,.95-d/200):0);}); + radarMark.textContent=radarMark.textContent.startsWith('MARK')?radarMark.textContent: + 'BEARING '+String(Math.round(radarA)%360).padStart(3,'0');} +tickRadar();setRd('R31','sweeping'); +if(!matchMedia('(prefers-reduced-motion: reduce)').matches)setInterval(tickRadar,50); + /* R25 fourteen-segment display: the starburst that spells */ const SEG14_WORDS=['ZOOM','ECHO','TAPE','MOOD','HALL','COMP']; const SEG14_MAP={A:['a','b','c','e','f','g1','g2'],C:['a','d','e','f'], diff --git a/working/retro-stereo-widgets/references/2026-07-12-radar-ppi.png b/working/retro-stereo-widgets/references/2026-07-12-radar-ppi.png Binary files differnew file mode 100644 index 0000000..7d22420 --- /dev/null +++ b/working/retro-stereo-widgets/references/2026-07-12-radar-ppi.png |
