diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-05 21:45:22 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-05 21:45:22 +0100 |
| commit | becb354b49119d27082b542ed7bdc70bc606e3b3 (patch) | |
| tree | a1ee9bd0c7d9b5d3138ab42c19b4ff7c306e1583 /tools | |
| parent | 194a47a99b3e3ae03c085721e94e5dd5b9a9f460 (diff) | |
feat(timeline-editor): Add time indicator, sequence flash, and taller view
Visual Enhancements:
1. Current Time Indicator (Vertical Line)
- Faint vertical line shows current scroll position
- Fixed position at left: 80px with gradient fade
- Color: rgba(78, 201, 176, 0.6) (teal/cyan)
- Gradient: fades at top/bottom for smooth appearance
- pointer-events: none (doesn't block interaction)
- z-index: 100 (appears above timeline elements)
- Guides the eye during mouse wheel navigation
2. Sequence Flash Effect
- Brief highlight when active sequence changes
- 0.6s animation: bright glow → normal state
- Keyframe animation sequenceFlash:
* Start: box-shadow 20px glow, teal border
* End: normal 10px glow, blue border
- Triggers on lastActiveSeqIndex change
- Auto-removes class after 600ms
- Helps user track which sequence is now active
3. Taller Timeline View
- timeline-container: height = calc(100vh - 280px)
- min-height: 500px (prevents over-shrinking)
- Uses full vertical real estate
- Much less squished appearance
- Better utilization of screen space
- Accommodates more sequences in viewport
Technical Implementation:
- Added lastActiveSeqIndex global state variable
- Wheel handler detects sequence index changes
- querySelector to find sequence div and add flash class
- setTimeout removes flash class after animation
- Fixed positioning for time indicator
- Responsive height calculation for container
User Experience:
- Visual feedback during diagonal scrolling
- Clear indication of current time position
- Smooth flash draws attention to sequence changes
- More comfortable editing with taller view
- Better spatial awareness of timeline position
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/timeline_editor/index.html | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/tools/timeline_editor/index.html b/tools/timeline_editor/index.html index ea8b454..ffaf74f 100644 --- a/tools/timeline_editor/index.html +++ b/tools/timeline_editor/index.html @@ -102,14 +102,34 @@ border-radius: 8px; padding: 20px; overflow-x: auto; + overflow-y: auto; + position: relative; + height: calc(100vh - 280px); + min-height: 500px; } .timeline { position: relative; - min-height: 400px; + min-height: 100%; border-left: 2px solid #3c3c3c; } + .current-time-indicator { + position: fixed; + left: 80px; + top: 0; + bottom: 0; + width: 2px; + background: linear-gradient(to bottom, + rgba(78, 201, 176, 0) 0%, + rgba(78, 201, 176, 0.6) 10%, + rgba(78, 201, 176, 0.6) 90%, + rgba(78, 201, 176, 0) 100%); + pointer-events: none; + z-index: 100; + opacity: 0.7; + } + .time-markers { position: relative; height: 30px; @@ -154,6 +174,21 @@ box-shadow: 0 0 10px rgba(78, 201, 176, 0.5); } + .sequence.active-flash { + animation: sequenceFlash 0.6s ease-out; + } + + @keyframes sequenceFlash { + 0% { + box-shadow: 0 0 20px rgba(78, 201, 176, 0.8); + border-color: #4ec9b0; + } + 100% { + box-shadow: 0 0 10px rgba(14, 99, 156, 0.5); + border-color: #0e639c; + } + } + .sequence-name { position: absolute; top: 50%; @@ -370,6 +405,7 @@ <div class="timeline-container"> <div class="time-markers" id="timeMarkers"></div> <div class="timeline" id="timeline"></div> + <div class="current-time-indicator" id="timeIndicator"></div> </div> <button class="panel-collapse-btn" id="panelCollapseBtn">◀ Properties</button> @@ -395,6 +431,7 @@ let bpm = 120; let isDragging = false; let dragOffset = { x: 0, y: 0 }; + let lastActiveSeqIndex = -1; // DOM elements const timeline = document.getElementById('timeline'); @@ -951,6 +988,21 @@ } } + // Flash effect when active sequence changes + if (targetSeqIndex !== lastActiveSeqIndex && sequences.length > 0) { + lastActiveSeqIndex = targetSeqIndex; + + // Add flash class to target sequence + const seqDivs = timeline.querySelectorAll('.sequence'); + if (seqDivs[targetSeqIndex]) { + seqDivs[targetSeqIndex].classList.add('active-flash'); + // Remove class after animation completes + setTimeout(() => { + seqDivs[targetSeqIndex]?.classList.remove('active-flash'); + }, 600); + } + } + // Smooth vertical scroll to bring target sequence to top of viewport const targetScrollTop = targetSeqIndex * 80; // 80px per sequence const currentScrollTop = timelineContainer.scrollTop; |
