Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: [Zoom] Performance improvements (especially w/ trackpad zoom) #3396

Merged
merged 4 commits into from
Dec 16, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 45 additions & 16 deletions src/plugins/zoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* Zoom in or out on the waveform when scrolling the mouse wheel
*
* @author HoodyHuo (https://github.com/HoodyHuo)
* @author Chris Morbitzer (https://github.com/cmorbitzer)
* @author Sam Hulick (https://github.com/ffxsam)
*
* @example
* // ... initialising wavesurfer with the plugin
Expand All @@ -20,11 +22,24 @@
import { BasePlugin, BasePluginEvents } from '../base-plugin.js'

export type ZoomPluginOptions = {
scale?: number // the amount of zoom per wheel step, e.g. 0.5 means a 50% magnification per scroll
maxZoom?: number // the maximum pixels-per-second factor while zooming
/**
* The amount of zoom per wheel step, e.g. 0.5 means a 50% magnification per scroll
*
* @default 0.5
*/
scale?: number
maxZoom?: number // The maximum pixels-per-second factor while zooming
/**
* The amount the wheel or trackpad needs to be moved before zooming the waveform. Set this value to 0 to have totally
* fluid zooming (this has a high CPU cost).
*
* @default 10
*/
deltaThreshold?: number
}
const defaultOptions = {
scale: 0.5,
deltaThreshold: 10,
}

export type ZoomPluginEvents = BasePluginEvents
Expand All @@ -33,6 +48,7 @@ class ZoomPlugin extends BasePlugin<ZoomPluginEvents, ZoomPluginOptions> {
protected options: ZoomPluginOptions & typeof defaultOptions
private wrapper: HTMLElement | undefined = undefined
private container: HTMLElement | null = null
private accumulatedDelta = 0

constructor(options?: ZoomPluginOptions) {
super(options || {})
Expand All @@ -59,20 +75,33 @@ class ZoomPlugin extends BasePlugin<ZoomPluginEvents, ZoomPluginOptions> {
// prevent scrolling the sidebar while zooming
e.preventDefault()

const duration = this.wavesurfer.getDuration()
const oldMinPxPerSec = this.wavesurfer.options.minPxPerSec
const x = e.clientX
const width = this.container.clientWidth
const scrollX = this.wavesurfer.getScroll()
const pointerTime = (scrollX + x) / oldMinPxPerSec
const newMinPxPerSec = this.calculateNewZoom(oldMinPxPerSec, -e.deltaY)
const newLeftSec = (width / newMinPxPerSec) * (x / width)
if (newMinPxPerSec * duration < width) {
this.wavesurfer.zoom(width / duration)
this.container.scrollLeft = 0
} else {
this.wavesurfer.zoom(newMinPxPerSec)
this.container.scrollLeft = (pointerTime - newLeftSec) * newMinPxPerSec
// Update the accumulated delta...
this.accumulatedDelta += -e.deltaY

// ...and only scroll once we've hit our threshold
if (this.options.deltaThreshold === 0 || Math.abs(this.accumulatedDelta) >= this.options.deltaThreshold) {
const duration = this.wavesurfer.getDuration()
const oldMinPxPerSec = this.wavesurfer.options.minPxPerSec
const x = e.clientX
const width = this.container.clientWidth
const scrollX = this.wavesurfer.getScroll()
const pointerTime = (scrollX + x) / oldMinPxPerSec
const newMinPxPerSec = this.calculateNewZoom(
oldMinPxPerSec,
this.options.deltaThreshold > 0 ? this.accumulatedDelta : -e.deltaY,
)
ffxsam marked this conversation as resolved.
Show resolved Hide resolved
const newLeftSec = (width / newMinPxPerSec) * (x / width)

if (newMinPxPerSec * duration < width) {
this.wavesurfer.zoom(width / duration)
this.container.scrollLeft = 0
} else {
this.wavesurfer.zoom(newMinPxPerSec)
this.container.scrollLeft = (pointerTime - newLeftSec) * newMinPxPerSec
}

// Reset the accumulated delta
this.accumulatedDelta %= this.options.deltaThreshold
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it can probably be just set to 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gonna rework some of this. I'll mark the PR as ready for review once I think it's in a good spot.

}
}

Expand Down