Widget:TwinSuns: Difference between revisions

From WyrdeWiki
No edit summary
No edit summary
Line 33: Line 33:
             style="position:relative;display:block;width:100%;background:transparent;">
             style="position:relative;display:block;width:100%;background:transparent;">
     </div>
     </div>
     <button id="<!--{$id|de
     <button id="<!--{$id|default:'wh'|escape:'html'}-->-play"
            style="font-size:1rem;padding:.2rem .6rem;cursor:pointer;">▶</button>
  </div>
 
  <!-- Date line -->
  <div style="margin:.25rem 0 .5rem;">
    <strong>Date:</strong>
    <span id="<!--{$id|default:'wh'|escape:'html'}-->-date">Fortnight of Renewal (Dawning), day 1</span>
  </div>
 
  <!-- Stage (centered sky, suns layered) -->
  <div id="<!--{$id|default:'wh'|escape:'html'}-->-stage"
      style="position:relative;width:100%;aspect-ratio:3/2;isolation:isolate;border:1px solid #333;background:#000;overflow:hidden;">
    <img id="<!--{$id|default:'wh'|escape:'html'}-->-sky"
        src="<!--{$sky|default:'/images/WyrdeHaven_Sky.png'|escape:'html'}-->" alt="Sky"
        decoding="async" draggable="false"
        style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center;z-index:1;"/>
    <img id="<!--{$id|default:'wh'|escape:'html'}-->-sol"
        src="<!--{$solara|default:'/wiki/images/f/fe/Solara.png'|escape:'html'}-->" alt="Solara"
        decoding="async" draggable="false"
        style="position:absolute;left:50%;top:35%;transform:translate(-50%,-50%);width:12%;height:auto;z-index:3;"/>
    <img id="<!--{$id|default:'wh'|escape:'html'}-->-vae"
        src="<!--{$vaelus|default:'/wiki/images/7/7a/Vaelus.png'|escape:'html'}-->" alt="Vaelus"
        decoding="async" draggable="false"
        style="position:absolute;left:50%;top:35%;transform:translate(-50%,-50%);width:8%;height:auto;z-index:2;"/>
  </div>
 
  <!-- Inclination readouts -->
  <div style="margin:.5rem 0 .25rem;">
    <strong>Relative Solar Inclination (Δ):</strong>
    <span id="<!--{$id|default:'wh'|escape:'html'}-->-delta">+2.50° (Closing)</span>
  </div>
  <div>
    <strong>Seasonal Equatorial Inclination (barycenter):</strong>
    <span id="<!--{$id|default:'wh'|escape:'html'}-->-season">-8.00°</span>
  </div>
</div>
 
<script type="text/javascript">
(function(){
  var ID  = "<!--{$id|default:'wh'|escape:'js'}-->";
  var FPS  = parseFloat("<!--{$fps|default:5|escape:'js'}-->") || 5;
  var N    = 479;
  var SEASON_AMP = parseFloat("<!--{$seasonAmp|default:8|escape:'js'}-->");    // degrees
  var WOBBLE_TOT = parseFloat("<!--{$wobbleTotal|default:2.5|escape:'js'}-->"); // degrees total
  // Split wobble: Solara 40%, Vaelus 60% (1.0° / 1.5° if total=2.5°)
  var SOL_WOB = WOBBLE_TOT * 0.40;
  var VAE_WOB = WOBBLE_TOT * 0.60;
 
  function ge(s){ return document.getElementById(ID + s); }
  var el = {
    x:    ge("-x"),
    play: ge("-play"),
    dayc: ge("-daycenter"),
    date: ge("-date"),
    sol:  ge("-sol"),
    vae:  ge("-vae"),
    delta: ge("-delta"),
    season: ge("-season"),
    stage: ge("-stage")
  };
 
  // Month / calendar helpers
  var months = [
    "Primaris","Vernalis","Tharion","Lunarae","Cindrel","Solvane","Auren",
    "Veyrath","Rhendol","Tirien","Gairos","Fenmir","Wyrdrun","Cernis","Eirathen"
  ];
 
  function dayToCalendar(d){
    // d: 1..479 ; first 7 = FR 8..14 (Dawning), last 7 = FR 1..7 (Fading)
    if (d <= 7) {
      return "Fortnight of Renewal (Dawning), day " + d;
    } else if (d > 472) {
      return "Fortnight of Renewal (Fading), day " + (d - 472);
    } else {
      var dd = d - 7; // shift into 1..465
      var m  = Math.floor((dd-1)/31);
      var md = ((dd-1)%31) + 1;
      return months[m] + ", day " + md;
    }
  }
 
  function fmtDeg(x){
    var s = (x>=0?"+":"−"); // true minus when negative
    var a = Math.abs(x).toFixed(2);
    return s + a + "°";
  }
 
  function update(){
    var X = parseInt(el.x.value,10);  // 1..479
    var t = (X-1)/N * 2*Math.PI;      // phase, cos starts at +1 on day 1
    // Seasonal inclination: lowest at midwinter (day 1), highest at midsummer
    var season = -SEASON_AMP * Math.cos(t);
    // Relative Δ between suns follows cos(t) with total amplitude WOBBLE_TOT
    var delta  =  WOBBLE_TOT * Math.cos(t);
    // Opening / Closing based on derivative sign of |Δ| toward 0 or max
    var ddt = -WOBBLE_TOT * Math.sin(t); // derivative of Δ
    var opening = (ddt > 0);            // increasing toward +max => moving away from 0
    var phaseWord;
    // We define "Closing" = moving from max toward 0; "Opening" = from 0 toward max
    // Around Δ ~ cos(t): when |Δ| decreasing => Closing; when increasing => Opening
    var dAbs = (delta>=0?1:-1)*ddt; // derivative of |Δ| (sign(Δ)*Δ')
    phaseWord = (dAbs < 0) ? "Closing" : "Opening";
 
    // Vertical placements:
    // Base center (percent from top). Keep near top third for visibility.
    var centerY = 35; // %
    // Convert degrees to pixel offset relative to stage height (small scaling for realism)
    var H = el.stage.clientHeight || 1;
    // 1 visual degree = 0.9% of stage height (tweakable, purely visual)
    var pxPerDeg = 0.009 * H;
 
    var solY = centerY - (season + SOL_WOB * Math.cos(t)) * (pxPerDeg*100/H);
    var vaeY = centerY - (season - VAE_WOB * Math.cos(t)) * (pxPerDeg*100/H);
 
    el.sol.style.top = solY + "%";
    el.vae.style.top = vaeY + "%";
    // Keep both horizontally centered over the stage (no right offset)
    el.sol.style.left = "50%";
    el.vae.style.left = "50%";
 
    // Readouts
    el.dayc.textContent = X + " / " + N;
    el.date.textContent = dayToCalendar(X);
    el.delta.textContent  = fmtDeg(delta) + " (" + phaseWord + ")";
    el.season.textContent = fmtDeg(season);
 
    // Cosine image is already width:100% under the slider and vertically centered.
  }
 
  // Scrub with rAF
  var raf = null;
  el.x.addEventListener("input", function(){
    if(raf) return;
    raf = requestAnimationFrame(function(){ raf=null; update(); });
  });
 
  // Play/stop
  var playing=false, timer=null, interval=1000/Math.max(1,FPS);
  function step(){
    var v = parseInt(el.x.value,10);
    v = (v>=N)?1:(v+1);
    el.x.value = v;
    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;
    }
  });
 
  // Initial
  update();
})();
</script>
</includeonly>

Revision as of 20:08, 11 November 2025

This widget displays WyrdeHaven’s Twin Suns with seasonal wobble and calendar.

Usage

1 / 479
Date: Fortnight of Renewal (Dawning), day 8 (FR 8)
Sky Solara Vaelus
Relative Solar Inclination (Δ): +2.50° (Closing)
Seasonal Equatorial Inclination (barycenter): -8.00°