Skip to content

Commit

Permalink
Refactor: optimize Timeline virtual rendering (katspaugh#3748)
Browse files Browse the repository at this point in the history
  • Loading branch information
katspaugh committed Jun 16, 2024
1 parent 700d997 commit 741f71c
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 12 deletions.
19 changes: 13 additions & 6 deletions src/plugins/timeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,15 @@ class TimelinePlugin extends BasePlugin<TimelinePluginEvents, TimelinePluginOpti
}

private virtualAppend(start: number, container: HTMLElement, element: HTMLElement) {
const renderIfVisible = () => {
let wasVisible = false

const renderIfVisible = (scrollLeft: number, scrollRight: number) => {
if (!this.wavesurfer) return
const clientWidth = this.wavesurfer.getWidth()
const scrollLeft = this.wavesurfer.getScroll()
const width = element.clientWidth
const isVisible = start + width > scrollLeft && start < scrollLeft + clientWidth
const isVisible = start > scrollLeft && start + width < scrollRight

if (isVisible === wasVisible) return
wasVisible = isVisible

if (isVisible) {
container.appendChild(element)
Expand All @@ -160,8 +163,12 @@ class TimelinePlugin extends BasePlugin<TimelinePluginEvents, TimelinePluginOpti

setTimeout(() => {
if (!this.wavesurfer) return
renderIfVisible()
this.subscriptions.push(this.wavesurfer.on('scroll', renderIfVisible))
renderIfVisible(0, this.wavesurfer?.getWidth() || 0)
this.subscriptions.push(
this.wavesurfer.on('scroll', (_start, _end, scrollLeft, scrollRight) => {
renderIfVisible(scrollLeft, scrollRight)
}),
)
}, 0)
}

Expand Down
6 changes: 3 additions & 3 deletions src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type RendererEvents = {
drag: [relativeX: number]
dragstart: [relativeX: number]
dragend: [relativeX: number]
scroll: [relativeStart: number, relativeEnd: number]
scroll: [relativeStart: number, relativeEnd: number, scrollLeft: number, scrollRight: number]
render: []
rendered: []
}
Expand Down Expand Up @@ -105,7 +105,7 @@ class Renderer extends EventEmitter<RendererEvents> {
const { scrollLeft, scrollWidth, clientWidth } = this.scrollContainer
const startX = scrollLeft / scrollWidth
const endX = (scrollLeft + clientWidth) / scrollWidth
this.emit('scroll', startX, endX)
this.emit('scroll', startX, endX, scrollLeft, scrollLeft + clientWidth)
})

// Re-render the waveform on container resize
Expand Down Expand Up @@ -730,7 +730,7 @@ class Renderer extends EventEmitter<RendererEvents> {
const newScroll = this.scrollContainer.scrollLeft
const startX = newScroll / scrollWidth
const endX = (newScroll + clientWidth) / scrollWidth
this.emit('scroll', startX, endX)
this.emit('scroll', startX, endX, newScroll, newScroll + clientWidth)
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/wavesurfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export type WaveSurferEvents = {
/** When the user ends dragging the cursor */
dragend: [relativeX: number]
/** When the waveform is scrolled (panned) */
scroll: [visibleStartTime: number, visibleEndTime: number]
scroll: [visibleStartTime: number, visibleEndTime: number, scrollLeft: number, scrollRight: number]
/** When the zoom level changes */
zoom: [minPxPerSec: number]
/** Just before the waveform is destroyed so you can clean up your events */
Expand Down Expand Up @@ -275,9 +275,9 @@ class WaveSurfer extends Player<WaveSurferEvents> {
}),

// Scroll
this.renderer.on('scroll', (startX, endX) => {
this.renderer.on('scroll', (startX, endX, scrollLeft, scrollRight) => {
const duration = this.getDuration()
this.emit('scroll', startX * duration, endX * duration)
this.emit('scroll', startX * duration, endX * duration, scrollLeft, scrollRight)
}),

// Redraw
Expand Down

0 comments on commit 741f71c

Please sign in to comment.