No edit summary |
No edit summary |
||
| (14 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
<noinclude>__NOTOC__ | <noinclude>__NOTOC__ | ||
This widget | This widget shows WyrdeHaven’s twin suns with seasonal wobble & calendar. | ||
=Usage= | =Usage= | ||
| Line 6: | Line 6: | ||
| id=ts1 | | id=ts1 | ||
| size=768 | | size=768 | ||
| fps=8 | | fps=5 | ||
| | | wobble=5 | ||
| | | equator=8 | ||
| | | sep=2.5 | ||
| | | degpx=10 | ||
| | | solara=https://www.wyrdehavenchronicl.es/wiki/images/f/fe/Solara.png | ||
| | | vaelus=https://www.wyrdehavenchronicl.es/wiki/images/7/7a/Vaelus.png | ||
| sky=http://wyrdehavenchronicl.es/images/WyrdeHaven_Sky.png | |||
| cos=http://wyrdehavenchronicl.es/images/Cosinus.png | |||
}} | }} | ||
{| class="wikitable" | |||
|- | |||
! param !! meaning !! default | |||
|- | |||
| size || max stage width (px) || 768 | |||
|- | |||
| fps || play speed (frames/s) || 5 | |||
|- | |||
| wobble || solar relative wobble amplitude (Δ, degrees) || 2.5 | |||
|- | |||
| equator || seasonal/barycenter max tilt (degrees) || 8 | |||
|- | |||
| sep || visible horizontal separation between suns (degrees) || 2.5 | |||
|- | |||
| degpx || vertical degree→pixel scale (px per degree) || 10 | |||
|} | |||
</noinclude><includeonly> | </noinclude><includeonly> | ||
<div class="wh- | <div class="wh-twins" style="max-width:<!--{$size|default:768|escape:'html'}-->px;margin:1rem 0;"> | ||
<!-- centered day | <!-- centered day label --> | ||
<div | <div id="<!--{$id|default:'ts'|escape:'html'}-->-daylabel" | ||
style="text-align:center;font-weight:600;margin-bottom:.25rem;">1 / 479</div> | |||
<!-- slider + cosine | <!-- slider + cosine --> | ||
<div style="position:relative;display:flex;align-items:center;gap:.5rem;"> | <div style="position:relative;display:flex;align-items:center;gap:.5rem;"> | ||
<img id="<!--{$id|default:'ts'|escape:'html'}-->-cos" | <img id="<!--{$id|default:'ts'|escape:'html'}-->-cos" | ||
src="<!--{$ | src="<!--{$cos|escape:'html'}-->" | ||
alt=" | alt="" decoding="async" | ||
style="position:absolute;left:0;right:2. | style="position:absolute;left:0;right:2.25rem;top:50%;transform:translateY(-50%);opacity:.6;pointer-events:none;width:calc(100% - 2.25rem);height:auto;"/> | ||
<input id="<!--{$id|default:'ts'|escape:'html'}-->-x" type="range" min="1" max="479" value="1" | <input id="<!--{$id|default:'ts'|escape:'html'}-->-x" type="range" min="1" max="479" value="1" | ||
style="flex:1;position:relative;z-index:1;"> | style="flex:1;position:relative;z-index:1;"> | ||
<button id="<!--{$id|default:'ts'|escape:'html'}-->-play" | <button id="<!--{$id|default:'ts'|escape:'html'}-->-play" | ||
style="font-size:1rem;padding:.2rem .5rem;cursor:pointer | style="font-size:1rem;padding:.2rem .5rem;cursor:pointer;">▶</button> | ||
</div> | </div> | ||
<!-- | <!-- date line moved slightly lower to avoid cosine overlap --> | ||
<div style="margin:2rem 0 .4rem 0;"> | |||
<div style="margin: | |||
<strong>Date:</strong> | <strong>Date:</strong> | ||
<span id="<!--{$id|default:'ts'|escape:'html'}-->- | <span id="<!--{$id|default:'ts'|escape:'html'}-->-date">Fortnight of Renewal (Dawning), day 8 (FR 8)</span> | ||
</div> | </div> | ||
<!-- stage --> | <!-- stage --> | ||
<div id="<!--{$id|default:'ts'|escape:'html'}-->-stage" | <div id="<!--{$id|default:'ts'|escape:'html'}-->-stage" | ||
style="position:relative;width:100%;aspect-ratio:3/2;isolation:isolate;border:1px solid #333 | style="position:relative;width:100%;aspect-ratio:3/2;isolation:isolate;background:#000;border:1px solid #333;overflow:hidden;"> | ||
<img id="<!--{$id|default:'ts'|escape:'html'}-->-sky" | <img id="<!--{$id|default:'ts'|escape:'html'}-->-sky" | ||
src="<!--{$ | src="<!--{$sky|escape:'html'}-->" alt="Sky" decoding="async" | ||
style="position:absolute;inset:0;object-fit:contain;object-position:center;z-index:1;width:100%;height:100%;"/> | |||
<img id="<!--{$id|default:'ts'|escape:'html'}-->-solara" | |||
style="position:absolute;inset:0 | src="<!--{$solara|escape:'html'}-->" alt="Solara" | ||
style="position:absolute;z-index:3;transform:translate(-50%,-50%);"/> | |||
<img id="<!--{$id|default:'ts'|escape:'html'}-->- | <img id="<!--{$id|default:'ts'|escape:'html'}-->-vaelus" | ||
src="<!--{$ | src="<!--{$vaelus|escape:'html'}-->" alt="Vaelus" | ||
style="position:absolute;z-index:2;transform:translate(-50%,-50%);"/> | |||
style="position:absolute;transform:translate(-50%,-50%) | |||
<img id="<!--{$id|default:'ts'|escape:'html'}-->- | |||
src="<!--{$ | |||
style="position:absolute;transform:translate(-50%,-50%) | |||
</div> | </div> | ||
<div style="margin:.5rem | <div style="margin-top:.5rem;"> | ||
<div><strong>Relative Solar Inclination (Δ):</strong> <span id="<!--{$id|default:'ts'|escape:'html'}-->- | <div><strong>Relative Solar Inclination (Δ):</strong> | ||
<div><strong>Seasonal Equatorial Inclination (barycenter):</strong> <span id="<!--{$id|default:'ts'|escape:'html'}-->- | <span id="<!--{$id|default:'ts'|escape:'html'}-->-relinc">+2.50° (Closing)</span> | ||
</div> | |||
<div><strong>Seasonal Equatorial Inclination (barycenter):</strong> | |||
<span id="<!--{$id|default:'ts'|escape:'html'}-->-eqinc">-8.00°</span> | |||
</div> | |||
</div> | </div> | ||
</div> | </div> | ||
| Line 70: | Line 84: | ||
var ID = "<!--{$id|default:'ts'|escape:'js'}-->"; | var ID = "<!--{$id|default:'ts'|escape:'js'}-->"; | ||
var FPS = parseFloat("<!--{$fps|default:5|escape:'js'}-->") || 5; | var FPS = parseFloat("<!--{$fps|default:5|escape:'js'}-->") || 5; | ||
var WOBBLE = parseFloat("<!--{$wobble|default:2.5|escape:'js'}-->") || 2.5; // observable Δ (deg) | |||
var EQUATOR = parseFloat("<!--{$equator|default:8|escape:'js'}-->") || 8; // seasonal max (deg) | |||
var SEP = parseFloat("<!--{$sep|default:2.5|escape:'js'}-->") || 2.5; // horizontal sep (deg) | |||
var DEGPX = parseFloat("<!--{$degpx|default:10|escape:'js'}-->") || 10; // px per degree | |||
// | // Find and init exactly one instance in a given DOM scope | ||
function initIn(root){ | |||
var wrap = root.querySelector('.wh-twins'); | |||
if(!wrap) return; | |||
function ge(s){ return document.getElementById(ID + s); } | |||
var el = { | |||
day: ge("-daylabel"), | |||
rng: ge("-x"), | |||
play: ge("-play"), | |||
date: ge("-date"), | |||
stage: ge("-stage"), | |||
sky: ge("-sky"), | |||
s: ge("-solara"), | |||
v: ge("-vaelus"), | |||
rel: ge("-relinc"), | |||
eq: ge("-eqinc") | |||
}; | |||
for (var k in el){ if(!el[k]) return; } // quietly bail if something’s missing | |||
var TAU = Math.PI*2; | |||
function cosPhase(d){ return Math.cos(TAU*((d-1)/479)); } | |||
function fmtDeg(x){ var s=(x>=0?"+":""); return s + x.toFixed(2) + "°"; } | |||
var | function openingClosing(_, phase){ | ||
var s = Math.sin(TAU*phase); | |||
return (-s>0) ? "Closing" : "Opening"; | |||
} | |||
var months = ["Primaris","Vernalis","Tharion","Lunarae","Cindrel","Solvane","Auren","Veyrath","Rhendol","Tirien","Gairos","Fenmir","Wyrdrun","Cernis","Eirathen"]; | |||
function dateText(d){ | |||
if(d<=7) return "Fortnight of Renewal (Dawning), day " + (d+7) + " (FR " + (d+7) + ")"; | |||
if(d>=473){var k=d-472; return "Fortnight of Renewal (Fading), day " + k + " (FR " + k + ")";} | |||
var n=d-7, m=Math.ceil(n/31), day=((n-1)%31)+1; return day + " " + months[m-1]; | |||
} | } | ||
var SOL_SHARE=1.0, VAE_SHARE=1.5, SUM=SOL_SHARE+VAE_SHARE; | |||
function setStarSizes(){ | |||
var w = el.stage.clientWidth || el.stage.getBoundingClientRect().width || 0; | |||
if(!w) return; | |||
var base = Math.round(w*0.08); | |||
el.s.width = el.s.height = base; | |||
el.v.width = el.v.height = Math.round(base*0.8); | |||
} | |||
function update(){ | |||
try{ | |||
var d = parseInt(el.rng.value,10) || 1; | |||
var phase = (d-1)/479; | |||
// Your “observable” Δ already in sky-arc degrees | |||
var delta = (WOBBLE * cosPhase(d)) / 8; // ±WOBBLE | |||
var eq = -EQUATOR * cosPhase(d); // lowest at midwinter | |||
el.day.textContent = d + " / 479"; | |||
el.date.textContent = dateText(d); | |||
el.rel.textContent = fmtDeg(delta) + " (" + openingClosing(delta, phase) + ")"; | |||
el.eq.textContent = fmtDeg(eq); | |||
var w = el.stage.clientWidth, h = el.stage.clientHeight; | |||
if(!w||!h) return; | |||
var cx = w*0.5, cy = h*0.33; | |||
var dx = (SEP/2)*DEGPX; | |||
var solOff = (delta*(SOL_SHARE/SUM))*DEGPX; | |||
var vaeOff = -(delta*(VAE_SHARE/SUM))*DEGPX; | |||
var yBase = cy - (eq*DEGPX); | |||
el.s.style.left = (cx - dx) + "px"; | |||
el.v.style.left = (cx + dx) + "px"; | |||
el.s.style.top = (yBase - solOff) + "px"; | |||
el.v.style.top = (yBase - vaeOff) + "px"; | |||
}catch(e){} | |||
} | |||
function ensureSizedThen(fn){ | |||
setStarSizes(); | |||
if(el.stage.clientWidth) fn(); | |||
else setTimeout(function(){ ensureSizedThen(fn); }, 50); | |||
} | |||
var timer=null, playing=false, interval=1000/Math.max(1,FPS); | |||
function step(){ var v=parseInt(el.rng.value,10)||1; el.rng.value=(v>=479)?1:(v+1); update(); } | |||
el.rng.addEventListener("input", update); | |||
el. | el.play.addEventListener("click", function(){ | ||
if(!playing){ playing=true; el.play.textContent="■"; timer=setInterval(step, interval); } | |||
else { playing=false; el.play.textContent="▶"; clearInterval(timer); timer=null; } | |||
}); | |||
window.addEventListener("resize", function(){ setStarSizes(); update(); }); | |||
ensureSizedThen(update); | |||
} | } | ||
// Run on normal load | |||
if (document.readyState === "complete" || document.readyState === "interactive"){ | |||
initIn(document); | |||
} else { | |||
document.addEventListener("DOMContentLoaded", function(){ initIn(document); }, {once:true}); | |||
} | } | ||
// | // Also run when MediaWiki injects content (tabs, previews, etc.) | ||
if (window.mw && mw.hook) { | |||
mw.hook('wikipage.content').add(function($c){ | |||
initIn($c && $c[0] ? $c[0] : document); | |||
}); | |||
} | } | ||
})(); | })(); | ||
</script> | </script> | ||
</includeonly> | </includeonly> | ||
Latest revision as of 21:50, 11 November 2025
This widget shows WyrdeHaven’s twin suns with seasonal wobble & calendar.
Usage
1 / 479
Date:
Fortnight of Renewal (Dawning), day 8 (FR 8)
Relative Solar Inclination (Δ):
+2.50° (Closing)
Seasonal Equatorial Inclination (barycenter):
-8.00°
| param | meaning | default |
|---|---|---|
| size | max stage width (px) | 768 |
| fps | play speed (frames/s) | 5 |
| wobble | solar relative wobble amplitude (Δ, degrees) | 2.5 |
| equator | seasonal/barycenter max tilt (degrees) | 8 |
| sep | visible horizontal separation between suns (degrees) | 2.5 |
| degpx | vertical degree→pixel scale (px per degree) | 10 |