aboutsummaryrefslogtreecommitdiff
path: root/docs/prototypes/panel-widget-gallery.html
diff options
context:
space:
mode:
Diffstat (limited to 'docs/prototypes/panel-widget-gallery.html')
-rw-r--r--docs/prototypes/panel-widget-gallery.html50
1 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'],