|
1576 | 1576 | window.addEventListener('load', function() { |
1577 | 1577 | const timelineSlider = document.getElementById('timelineSlider'); |
1578 | 1578 | if (timelineSlider) { |
1579 | | - timelineSlider.style.setProperty('background', '#5a8a2a', 'important'); |
1580 | | - timelineSlider.style.backgroundColor = '#5a8a2a'; |
1581 | | - timelineSlider.style.background = '#5a8a2a'; |
1582 | | - |
1583 | | - // Add dynamic styles |
| 1579 | + // Add dynamic styles for thumb |
1584 | 1580 | const dynamicStyle = document.createElement('style'); |
1585 | 1581 | dynamicStyle.id = 'timeline-green-style'; |
1586 | 1582 | dynamicStyle.textContent = ` |
1587 | | - #timelineSlider { |
1588 | | - background: #5a8a2a !important; |
1589 | | - background-color: #5a8a2a !important; |
1590 | | - } |
1591 | 1583 | #timelineSlider::-webkit-slider-thumb { |
1592 | 1584 | background: #5a8a2a !important; |
1593 | 1585 | } |
|
2038 | 2030 | timelineSlider.value = point; |
2039 | 2031 | frameVideo.currentTime = point; |
2040 | 2032 | updateTimeDisplay(point); |
| 2033 | + lastUpdateTime = 0; |
| 2034 | + updateProgressBarColor(); |
2041 | 2035 | }); |
2042 | 2036 |
|
2043 | 2037 | // Click key point to also jump |
2044 | 2038 | keyPoint.addEventListener('click', function() { |
2045 | 2039 | timelineSlider.value = point; |
2046 | 2040 | frameVideo.currentTime = point; |
2047 | 2041 | updateTimeDisplay(point); |
| 2042 | + lastUpdateTime = 0; |
| 2043 | + updateProgressBarColor(); |
2048 | 2044 | }); |
2049 | 2045 |
|
2050 | 2046 | // Add to timelineMarks container |
|
2058 | 2054 | const time = parseFloat(this.value); |
2059 | 2055 | frameVideo.currentTime = time; |
2060 | 2056 | updateTimeDisplay(time); |
| 2057 | + // Force immediate update for user input |
| 2058 | + lastUpdateTime = 0; |
| 2059 | + updateProgressBarColor(); |
2061 | 2060 | }); |
2062 | 2061 |
|
| 2062 | + // Throttle function for performance |
| 2063 | + let lastUpdateTime = 0; |
| 2064 | + const throttleDelay = 50; // Update at most every 50ms |
| 2065 | + |
2063 | 2066 | // Video time update events |
2064 | 2067 | frameVideo.addEventListener('timeupdate', function() { |
2065 | | - timelineSlider.value = this.currentTime; |
2066 | | - updateTimeDisplay(this.currentTime); |
| 2068 | + const currentTime = this.currentTime; |
| 2069 | + timelineSlider.value = currentTime; |
| 2070 | + updateTimeDisplay(currentTime); |
| 2071 | + |
| 2072 | + // Throttle progress bar color updates |
| 2073 | + const now = Date.now(); |
| 2074 | + if (now - lastUpdateTime >= throttleDelay) { |
| 2075 | + updateProgressBarColor(); |
| 2076 | + lastUpdateTime = now; |
| 2077 | + } |
2067 | 2078 | }); |
2068 | 2079 |
|
2069 | 2080 | // Update time display |
|
2075 | 2086 | `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(2, '0')}`; |
2076 | 2087 | } |
2077 | 2088 |
|
2078 | | - // Force set timeline color - multiple safeguards |
2079 | | - timelineSlider.style.setProperty('background', '#5a8a2a', 'important'); |
2080 | | - timelineSlider.style.backgroundColor = '#5a8a2a'; |
2081 | | - timelineSlider.style.background = '#5a8a2a'; |
| 2089 | + // Update progress bar color (green for reached, gray for unreached) |
| 2090 | + let lastPercentage = -1; // Track last percentage to avoid unnecessary updates |
| 2091 | + function updateProgressBarColor() { |
| 2092 | + const value = parseFloat(timelineSlider.value) || 0; |
| 2093 | + const max = parseFloat(timelineSlider.max) || 25; |
| 2094 | + if (max <= 0) return; // Don't update if max is invalid |
| 2095 | + |
| 2096 | + const percentage = Math.max(0, Math.min(100, (value / max) * 100)); |
| 2097 | + |
| 2098 | + // Only update if percentage changed significantly (avoid unnecessary updates) |
| 2099 | + if (Math.abs(percentage - lastPercentage) < 0.1 && lastPercentage >= 0) { |
| 2100 | + return; |
| 2101 | + } |
| 2102 | + lastPercentage = percentage; |
| 2103 | + |
| 2104 | + // Get or create style element - always use the same ID |
| 2105 | + let trackStyle = document.getElementById('timeline-track-style'); |
| 2106 | + if (!trackStyle) { |
| 2107 | + trackStyle = document.createElement('style'); |
| 2108 | + trackStyle.id = 'timeline-track-style'; |
| 2109 | + // Insert at the end of head to ensure highest priority |
| 2110 | + document.head.appendChild(trackStyle); |
| 2111 | + } |
| 2112 | + |
| 2113 | + // Use layered backgrounds: green on top, gray below |
| 2114 | + // Use !important to override any static CSS |
| 2115 | + // Set both background and background-image for maximum compatibility |
| 2116 | + const gradient = `linear-gradient(to right, #5a8a2a 0%, #5a8a2a ${percentage}%, transparent ${percentage}%, transparent 100%)`; |
| 2117 | + |
| 2118 | + // Force update by removing and re-adding the style element |
| 2119 | + // This ensures the browser re-applies the styles |
| 2120 | + if (trackStyle.parentNode) { |
| 2121 | + trackStyle.parentNode.removeChild(trackStyle); |
| 2122 | + } |
| 2123 | + trackStyle = document.createElement('style'); |
| 2124 | + trackStyle.id = 'timeline-track-style'; |
| 2125 | + trackStyle.textContent = ` |
| 2126 | + #timelineSlider::-webkit-slider-runnable-track { |
| 2127 | + background: #ccc !important; |
| 2128 | + background-image: ${gradient} !important; |
| 2129 | + background-size: 100% 100% !important; |
| 2130 | + background-repeat: no-repeat !important; |
| 2131 | + background-position: 0 0 !important; |
| 2132 | + } |
| 2133 | + #timelineSlider::-moz-range-track { |
| 2134 | + background: #ccc !important; |
| 2135 | + background-image: ${gradient} !important; |
| 2136 | + background-size: 100% 100% !important; |
| 2137 | + background-repeat: no-repeat !important; |
| 2138 | + background-position: 0 0 !important; |
| 2139 | + } |
| 2140 | + `; |
| 2141 | + // Append to end of head for highest priority |
| 2142 | + document.head.appendChild(trackStyle); |
| 2143 | + } |
2082 | 2144 |
|
2083 | | - // Set slider thumb color |
| 2145 | + // Set slider thumb color and positioning |
2084 | 2146 | const style = document.createElement('style'); |
2085 | 2147 | style.textContent = ` |
2086 | 2148 | #timelineSlider::-webkit-slider-thumb { |
2087 | 2149 | background: #5a8a2a !important; |
| 2150 | + margin-top: -6px !important; |
2088 | 2151 | } |
2089 | 2152 | #timelineSlider::-moz-range-thumb { |
2090 | 2153 | background: #5a8a2a !important; |
2091 | 2154 | } |
2092 | | - #timelineSlider { |
2093 | | - background: #5a8a2a !important; |
2094 | | - } |
2095 | 2155 | `; |
2096 | 2156 | document.head.appendChild(style); |
2097 | 2157 |
|
| 2158 | + // Initialize progress bar color |
| 2159 | + updateProgressBarColor(); |
| 2160 | + |
2098 | 2161 | // Initialize |
2099 | 2162 | timelineSlider.max = frameVideo.duration || 30; |
2100 | 2163 | updateTimeDisplay(0); |
| 2164 | + updateProgressBarColor(); |
2101 | 2165 |
|
2102 | 2166 | // Ensure initialization after video loads |
2103 | 2167 | frameVideo.addEventListener('loadedmetadata', function() { |
2104 | 2168 | timelineSlider.max = this.duration; |
2105 | 2169 | updateTimeDisplay(0); |
| 2170 | + updateProgressBarColor(); |
2106 | 2171 | }); |
2107 | 2172 |
|
2108 | 2173 | // If video is already loaded, initialize immediately |
2109 | 2174 | if (frameVideo.readyState >= 1) { |
2110 | 2175 | timelineSlider.max = frameVideo.duration; |
2111 | 2176 | updateTimeDisplay(0); |
| 2177 | + updateProgressBarColor(); |
2112 | 2178 | } |
2113 | 2179 | } |
2114 | 2180 | }); |
@@ -3674,7 +3740,7 @@ <h2 class="title is-3" style="text-align: center; color: #3a6902;">Goal Reaching |
3674 | 3740 | <h4 style="text-align: center; margin-bottom: 15px; font-family: var(--font-sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif);">Click image for real-world goal pose, click ▶ for natural transition, and drag the progress bar to view frame by frame.</h4> |
3675 | 3741 | <div class="video-timeline-container"> |
3676 | 3742 | <div class="timeline-marks" id="timelineMarks"></div> |
3677 | | - <input type="range" id="timelineSlider" class="timeline-slider" min="0" max="25" step="0.1" value="0" style="background: #5a8a2a !important;"> |
| 3743 | + <input type="range" id="timelineSlider" class="timeline-slider" min="0" max="25" step="0.1" value="0" style="background: #ccc;"> |
3678 | 3744 | <div class="timeline-current-time" id="currentTime">00:00.00</div> |
3679 | 3745 | </div> |
3680 | 3746 |
|
|
0 commit comments