Buy me a coffee

Media Toggle with Image and Sound

Description

  • View Demo – Password: abc
  • toggle button, click on each button will change image and play icon
  • click play icon will play sound

12.25l26

#1. Install Code

Hover on Page where you want to apply effect > Click Gear icon

12.25l26

Click Advanced > Paste this code

<style>
  :root{
    --tp-minh:100vh;
    --tp-toggle-bottom:22px;
    --tp-toggle-top:auto;
    --tp-label-size:14px;
    --tp-label-track:.08em;
    --tp-label-dim:.45;
    --tp-label-on:.95;
    --tp-switch-w:46px;
    --tp-switch-h:20px;
    --tp-switch-border:.8;
    --tp-knob:12px;
    --tp-knob-pad:3px;
    --tp-pin-size:56px;
    --tp-pin-stroke:.75;
    --tp-ico-size:26px;
  }
  .tp-audio-scene{position:relative;width:100%;min-height:var(--tp-minh);overflow:hidden;background:#0b0f14}
  .tp-audio-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center}
  .tp-audio-overlay{position:absolute;inset:0;pointer-events:none}
  .tp-pin{position:absolute;left:calc(var(--x)*1%);top:calc(var(--y)*1%);transform:translate(-50%,-50%);pointer-events:auto}
  .tp-pin-btn{width:var(--tp-pin-size);height:var(--tp-pin-size);border-radius:50%;border:1px solid rgba(255,255,255,var(--tp-pin-stroke));background:transparent;display:grid;place-items:center;cursor:pointer}
  .tp-pin-btn svg{width:var(--tp-ico-size);height:var(--tp-ico-size);fill:none;stroke:#fff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
  .tp-pin-btn .tp-ico-on{display:none}
  .tp-pin-btn[aria-pressed="true"] .tp-ico-off{display:none}
  .tp-pin-btn[aria-pressed="true"] .tp-ico-on{display:block}
  .tp-toggle{position:absolute;left:50%;top:var(--tp-toggle-top);bottom:var(--tp-toggle-bottom);transform:translateX(-50%);display:flex;align-items:center;gap:18px;user-select:none}
  .tp-toggle .tp-lbl{appearance:none;border:0;background:transparent;font:700 var(--tp-label-size)/1.1 system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;letter-spacing:var(--tp-label-track);text-transform:uppercase;padding:0;margin:0;cursor:default;color:rgba(255,255,255,var(--tp-label-dim))}
  .tp-toggle .tp-lbl[aria-current="true"]{color:rgba(255,255,255,var(--tp-label-on))}
  .tp-switch{width:var(--tp-switch-w);height:var(--tp-switch-h);border-radius:999px;border:1px solid rgba(255,255,255,var(--tp-switch-border));background:transparent;position:relative;cursor:pointer}
  .tp-knob{position:absolute;top:50%;left:var(--tp-knob-pad);transform:translateY(-50%);width:var(--tp-knob);height:var(--tp-knob);border-radius:50%;background:#fff;transition:left .22s ease}
  .tp-audio-scene[data-mode="interior"] .tp-knob{left:calc(var(--tp-switch-w) - var(--tp-knob) - var(--tp-knob-pad))}
  ul.user-items-list-item-container{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:0!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important;white-space:nowrap!important;border:0!important}
  .tp-audio-scene{margin-top:18px}
  @media(max-width:767px){
    :root{--tp-toggle-bottom:16px;--tp-pin-size:52px;--tp-ico-size:24px}
  }
</style>

<script>
  (() => {
    const CONFIG = {
      sectionSelector: '#media-sound-toggle',
      retryTimes: 90,
      retryDelay: 250
    };

    const ICON_OFF = `
      <svg class="tp-ico-off" viewBox="0 0 24 24">
        <path d="M11 5L6 9H3v6h3l5 4V5z"></path>
        <path d="M16.2 9.3l4.2 4.2"></path>
        <path d="M20.4 9.3l-4.2 4.2"></path>
      </svg>
    `;

    const ICON_ON = `
      <svg class="tp-ico-on" viewBox="0 0 24 24">
        <path d="M11 5L6 9H3v6h3l5 4V5z"></path>
        <path d="M15.5 8.5a5 5 0 0 1 0 7"></path>
        <path d="M18 6a8 8 0 0 1 0 12"></path>
      </svg>
    `;

  const $=(s,r=document)=>r.querySelector(s);const $$=(s,r=document)=>Array.from(r.querySelectorAll(s));function getImage(i){const img=i?.querySelector(".list-item-media img");if(!img)return"";return img.getAttribute("data-src")||img.getAttribute("data-image")||img.getAttribute("src")||""}function getTitle(i){const el=i?.querySelector(".list-item-content__title");return el?el.textContent.trim():""}function getAudios(i){const d=i?.querySelector(".list-item-content__description");if(!d)return[];const a=Array.from(d.querySelectorAll("a[href]"));if(a.length){const u=[];a.forEach(x=>{const h=(x.getAttribute("href")||"").trim();if(h)u.push(h)});return u}const u=[];(d.textContent||"").split(/\r?\n/).map(t=>t.trim()).filter(Boolean).forEach(l=>{const f=l.match(/https?:\/\/[^\s]+/g);if(f)u.push(...f)});return u}function extractData(l){const it=$$(":scope > li.list-item",l);if(!it.length)return null;const ex=it[0];const inn=it[1]||it[0];return{labels:{exterior:getTitle(ex)||"EXTERIOR",interior:getTitle(inn)||"INTERIOR"},images:{exterior:getImage(ex),interior:getImage(inn)},audios:{exterior:getAudios(ex),interior:getAudios(inn)}}}function autoPinLayout(c,k="scene"){const n=Math.max(0,c|0);if(!n)return[];function hash(s){let h=2166136261;for(let i=0;i<s.length;i++){h^=s.charCodeAt(i);h=Math.imul(h,16777619)}return h>>>0}function mulberry32(a){return function(){let t=a+=0x6D2B79F5;t=Math.imul(t^(t>>>15),t|1);t^=t+Math.imul(t^(t>>>7),t|61);return((t^(t>>>14))>>>0)/4294967296}}const rand=mulberry32(hash(String(k)+"|"+n));const area={x0:14,x1:86,y0:14,y1:86};const minDist=10,triesPerPin=100,pts=[];function sample(){return{x:area.x0+rand()*(area.x1-area.x0),y:area.y0+rand()*(area.y1-area.y0)}}function ok(p){for(const q of pts){if(Math.hypot(p.x-q.x,p.y-q.y)<minDist)return false}return true}for(let i=0;i<n;i++){let placed=false;for(let t=0;t<triesPerPin;t++){const p=sample();if(ok(p)){pts.push(p);placed=true;break}}if(!placed)pts.push(sample())}return pts.map((p,i)=>({x:p.x,y:p.y,audioIndex:i}))}function renderScene(m,data){m.innerHTML=`<div class="tp-audio-scene" data-mode="exterior"><img class="tp-audio-bg"><div class="tp-audio-overlay"></div><div class="tp-toggle"><span class="tp-lbl" aria-current="true"></span><button type="button" class="tp-switch"><span class="tp-knob"></span></button><span class="tp-lbl"></span></div></div>`;const scene=$(".tp-audio-scene",m),bg=$(".tp-audio-bg",m),pinsHost=$(".tp-audio-overlay",m),switchBtn=$(".tp-switch",m),labels=$$(".tp-lbl",m);let mode="exterior",currentAudio=null,currentButton=null;function stopAudio(){if(currentAudio){currentAudio.pause();currentAudio.currentTime=0}if(currentButton)currentButton.setAttribute("aria-pressed","false");currentAudio=null;currentButton=null}function paint(){stopAudio();scene.dataset.mode=mode;labels[0].textContent=data.labels.exterior;labels[1].textContent=data.labels.interior;labels[0].setAttribute("aria-current",mode==="exterior");labels[1].setAttribute("aria-current",mode==="interior");bg.src=data.images[mode]||"";pinsHost.innerHTML="";const audioList=data.audios[mode]||[];const pinList=autoPinLayout(audioList.length,mode);pinList.forEach(pin=>{const src=audioList[pin.audioIndex];if(!src)return;const wrap=document.createElement("div");wrap.className="tp-pin";wrap.style.setProperty("--x",pin.x);wrap.style.setProperty("--y",pin.y);const btn=document.createElement("button");btn.className="tp-pin-btn";btn.setAttribute("aria-pressed","false");btn.innerHTML=ICON_OFF+ICON_ON;const audio=new Audio(src);btn.addEventListener("click",async()=>{if(currentButton===btn){stopAudio();return}stopAudio();currentButton=btn;currentAudio=audio;btn.setAttribute("aria-pressed","true");try{await audio.play()}catch{stopAudio()}audio.onended=()=>{if(currentButton===btn)stopAudio()}});wrap.appendChild(btn);pinsHost.appendChild(wrap)})}switchBtn.addEventListener("click",()=>{mode=mode==="exterior"?"interior":"exterior";paint()});paint();return{repaint(n){Object.assign(data,n);paint()}}}function init(r){const section=$(CONFIG.sectionSelector);const list=section?.querySelector("ul.user-items-list-item-container");if(!section||!list||!list.querySelector("li.list-item")){if(r>0)setTimeout(()=>init(r-1),CONFIG.retryDelay);return}const data=extractData(list);if(!data)return;const host=section.querySelector(".user-items-list")||section;let mount=$("#"+CONFIG.mountId,section);if(!mount){mount=document.createElement("div");mount.id=CONFIG.mountId;host.insertBefore(mount,host.children[1]||host.firstChild)}const api=renderScene(mount,data);new MutationObserver(()=>{const n=extractData(list);if(n)api.repaint(n)}).observe(list,{childList:true,subtree:true,characterData:true})}if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",()=>init(CONFIG.retryTimes))}else{init(CONFIG.retryTimes)}})();
</script>

12.25l26

#2. Usage

You need to add a Team Section

12.25l22

Hover on top right of section > Click Edit Section > At Anchor Link, enter word: media-sound-toggle

media-sound-toggle

12.25l26

Enable these options in Team Section

12.25l26

Click Content tab to add image, toggle text, audio url

12.25l26

Upload image & Enter toggle text

12.25l26

Next, enter Audio URL. Make sure use .mp3 format

12.25l26

Repeat for remain toggle

12.25l26

#3. Customize

All style options in Line 03 to Line 17

--tp-minh:100vh;
  --tp-toggle-bottom:22px;
  --tp-toggle-top:auto;
  --tp-label-size:14px;
  --tp-label-track:.08em;
  --tp-label-dim:.45;
  --tp-label-on:.95;
  --tp-switch-w:46px;
  --tp-switch-h:20px;
  --tp-switch-border:.8;
  --tp-knob:12px;
  --tp-knob-pad:3px;
  --tp-pin-size:56px;
  --tp-pin-stroke:.75;
  --tp-ico-size:26px;

12.25l26