[object Object]

← back to Scarlet Riverboat Masquerade

Replace emoji motifs with original DRAWN animated song-items: flickering flames, spinning flowers, twinkling stars, rotating snowflakes, water drops, spinning wheels, flapping birds, + musical notes default — keyed to the current track title, floating up through the scene

546a5e7ce467506f816c3b9560f210ce75831858 · 2026-09-01 22:30:12 -0700 · Steve Abrams

Files touched

Diff

commit 546a5e7ce467506f816c3b9560f210ce75831858
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Sep 1 22:30:12 2026 -0700

    Replace emoji motifs with original DRAWN animated song-items: flickering flames, spinning flowers, twinkling stars, rotating snowflakes, water drops, spinning wheels, flapping birds, + musical notes default — keyed to the current track title, floating up through the scene
---
 index.html | 89 ++++++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 55 insertions(+), 34 deletions(-)

diff --git a/index.html b/index.html
index b9dda3c..986ee3e 100644
--- a/index.html
+++ b/index.html
@@ -422,52 +422,73 @@ const VENUES=[
 ];
 let venueOn=true;
 
-// ---- Song-motif layer: floats items drawn from the current track's title ----
-const MOTIFS=[
-  [/fire|flame|mountain|burn/,           ['🔥','⛰️','✨']],
-  [/sugar|magnolia|sugaree|begonia|rose|flower|daffodil|lily|garden/, ['🌺','🌸','🌼']],
-  [/rain|snow|cold|storm|hail|winter/,   ['❄️','🌧️','☁️']],
-  [/sun|sunshine|sunflower|shine|summer/,['🌞','🌻','☀️']],
-  [/moon|dark star|midnight|star/,       ['🌙','⭐','✨']],
-  [/water|river|ripple|ocean|wave|sea|rowing/, ['💧','🌊']],
-  [/bird|eagle|dove|sparrow|crow/,       ['🐦','🕊️']],
-  [/cat|china cat|tiger|lion/,           ['🐱','🐾']],
-  [/train|casey|railroad|jones|engine/,  ['🚂','🛤️']],
-  [/truck|road|highway|ramble|wheel|turnin/, ['🚚','🛣️','🎡']],
-  [/devil|hell|deal|gambl|dice|card/,    ['🃏','🎲']],
-  [/eyes|world/,                          ['👁️','🌍']],
-  [/wine|whiskey|beer|jug|drink/,        ['🍷','🥃']],
-  [/love|heart|sweet|darling|honey/,     ['💗','💘']],
-  [/gold|silver|diamond|jewel/,          ['✨','💎']],
-  [/rat|mouse|wharf/,                    ['🐀']],
-  [/candy|man/,                          ['🍬']]
+// ---- Song-motif layer: original DRAWN animated items keyed to the current track title ----
+const MOTIF_MAP=[
+  [/fire|flame|mountain|burn/,                             'flame'],
+  [/sugar|magnolia|sugaree|begonia|rose|flower|lily|garden|daffodil|scarlet/, 'flower'],
+  [/rain|snow|cold|storm|winter|hail/,                     'snow'],
+  [/star|moon|dark star|midnight|shine|sunshine|sun/,      'star'],
+  [/water|river|ripple|ocean|wave|sea|row|creek/,          'water'],
+  [/wheel|turnin|truck|road|ramble|train|casey|railroad|jones/, 'wheel'],
+  [/bird|eagle|dove|sparrow|crow|wing/,                    'bird']
 ];
-let motifParticles=[], motifClock=0, motifSet=null, motifKey=null;
-function currentMotifs(){
+let motifParticles=[], motifClock=0, motifType=null, motifKey=null;
+function currentMotifType(){
   const tr=((window.SRM&&window.SRM.track)||'').toLowerCase();
-  if(tr===motifKey) return motifSet;
-  motifKey=tr; motifSet=null;
-  for(const m of MOTIFS){ if(m[0].test(tr)){ motifSet=m[1]; break; } }
-  return motifSet;
+  if(tr===motifKey) return motifType;
+  motifKey=tr; motifType='note';                 // default: musical notes for every song
+  for(const m of MOTIF_MAP){ if(m[0].test(tr)){ motifType=m[1]; break; } }
+  return motifType;
+}
+function drawMotif(type,s,life,tt,col){
+  const al=Math.max(0,Math.min(0.9,life));
+  if(type==='flame'){
+    const f=Math.sin(tt*12+s)*0.18;
+    ctx.globalAlpha=al; ctx.fillStyle='#ff8a3a';
+    ctx.beginPath(); ctx.moveTo(0,s*0.6); ctx.quadraticCurveTo(-s*0.5,0,0,-s*0.75-f*s); ctx.quadraticCurveTo(s*0.5,0,0,s*0.6); ctx.fill();
+    ctx.fillStyle='#ffd24a'; ctx.beginPath(); ctx.moveTo(0,s*0.4); ctx.quadraticCurveTo(-s*0.25,0,0,-s*0.42-f*s); ctx.quadraticCurveTo(s*0.25,0,0,s*0.4); ctx.fill();
+  } else if(type==='flower'){
+    ctx.globalAlpha=al; ctx.rotate(tt*0.6+s); ctx.fillStyle=col||'#ff6aa0';
+    for(let i=0;i<5;i++){ ctx.rotate(Math.PI*2/5); ctx.beginPath(); ctx.ellipse(0,-s*0.5,s*0.28,s*0.5,0,0,7); ctx.fill(); }
+    ctx.fillStyle='#ffd24a'; ctx.beginPath(); ctx.arc(0,0,s*0.22,0,7); ctx.fill();
+  } else if(type==='snow'){
+    ctx.globalAlpha=al; ctx.strokeStyle='#dff0ff'; ctx.lineWidth=1.6; ctx.lineCap='round'; ctx.rotate(tt*0.8);
+    for(let i=0;i<6;i++){ ctx.rotate(Math.PI/3); ctx.beginPath(); ctx.moveTo(0,0); ctx.lineTo(0,-s*0.6); ctx.stroke(); }
+  } else if(type==='star'){
+    const tw=0.6+0.4*Math.sin(tt*6+s); ctx.globalAlpha=al*tw; ctx.fillStyle='#ffe89a';
+    ctx.beginPath(); for(let i=0;i<10;i++){ const a=i*Math.PI/5-Math.PI/2, r=(i%2?s*0.22:s*0.6); ctx.lineTo(Math.cos(a)*r,Math.sin(a)*r); } ctx.closePath(); ctx.fill();
+  } else if(type==='water'){
+    ctx.globalAlpha=al; ctx.fillStyle='#7ac0ff';
+    ctx.beginPath(); ctx.moveTo(0,-s*0.55); ctx.quadraticCurveTo(s*0.5,s*0.2,0,s*0.5); ctx.quadraticCurveTo(-s*0.5,s*0.2,0,-s*0.55); ctx.fill();
+  } else if(type==='wheel'){
+    ctx.globalAlpha=al; ctx.rotate(tt*3); ctx.strokeStyle='#f2b64a'; ctx.lineWidth=2;
+    ctx.beginPath(); ctx.arc(0,0,s*0.5,0,7); ctx.stroke();
+    for(let i=0;i<6;i++){ ctx.rotate(Math.PI/3); ctx.beginPath(); ctx.moveTo(0,0); ctx.lineTo(0,-s*0.5); ctx.stroke(); }
+  } else if(type==='bird'){
+    const flap=Math.sin(tt*8+s)*0.4; ctx.globalAlpha=al; ctx.strokeStyle='#241010'; ctx.lineWidth=2.2; ctx.lineCap='round';
+    ctx.beginPath(); ctx.moveTo(-s*0.5,0); ctx.quadraticCurveTo(-s*0.2,-s*0.45-flap*s,0,0); ctx.quadraticCurveTo(s*0.2,-s*0.45-flap*s,s*0.5,0); ctx.stroke();
+  } else {  // musical note
+    ctx.globalAlpha=al; ctx.fillStyle=col||'#f2b64a';
+    ctx.beginPath(); ctx.ellipse(-s*0.18,s*0.35,s*0.28,s*0.2,-0.3,0,7); ctx.fill();
+    ctx.fillRect(s*0.06,-s*0.55,s*0.09,s*0.95);
+    ctx.beginPath(); ctx.moveTo(s*0.15,-s*0.55); ctx.quadraticCurveTo(s*0.5,-s*0.5,s*0.42,-s*0.18); ctx.lineTo(s*0.15,-s*0.28); ctx.closePath(); ctx.fill();
+  }
+  ctx.globalAlpha=1;
 }
 function drawSongMotifs(dt){
-  const set=currentMotifs();
-  if(set && S.playing && !S.reduced){
+  const type=currentMotifType();
+  if(type && S.playing && !S.reduced){
     motifClock+=dt;
-    if(motifClock>0.75 && motifParticles.length<40){ motifClock=0;
-      motifParticles.push({x:S.W*(0.08+Math.random()*0.84), y:S.H*0.9, vy:-(18+Math.random()*26), drift:(Math.random()-0.5)*14, life:1, size:20+Math.random()*20, g:set[(Math.random()*set.length)|0]});
+    if(motifClock>0.55 && motifParticles.length<48){ motifClock=0;
+      motifParticles.push({x:S.W*(0.06+Math.random()*0.88), y:S.H*0.9, vy:-(18+Math.random()*26), drift:(Math.random()-0.5)*14, life:1, size:16+Math.random()*16, type, col:pal('accent',0)});
     }
   }
   if(!motifParticles.length) return;
-  ctx.save(); ctx.textAlign='center'; ctx.textBaseline='middle';
   for(let i=motifParticles.length-1;i>=0;i--){ const p=motifParticles[i];
     p.y+=p.vy*dt; p.x+=p.drift*dt; p.life-=dt*0.16;
     if(p.life<=0 || p.y<S.H*0.14){ motifParticles.splice(i,1); continue; }
-    ctx.globalAlpha=Math.max(0,Math.min(0.9,p.life));
-    ctx.font=`${p.size}px "Apple Color Emoji","Segoe UI Emoji",serif`;
-    ctx.fillText(p.g, p.x, p.y);
+    ctx.save(); ctx.translate(p.x,p.y); drawMotif(p.type,p.size,p.life,S.t,p.col); ctx.restore();
   }
-  ctx.restore(); ctx.globalAlpha=1;
 }
 
 function drawVenue(){

← c67e4f5 Concert venue backdrops (per-show stage-light beams + venue  ·  back to Scarlet Riverboat Masquerade  ·  Riverboat room: searchable full Grateful Dead archive — type 88dc7e0 →