1 2 (() => { 3 const IMAGE_SRCS = [ 4 // "https://www.inviya.com/uploads/homepage/desktopfinll16796438201680932998.jpeg", 5 // "https://www.inviya.com/uploads/homepage/inviya_mask1676266910.jpg", 6 // "https://www.inviya.com/uploads/homepage/desk16800828471680933684.jpeg", 7 // "https://www.narayanburners.com/images/vision-banner-small.jpg", 8 // "https://cdn.vectorstock.com/i/500p/83/80/mission-vision-amp-values-icons-vector-51578380.jpg", 9 // "https://img.magnific.com/free-photo/business-hands-joined-together-teamwork_53876-30575.jpg" 10// "https://assets.codepen.io/573855/demo-raw-01.webp", 11// "https://assets.codepen.io/573855/demo-raw-02.webp", 12// "https://assets.codepen.io/573855/demo-raw-03.webp", 13// "https://assets.codepen.io/573855/demo-raw-04.webp", 14// "https://assets.codepen.io/573855/demo-raw-05.webp", 15// "https://assets.codepen.io/573855/demo-raw-06.webp" 16 ]; 17const FACE_NAMES = [ 18 "2012 - INVIYA⢠Launch", 19 "2017 - ACY Expansion", 20 "2018 - Fine Circular Knitting", 21 "2022 - SnugFit⢠Launch", 22 "2023 - ECOMODA 100â¢", 23 // "Present - P3 Plant Expansion" 24]; 25 const STOPS = [ 26 { rx: 90, ry: 0 }, { rx: 0, ry: 0 }, { rx: 0, ry: -90 }, 27 { rx: 0, ry: -180 }, { rx: 0, ry: -270 }, { rx: -90, ry: -360 } 28 ]; 29 30 const root = document.getElementById("rc-gal__root"); 31 const cube = document.getElementById("rc-gal__cube"); 32 const faces = [...document.querySelectorAll(".rc-gal__face")]; 33 const progFill = document.getElementById("rc-gal__prog_fill"); 34 const hudPct = document.getElementById("rc-gal__hud_pct"); 35 const sceneStrip = document.getElementById("rc-gal__scene_strip"); 36 const sections = [...document.querySelectorAll(".rc-gal__section")]; 37 38 // Generate Navigation Dots 39 sections.forEach((_, i) => { 40 const dot = document.createElement("div"); 41 dot.className = `rc-gal__dot ${i === 0 ? "active" : ""}`; 42 dot.onclick = () => { 43 const target = document.getElementById(`rc-gal__s${i}`); 44 target.scrollIntoView({ behavior: 'smooth' }); 45 }; 46 sceneStrip.appendChild(dot); 47 }); 48 49 const dots = [...document.querySelectorAll(".rc-gal__dot")]; 50 51 // Intersection Observer for animations 52 const observer = new IntersectionObserver((entries) => { 53 entries.forEach(entry => { 54 if (entry.isIntersecting) { 55 entry.target.querySelectorAll('.rc-gal__tag, .rc-gal__h1, .rc-gal__h2, .rc-gal__body-text, .rc-gal__cta') 56 .forEach(el => el.classList.add('rc-gal__visible')); 57 } 58 }); 59 }, { threshold: 0.2 }); 60 61 sections.forEach(s => observer.observe(s)); 62 63 // Theme Toggle Logic 64 document.getElementById("rc-gal__theme_toggle").addEventListener("click", () => { 65 const isLight = root.getAttribute("data-theme") === "light"; 66 root.setAttribute("data-theme", isLight ? "dark" : "light"); 67 }); 68 69 // Face Management 70 const setFaceImg = (faceIdx, imgIdx) => { 71 const face = faces[faceIdx]; 72 if (face && IMAGE_SRCS[imgIdx] && !face.querySelector('img')) { 73 const img = new Image(); 74 img.src = IMAGE_SRCS[imgIdx]; 75 face.appendChild(img); 76 } 77 }; 78 79 // Initialize initial faces 80 for(let i=0; i<6; i++) setFaceImg(i, i); 81 82 // Scroll Handling 83 const easeIO = (t) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t); 84 85 function update() { 86 if (!root) return; 87 88 const rect = root.getBoundingClientRect(); 89 const totalHeight = root.offsetHeight; 90 const viewportHeight = window.innerHeight; 91 92 // currentScroll is 0 when the top of the container hits the top of the viewport 93 const currentScroll = Math.max(0, -rect.top); 94 95 // Progress for the entire gallery (0 to 1) 96 const scrollDistance = totalHeight - viewportHeight; 97 let progress = Math.max(0, Math.min(1, currentScroll / scrollDistance)); 98 99 // Update HUD 100 if (progFill) progFill.style.width = `${progress * 100}%`; 101 if (hudPct) hudPct.textContent = `${Math.round(progress * 100).toString().padStart(3, '0')}%`; 102 103 // Update Cube - each section handles one transition 104 // We calculate rawT by finding which section we are currently in 105 let rawT = 0; 106 let cumulativeHeight = 0; 107 const sectionCount = sections.length; 108 109 for (let i = 0; i < sectionCount; i++) { 110 const h = sections[i].offsetHeight; 111 if (currentScroll < cumulativeHeight + h) { 112 // We are in this section. Progress within this section: 113 rawT = i + (currentScroll - cumulativeHeight) / h; 114 break; 115 } 116 cumulativeHeight += h; 117 if (i === sectionCount - 1) { 118 rawT = sectionCount; // Beyond last section 119 } 120 } 121 122 // Clamp rawT to [0, STOPS.length - 1] 123 rawT = Math.max(0, Math.min(STOPS.length - 1, rawT)); 124 125 const idx = Math.floor(rawT); 126 const localT = easeIO(rawT - idx); 127 128 if (idx < STOPS.length - 1) { 129 const a = STOPS[idx]; 130 const b = STOPS[idx + 1];
131 const rx = a.rx + (b.rx - a.rx) * localT; 132 const ry = a.ry + (b.ry - a.ry) * localT; 133 cube.style.transform = `rotateX(${rx}deg) rotateY(${ry}deg)`; 134 } else { 135 const last = STOPS[STOPS.length - 1]; 136 cube.style.transform = `rotateX(${last.rx}deg) rotateY(${last.ry}deg)`; 137 } 138 139 // Update Nav Dots & Labels based on current section 140 // activeIdx is the section the user is currently looking at 141 const activeIdx = Math.max(0, Math.min(sectionCount - 1, Math.floor(rawT))); 142 dots.forEach((d, i) => d.classList.toggle("active", i === activeIdx)); 143 144 const sceneName = document.getElementById("rc-gal__scene_name"); 145 const captionNum = document.getElementById("rc-gal__face_caption_num"); 146 const captionName = document.getElementById("rc-gal__face_caption_name"); 147 148 if (sceneName) sceneName.textContent = FACE_NAMES[activeIdx] || ""; 149 if (captionNum) captionNum.textContent = (activeIdx + 1).toString().padStart(2, '0'); 150 if (captionName) captionName.textContent = FACE_NAMES[activeIdx] || ""; 151 152 requestAnimationFrame(update); 153 } 154 155 requestAnimationFrame(update); 156 157 158 })(); 159 160
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.