No edit summary |
No edit summary |
||
| (13 intermediate revisions by the same user not shown) | |||
| Line 7: | Line 7: | ||
| size=768 | | size=768 | ||
| fps=5 | | fps=5 | ||
| wobble= | | wobble=5 | ||
| equator=8 | | equator=8 | ||
| sep=2.5 | | sep=2.5 | ||
| Line 50: | Line 50: | ||
</div> | </div> | ||
<!-- date line | <!-- date line moved slightly lower to avoid cosine overlap --> | ||
<div style="margin: | <div style="margin:2rem 0 .4rem 0;"> | ||
<strong>Date:</strong> | <strong>Date:</strong> | ||
<span id="<!--{$id|default:'ts'|escape:'html'}-->-date">Fortnight of Renewal (Dawning), day 8 (FR 8)</span> | <span id="<!--{$id|default:'ts'|escape:'html'}-->-date">Fortnight of Renewal (Dawning), day 8 (FR 8)</span> | ||
| Line 84: | 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; | var WOBBLE = parseFloat("<!--{$wobble|default:2.5|escape:'js'}-->") || 2.5; // observable Δ (deg) | ||
var EQUATOR = parseFloat("<!--{$equator|default:8|escape:'js'}-->") || 8; | var EQUATOR = parseFloat("<!--{$equator|default:8|escape:'js'}-->") || 8; // seasonal max (deg) | ||
var SEP = parseFloat("<!--{$sep|default:2.5|escape:'js'}-->") || 2.5; | var SEP = parseFloat("<!--{$sep|default:2.5|escape:'js'}-->") || 2.5; // horizontal sep (deg) | ||
var DEGPX = parseFloat("<!--{$degpx|default:10|escape:'js'}-->") || 10; | var DEGPX = parseFloat("<!--{$degpx|default:10|escape:'js'}-->") || 10; // px per degree | ||
function | // 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"), | |||
el. | 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) + "°"; } | |||
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.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> | |||
</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 |