Update script handle and description for gallery TV slideshow in enqueue.php
This commit is contained in:
@@ -5424,10 +5424,10 @@ p:last-child { margin-bottom: 0; }
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════
|
||||
INDUSTRY MOCKUP ANIMATIONS (.platform-visual.has-industry)
|
||||
GALLERY TV SLIDESHOW (.platform-visual.has-gallery-tv)
|
||||
═══════════════════════════════════════════════════════════════ */
|
||||
|
||||
.platform-visual.has-industry {
|
||||
.platform-visual.has-gallery-tv {
|
||||
background: none !important;
|
||||
border: none !important;
|
||||
border-radius: 0;
|
||||
@@ -5438,93 +5438,76 @@ p:last-child { margin-bottom: 0; }
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.ind-stage {
|
||||
.gtv-stage {
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
max-width: 520px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.ind-stage svg {
|
||||
|
||||
/* TV frame (mirrors dashboard-tv pattern) */
|
||||
.gtv-tv {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.gtv-tv__body {
|
||||
width: 100%;
|
||||
background: #111;
|
||||
border: 4px solid #111;
|
||||
border-radius: 6px 6px 4px 4px;
|
||||
outline: 1px solid #000;
|
||||
padding: 3px;
|
||||
position: relative;
|
||||
box-shadow: 0 14px 48px rgba(0,0,0,0.55);
|
||||
}
|
||||
.gtv-tv__screen {
|
||||
width: 100%;
|
||||
aspect-ratio: 16/9;
|
||||
background: var(--color-bg);
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.gtv-tv__feet {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 60%;
|
||||
max-width: 300px;
|
||||
}
|
||||
.gtv-tv__foot {
|
||||
width: 12px;
|
||||
height: 8px;
|
||||
background: #111;
|
||||
border: 1px solid #000;
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
|
||||
/* Slides */
|
||||
.gtv-slides {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.gtv-slide {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
opacity: 0;
|
||||
transition: opacity 0.8s ease;
|
||||
}
|
||||
.gtv-slide.is-active {
|
||||
opacity: 1;
|
||||
}
|
||||
.gtv-slide img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
border-radius: var(--radius-md);
|
||||
box-shadow: 0 8px 32px rgba(0,0,0,.3);
|
||||
}
|
||||
|
||||
/* Subtle glow around active screens */
|
||||
.ind-stage svg rect[fill="#1c2333"] {
|
||||
transition: filter .6s ease;
|
||||
}
|
||||
|
||||
/* Animated content transitions */
|
||||
.ind-menu-price,
|
||||
.ind-sale-tag,
|
||||
.ind-footfall-val,
|
||||
.ind-kpi-val,
|
||||
.ind-meet-status,
|
||||
.ind-alert-text,
|
||||
.ind-weather-icon,
|
||||
.ind-weather-temp,
|
||||
.ind-busy-label,
|
||||
.ind-ld-val,
|
||||
.ind-ld-alert-text {
|
||||
transition: opacity .3s ease;
|
||||
}
|
||||
|
||||
.ind-menu-bar,
|
||||
.ind-rev-bar,
|
||||
.ind-vendor-bar,
|
||||
.ind-ld-bar {
|
||||
transition: height .4s ease, y .4s ease;
|
||||
}
|
||||
|
||||
.ind-product-slot {
|
||||
transition: stroke-width .3s ease;
|
||||
}
|
||||
|
||||
.ind-sched-slot {
|
||||
transition: opacity .4s ease, stroke .3s ease;
|
||||
}
|
||||
|
||||
.ind-wf-dot {
|
||||
transition: opacity .5s ease;
|
||||
}
|
||||
|
||||
.ind-alert-bar {
|
||||
transition: opacity .4s ease;
|
||||
}
|
||||
|
||||
.ind-meet-dot,
|
||||
.ind-busy-dot,
|
||||
.ind-ld-alert {
|
||||
transition: fill .4s ease;
|
||||
}
|
||||
|
||||
.ind-corp-line,
|
||||
.ind-ld-line {
|
||||
transition: d .3s ease;
|
||||
}
|
||||
|
||||
.ind-ld-pie {
|
||||
transition: d .4s ease;
|
||||
}
|
||||
|
||||
/* ── Reduced-motion overrides for industry animations ── */
|
||||
/* ── Reduced-motion overrides for gallery TV ── */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.ind-menu-bar,
|
||||
.ind-rev-bar,
|
||||
.ind-vendor-bar,
|
||||
.ind-ld-bar,
|
||||
.ind-product-slot,
|
||||
.ind-sched-slot,
|
||||
.ind-wf-dot,
|
||||
.ind-alert-bar,
|
||||
.ind-corp-line,
|
||||
.ind-ld-line,
|
||||
.ind-ld-pie,
|
||||
.ind-meet-dot,
|
||||
.ind-busy-dot,
|
||||
.ind-ld-alert {
|
||||
.gtv-slide {
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,380 +1,56 @@
|
||||
/**
|
||||
* Industry Mockup Animator
|
||||
* Animates SVG environment mockups for each industry on the solutions page.
|
||||
* Each mockup shows devices in real-world use with animated screen content.
|
||||
* Gallery TV Slideshow
|
||||
* Cycles through images inside gallery-TV blocks.
|
||||
* Pauses off-screen via IntersectionObserver for performance.
|
||||
* Respects prefers-reduced-motion.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||
|
||||
var SPEED = 0.0018;
|
||||
|
||||
/* ── Utility ────────────────────────────────────────────── */
|
||||
function wave(t, off) {
|
||||
return Math.max(0, Math.min(1,
|
||||
0.55 + Math.sin(t + off) * 0.25 + Math.sin(t * 1.8 + off * 1.3) * 0.15
|
||||
));
|
||||
}
|
||||
|
||||
function lerp(a, b, t) { return a + (b - a) * t; }
|
||||
|
||||
function isDark() {
|
||||
return document.documentElement.getAttribute('data-theme') === 'dark';
|
||||
}
|
||||
|
||||
/* ── Hospitality ────────────────────────────────────────── */
|
||||
function initHospitality(svg, st) {
|
||||
st.menuPrices = svg.querySelectorAll('.ind-menu-price');
|
||||
st.menuBars = svg.querySelectorAll('.ind-menu-bar');
|
||||
st.promoBanner = svg.querySelector('.ind-promo-text');
|
||||
st.promoPhase = 0;
|
||||
st.promos = ['HAPPY HOUR 5-7PM', 'NEW: SUMMER MENU', '20% OFF DESSERTS', 'LIVE MUSIC FRI'];
|
||||
}
|
||||
|
||||
function tickHospitality(st) {
|
||||
// Animate menu prices (shimmer)
|
||||
for (var i = 0; i < st.menuPrices.length; i++) {
|
||||
var v = wave(st.phase, i * 1.4);
|
||||
var price = (5 + Math.round(v * 20)).toFixed(2);
|
||||
st.menuPrices[i].textContent = '$' + price;
|
||||
}
|
||||
// Animate popularity bars
|
||||
for (var j = 0; j < st.menuBars.length; j++) {
|
||||
var bv = wave(st.phase * 0.6, j * 1.8);
|
||||
st.menuBars[j].setAttribute('width', Math.round(bv * 50 + 10));
|
||||
}
|
||||
// Cycle promo banner
|
||||
st.promoPhase += SPEED * 0.3;
|
||||
if (st.promoPhase > 1) {
|
||||
st.promoPhase = 0;
|
||||
if (st.promoBanner) {
|
||||
var idx = Math.floor(Math.random() * st.promos.length);
|
||||
st.promoBanner.textContent = st.promos[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Retail ─────────────────────────────────────────────── */
|
||||
function initRetail(svg, st) {
|
||||
st.saleTags = svg.querySelectorAll('.ind-sale-tag');
|
||||
st.footfall = svg.querySelector('.ind-footfall-val');
|
||||
st.revBars = svg.querySelectorAll('.ind-rev-bar');
|
||||
st.productSlots = svg.querySelectorAll('.ind-product-slot');
|
||||
st.productPhase = 0;
|
||||
}
|
||||
|
||||
function tickRetail(st) {
|
||||
// Sale tags pulse opacity
|
||||
for (var i = 0; i < st.saleTags.length; i++) {
|
||||
var op = 0.5 + wave(st.phase * 1.2, i * 2.0) * 0.5;
|
||||
st.saleTags[i].setAttribute('opacity', op.toFixed(2));
|
||||
}
|
||||
// Footfall counter
|
||||
if (st.footfall) {
|
||||
var count = Math.round(wave(st.phase * 0.3, 0) * 450 + 50);
|
||||
st.footfall.textContent = count;
|
||||
}
|
||||
// Revenue bars
|
||||
for (var j = 0; j < st.revBars.length; j++) {
|
||||
var rv = wave(st.phase * 0.5, j * 1.5);
|
||||
var h = Math.round(rv * 35 + 5);
|
||||
st.revBars[j].setAttribute('height', h);
|
||||
st.revBars[j].setAttribute('y', 40 - h);
|
||||
}
|
||||
// Product slots cycle highlight
|
||||
st.productPhase += SPEED * 0.15;
|
||||
if (st.productPhase > 1) {
|
||||
st.productPhase = 0;
|
||||
var active = Math.floor(Math.random() * st.productSlots.length);
|
||||
for (var k = 0; k < st.productSlots.length; k++) {
|
||||
st.productSlots[k].setAttribute('stroke-width', k === active ? '2' : '0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Corporate ──────────────────────────────────────────── */
|
||||
function initCorporate(svg, st) {
|
||||
st.kpiVals = svg.querySelectorAll('.ind-kpi-val');
|
||||
st.kpiArrows = svg.querySelectorAll('.ind-kpi-arrow');
|
||||
st.meetStatus = svg.querySelector('.ind-meet-status');
|
||||
st.meetDot = svg.querySelector('.ind-meet-dot');
|
||||
st.meetPhase = 0;
|
||||
st.statuses = ['Available', 'In Meeting', 'Reserved 2:30', 'Available'];
|
||||
st.statusIdx = 0;
|
||||
st.linePath = svg.querySelector('.ind-corp-line');
|
||||
st.lineW = 140;
|
||||
st.linePts = 6;
|
||||
}
|
||||
|
||||
function tickCorporate(st) {
|
||||
// KPI counters
|
||||
for (var i = 0; i < st.kpiVals.length; i++) {
|
||||
var kv = wave(st.phase * 0.6, i * 2.2);
|
||||
var vals = [
|
||||
Math.round(kv * 98) + '%',
|
||||
Math.round(kv * 340 + 60),
|
||||
Math.round(kv * 50 + 10) + 'ms'
|
||||
];
|
||||
if (vals[i]) st.kpiVals[i].textContent = vals[i];
|
||||
}
|
||||
// KPI arrows
|
||||
for (var j = 0; j < st.kpiArrows.length; j++) {
|
||||
var up = wave(st.phase * 0.6, j * 2.2) > 0.5;
|
||||
st.kpiArrows[j].setAttribute('transform',
|
||||
up ? 'rotate(0)' : 'rotate(180)');
|
||||
st.kpiArrows[j].setAttribute('fill', up ? '#4CAF50' : '#ef4444');
|
||||
}
|
||||
// Meeting room status cycle
|
||||
st.meetPhase += SPEED * 0.15;
|
||||
if (st.meetPhase > 1) {
|
||||
st.meetPhase = 0;
|
||||
st.statusIdx = (st.statusIdx + 1) % st.statuses.length;
|
||||
if (st.meetStatus) st.meetStatus.textContent = st.statuses[st.statusIdx];
|
||||
if (st.meetDot) {
|
||||
st.meetDot.setAttribute('fill',
|
||||
st.statusIdx === 1 ? '#ef4444' : st.statusIdx === 2 ? '#f59e0b' : '#4CAF50');
|
||||
}
|
||||
}
|
||||
// Line chart
|
||||
if (st.linePath) {
|
||||
var d = 'M';
|
||||
for (var p = 0; p < st.linePts; p++) {
|
||||
var x = (p / (st.linePts - 1)) * st.lineW;
|
||||
var y = 10 + (1 - wave(st.phase * 0.8, p * 0.9)) * 30;
|
||||
d += (p ? ' L' : '') + x.toFixed(1) + ',' + y.toFixed(1);
|
||||
}
|
||||
st.linePath.setAttribute('d', d);
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Education ──────────────────────────────────────────── */
|
||||
function initEducation(svg, st) {
|
||||
st.schedSlots = svg.querySelectorAll('.ind-sched-slot');
|
||||
st.alertBar = svg.querySelector('.ind-alert-bar');
|
||||
st.alertText = svg.querySelector('.ind-alert-text');
|
||||
st.alertPhase = 0;
|
||||
st.alerts = ['Fire Drill 2:00 PM', 'Early Dismissal Fri', 'Gym Closed Today', 'Bus 12 Delayed'];
|
||||
st.alertIdx = 0;
|
||||
st.wayfindDots = svg.querySelectorAll('.ind-wf-dot');
|
||||
st.wfActive = 0;
|
||||
st.wfPhase = 0;
|
||||
}
|
||||
|
||||
function tickEducation(st) {
|
||||
// Schedule slots pulse (current class highlight)
|
||||
for (var i = 0; i < st.schedSlots.length; i++) {
|
||||
var isCurrent = (Math.floor(st.phase * 0.3) % st.schedSlots.length) === i;
|
||||
st.schedSlots[i].setAttribute('opacity', isCurrent ? '1' : '0.5');
|
||||
st.schedSlots[i].setAttribute('stroke', isCurrent ? '#D83302' : 'none');
|
||||
st.schedSlots[i].setAttribute('stroke-width', isCurrent ? '1.5' : '0');
|
||||
}
|
||||
// Alert banner cycle
|
||||
st.alertPhase += SPEED * 0.12;
|
||||
if (st.alertPhase > 1) {
|
||||
st.alertPhase = 0;
|
||||
st.alertIdx = (st.alertIdx + 1) % st.alerts.length;
|
||||
if (st.alertText) st.alertText.textContent = st.alerts[st.alertIdx];
|
||||
}
|
||||
// Alert bar pulse
|
||||
if (st.alertBar) {
|
||||
var ap = 0.6 + Math.sin(st.phase * 2) * 0.4;
|
||||
st.alertBar.setAttribute('opacity', ap.toFixed(2));
|
||||
}
|
||||
// Wayfinding dot sequence
|
||||
st.wfPhase += SPEED * 0.2;
|
||||
if (st.wfPhase > 1) {
|
||||
st.wfPhase = 0;
|
||||
st.wfActive = (st.wfActive + 1) % Math.max(st.wayfindDots.length, 1);
|
||||
}
|
||||
for (var w = 0; w < st.wayfindDots.length; w++) {
|
||||
st.wayfindDots[w].setAttribute('opacity', w === st.wfActive ? '1' : '0.2');
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Outdoor Marketplace ────────────────────────────────── */
|
||||
function initOutdoor(svg, st) {
|
||||
st.weatherIcon = svg.querySelector('.ind-weather-icon');
|
||||
st.weatherTemp = svg.querySelector('.ind-weather-temp');
|
||||
st.weatherPhase = 0;
|
||||
st.weathers = [
|
||||
{ icon: '\u2600', temp: '24°C' },
|
||||
{ icon: '\u26C5', temp: '19°C' },
|
||||
{ icon: '\u2601', temp: '16°C' },
|
||||
{ icon: '\u2600', temp: '22°C' }
|
||||
];
|
||||
st.weatherIdx = 0;
|
||||
st.vendorBars = svg.querySelectorAll('.ind-vendor-bar');
|
||||
st.busyDot = svg.querySelector('.ind-busy-dot');
|
||||
st.busyLabel = svg.querySelector('.ind-busy-label');
|
||||
}
|
||||
|
||||
function tickOutdoor(st) {
|
||||
// Weather cycle
|
||||
st.weatherPhase += SPEED * 0.1;
|
||||
if (st.weatherPhase > 1) {
|
||||
st.weatherPhase = 0;
|
||||
st.weatherIdx = (st.weatherIdx + 1) % st.weathers.length;
|
||||
var w = st.weathers[st.weatherIdx];
|
||||
if (st.weatherIcon) st.weatherIcon.textContent = w.icon;
|
||||
if (st.weatherTemp) st.weatherTemp.textContent = w.temp;
|
||||
}
|
||||
// Vendor activity bars
|
||||
for (var i = 0; i < st.vendorBars.length; i++) {
|
||||
var bv = wave(st.phase * 0.5, i * 1.6);
|
||||
var h = Math.round(bv * 25 + 3);
|
||||
st.vendorBars[i].setAttribute('height', h);
|
||||
st.vendorBars[i].setAttribute('y', 28 - h);
|
||||
}
|
||||
// Busy indicator pulse
|
||||
if (st.busyDot) {
|
||||
var busy = wave(st.phase * 0.3, 0) > 0.6;
|
||||
st.busyDot.setAttribute('fill', busy ? '#ef4444' : '#4CAF50');
|
||||
if (st.busyLabel) st.busyLabel.textContent = busy ? 'Busy' : 'Quiet';
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Live Data Displays ─────────────────────────────────── */
|
||||
function initLiveData(svg, st) {
|
||||
st.ldBars = svg.querySelectorAll('.ind-ld-bar');
|
||||
st.ldVals = svg.querySelectorAll('.ind-ld-val');
|
||||
st.ldLine = svg.querySelector('.ind-ld-line');
|
||||
st.ldLineW = 110;
|
||||
st.ldLinePts = 8;
|
||||
st.ldPieSegs = svg.querySelectorAll('.ind-ld-pie');
|
||||
st.ldPieR = 22;
|
||||
st.ldAlertDot = svg.querySelector('.ind-ld-alert');
|
||||
st.ldAlertText = svg.querySelector('.ind-ld-alert-text');
|
||||
st.ldAlertPhase = 0;
|
||||
st.ldAlerts = ['All Systems OK', 'CPU: 72%', 'Latency: 12ms', 'Queue: 340'];
|
||||
st.ldAlertIdx = 0;
|
||||
}
|
||||
|
||||
function tickLiveData(st) {
|
||||
// Bars animate
|
||||
for (var i = 0; i < st.ldBars.length; i++) {
|
||||
var bv = wave(st.phase, i * 1.1);
|
||||
var h = Math.round(bv * 30 + 5);
|
||||
st.ldBars[i].setAttribute('height', h);
|
||||
st.ldBars[i].setAttribute('y', 35 - h);
|
||||
}
|
||||
// Values update
|
||||
for (var v = 0; v < st.ldVals.length; v++) {
|
||||
var val = wave(st.phase, v * 1.1);
|
||||
st.ldVals[v].textContent = Math.round(val * 5000);
|
||||
}
|
||||
// Line chart
|
||||
if (st.ldLine) {
|
||||
var d = 'M';
|
||||
for (var p = 0; p < st.ldLinePts; p++) {
|
||||
var x = (p / (st.ldLinePts - 1)) * st.ldLineW;
|
||||
var y = 5 + (1 - wave(st.phase * 0.8, p * 0.9)) * 30;
|
||||
d += (p ? ' L' : '') + x.toFixed(1) + ',' + y.toFixed(1);
|
||||
}
|
||||
st.ldLine.setAttribute('d', d);
|
||||
}
|
||||
// Pie chart
|
||||
if (st.ldPieSegs.length) {
|
||||
var n = st.ldPieSegs.length;
|
||||
var weights = [], total = 0;
|
||||
for (var pi = 0; pi < n; pi++) {
|
||||
var pw = 0.5 + wave(st.phase * 0.4, pi * 2.0) * 0.5;
|
||||
weights.push(pw);
|
||||
total += pw;
|
||||
}
|
||||
var angle = 0;
|
||||
for (var pj = 0; pj < n; pj++) {
|
||||
var sweep = (weights[pj] / total) * 360;
|
||||
var startA = angle * Math.PI / 180;
|
||||
var endA = (angle + sweep) * Math.PI / 180;
|
||||
var large = sweep > 180 ? 1 : 0;
|
||||
var r = st.ldPieR;
|
||||
var x1 = Math.sin(startA) * r, y1 = -Math.cos(startA) * r;
|
||||
var x2 = Math.sin(endA) * r, y2 = -Math.cos(endA) * r;
|
||||
var path = st.ldPieSegs[pj];
|
||||
if (path) {
|
||||
path.setAttribute('d',
|
||||
'M0,0 L' + x1.toFixed(2) + ',' + y1.toFixed(2) +
|
||||
' A' + r + ',' + r + ' 0 ' + large + ',1 ' +
|
||||
x2.toFixed(2) + ',' + y2.toFixed(2) + ' Z');
|
||||
}
|
||||
angle += sweep;
|
||||
}
|
||||
}
|
||||
// Alert text cycle
|
||||
st.ldAlertPhase += SPEED * 0.12;
|
||||
if (st.ldAlertPhase > 1) {
|
||||
st.ldAlertPhase = 0;
|
||||
st.ldAlertIdx = (st.ldAlertIdx + 1) % st.ldAlerts.length;
|
||||
if (st.ldAlertText) st.ldAlertText.textContent = st.ldAlerts[st.ldAlertIdx];
|
||||
if (st.ldAlertDot) {
|
||||
st.ldAlertDot.setAttribute('fill', st.ldAlertIdx === 0 ? '#4CAF50' : '#f59e0b');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Registry ───────────────────────────────────────────── */
|
||||
var INDUSTRIES = {
|
||||
hospitality: { init: initHospitality, tick: tickHospitality },
|
||||
retail: { init: initRetail, tick: tickRetail },
|
||||
corporate: { init: initCorporate, tick: tickCorporate },
|
||||
education: { init: initEducation, tick: tickEducation },
|
||||
outdoor: { init: initOutdoor, tick: tickOutdoor },
|
||||
livedata: { init: initLiveData, tick: tickLiveData }
|
||||
};
|
||||
|
||||
/* ── Main loop ──────────────────────────────────────────── */
|
||||
var instances = [];
|
||||
|
||||
function tickAll() {
|
||||
for (var i = 0; i < instances.length; i++) {
|
||||
var st = instances[i];
|
||||
if (st.paused) continue;
|
||||
st.phase += SPEED * 16;
|
||||
st.handler.tick(st);
|
||||
}
|
||||
requestAnimationFrame(tickAll);
|
||||
}
|
||||
|
||||
function observe(st) {
|
||||
if (!('IntersectionObserver' in window)) return;
|
||||
new IntersectionObserver(function (entries) {
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
st.paused = !entries[i].isIntersecting;
|
||||
}
|
||||
}, { rootMargin: '200px', threshold: 0.05 }).observe(st.el);
|
||||
}
|
||||
var INTERVAL = 4000; // ms between slides
|
||||
|
||||
function boot() {
|
||||
var els = document.querySelectorAll('[data-industry-anim]');
|
||||
if (!els.length) return;
|
||||
var stages = document.querySelectorAll('[data-gtv-slideshow]');
|
||||
if (!stages.length) return;
|
||||
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
var el = els[i];
|
||||
var type = el.getAttribute('data-industry-anim');
|
||||
var handler = INDUSTRIES[type];
|
||||
if (!handler) continue;
|
||||
if (el._indAnim) continue;
|
||||
/* Honour reduced-motion – show first slide only */
|
||||
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||
|
||||
var svg = el.querySelector('svg');
|
||||
if (!svg) continue;
|
||||
for (var i = 0; i < stages.length; i++) {
|
||||
initSlideshow(stages[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var st = {
|
||||
el: el,
|
||||
svg: svg,
|
||||
handler: handler,
|
||||
phase: Math.random() * Math.PI * 2,
|
||||
paused: false
|
||||
};
|
||||
function initSlideshow(stage) {
|
||||
var slides = stage.querySelectorAll('.gtv-slide');
|
||||
if (slides.length < 2) return;
|
||||
|
||||
handler.init(svg, st);
|
||||
observe(st);
|
||||
el._indAnim = st;
|
||||
instances.push(st);
|
||||
var state = { current: 0, paused: false, timer: null };
|
||||
|
||||
/* IntersectionObserver – pause when off-screen */
|
||||
if ('IntersectionObserver' in window) {
|
||||
new IntersectionObserver(function (entries) {
|
||||
for (var j = 0; j < entries.length; j++) {
|
||||
state.paused = !entries[j].isIntersecting;
|
||||
}
|
||||
if (!state.paused && !state.timer) {
|
||||
state.timer = setInterval(function () { advance(slides, state); }, INTERVAL);
|
||||
} else if (state.paused && state.timer) {
|
||||
clearInterval(state.timer);
|
||||
state.timer = null;
|
||||
}
|
||||
}, { rootMargin: '200px', threshold: 0.05 }).observe(stage);
|
||||
}
|
||||
|
||||
if (instances.length) requestAnimationFrame(tickAll);
|
||||
/* Start cycling */
|
||||
state.timer = setInterval(function () { advance(slides, state); }, INTERVAL);
|
||||
}
|
||||
|
||||
function advance(slides, state) {
|
||||
if (state.paused) return;
|
||||
slides[state.current].classList.remove('is-active');
|
||||
state.current = (state.current + 1) % slides.length;
|
||||
slides[state.current].classList.add('is-active');
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
|
||||
Reference in New Issue
Block a user