katspaugh / wavesurfer.js

Audio waveform player
https://wavesurfer.xyz
BSD 3-Clause "New" or "Revised" License
8.7k stars 1.62k forks source link

Get multiple regions on mouse over #1573

Closed zapfdk closed 1 year ago

zapfdk commented 5 years ago

Wavesurfer.js version(s):

2.1.1

Browser version(s):

All

Hi, I have some annotations for regions, that can overlap. Now I want to retrieve all the regions under the cursor. When using the mouse enter event from the regions plugins, only one region is returned, which doesn't help me a lot. So how could I achieve that? Or is there a way to get the current position (in sec or px) of the mouse cursor on the waveform from which I could calculate the corresponding regions?

One part of the problem I forgot to mention: When the mouse enters a region, that is overlapped by another region, no mouseenter event is triggered at all, only for the overlapping event.

thijstriemstra commented 5 years ago

@moritzvieli any idea about this regions issue?

aburai commented 5 years ago

i think it is no problem to get x,y position on mouseover (like cursor) and find all regions my way is a gantt like diagram on top of the waveform that shows the regions

moritzvieli commented 5 years ago

Indeed, this is the way, html behaves. And I agree with @aburai. It should be possible to calc the position the way the cursor does it: https://github.com/katspaugh/wavesurfer.js/blob/master/src/plugin/cursor.js -> _onMousemove

zapfdk commented 5 years ago

I solved this by adding a onmousemove listener on the wavesurfer container, and getting the current x position:

waveSurferEl.onmousemove = function(e) {
        var x = e.pageX - this.offsetLeft;
}

Then calculating the corresponding second for the x-value, then iterating all regions and see if they match

let mousePosSec = currentLeftSec + (currentRightSec-currentLeftSec)*(x/viewWidth);
    let activeLabels = [];
    for (let region of regions){
        if ((mousePosSec >= region["start"]) && mousePosSec <= region["end"]){
            activeLabels.push(region.data);
        }
    }
    return new Set(activeLabels);

With currentLeftSec/currentRightSec the borders of the current waveform view, calculated in an onscroll event and viewWidth being document.getElementById("waveform").offsetWidth

The regions list is a list of the options objects that are passed to the addRegion method.

This works pretty good, but I think this could be implemented into the Regions plugin as an addition to the mouseover event or something like that.

thijstriemstra commented 5 years ago

This works pretty good, but I think this could be implemented into the Regions plugin as an addition to the mouseover event or something like that.

@zapfdk feel free to open a pull request with this change!