Created Regions Not Removed When Using 'Regions.Remove()'
Closed this issue · 7 comments
Bug description
Attempting to ensure that only one region can be created at a time. I created code that removes regions, however, that are still visible on screen although the list of regions has been reduced.
Utilizing region.remove() does not visibly remove regions created with 'regions.addRegion'
I thought it was possibly my environment but I pasted the minimal code snippet into https://wavesurfer.xyz/examples/?regions.js and obtained the same behavior.
Environment
- Browser: Firefox
Minimal code snippet
regions.addRegion({{
start: 12,
end: 17,
content: 'Drag me',
color: 'rgba(0, 255, 0, 0.1)
resize: false,
}})
regions.enableDragSelection({{
color: 'rgba(255, 0, 0, 0.1)',
drag: false,
resize: true,
}})
var regionTest = [];
// Listen for region creation
regions.on('region-created', (region) => {{
const now = Date.now();
// Add the new region with its timestamp
regionTest.push({ region, timestamp: now });
// If there is more than one recent region, remove all but the last
if (regionTest.length > 1) {{
const regionsToRemove = regionTest.slice(0, -1); // All but the last
console.log('regionsToRemove', regionsToRemove);
// Remove each region except the last
regionsToRemove.forEach(item => {{
console.log('removing region', item.region);
item.region.remove(); // Remove the region from Wavesurfer
}});
// Keep only the last region in the array
regionTest = [regionTest[regionTest.length - 1]];
}}
}});
Expected result
Removal of all regions except the last created region, regardless of whether it was created with '.addRegion' or user drag creation associated with enableDragSelection.
Additionally, any drag creation of a region would remove previously created regions, leaving only the newly created region.
Obtained result
Regions that were created with 'regions.addRegion' remain on screen
Screenshots
Same here
As workaround I clear all regions and then add every region that should exit
The code you pasted works as intended for me:
https://wavesurfer.xyz/examples/?5cc63deca8da61df67c85b01d4004247
Tested in Chrome and Firefox.
I borrowed the portion of https://wavesurfer.xyz/examples/?regions.js example that creates the regions.
The full code shown will remove the most recently created region when you perform a drag selection to create a region but the other existing regions remain visible.
I am using firefox 132.0.2 (64-bit) on Ubuntu.
<script src="https://unpkg.com/wavesurfer.js"></script>
<script src="https://unpkg.com/wavesurfer.js@7"></script>
<script src="https://unpkg.com/wavesurfer.js@7/dist/plugins/regions.min.js"></script>
My actual code is pulling the javascript but it behaves the same way as the code below
// Regions plugin
import WaveSurfer from 'wavesurfer.js'
import RegionsPlugin from 'wavesurfer.js/dist/plugins/regions.esm.js'
// Initialize the Regions plugin
const regions = RegionsPlugin.create()
// Create a WaveSurfer instance
const ws = WaveSurfer.create({
container: '#waveform',
waveColor: 'rgb(200, 0, 200)',
progressColor: 'rgb(100, 0, 100)',
url: '/examples/audio/audio.wav',
plugins: [regions],
})
// Give regions a random color when they are created
const random = (min, max) => Math.random() * (max - min) + min
const randomColor = () => `rgba(${random(0, 255)}, ${random(0, 255)}, ${random(0, 255)}, 0.5)`
// Create some regions at specific time ranges
ws.on('decode', () => {
// Regions
regions.addRegion({
start: 0,
end: 8,
content: 'Resize me',
color: randomColor(),
drag: false,
resize: true,
})
regions.addRegion({
start: 9,
end: 10,
content: 'Cramped region',
color: randomColor(),
minLength: 1,
maxLength: 10,
})
regions.addRegion({
start: 12,
end: 17,
content: 'Drag me',
color: randomColor(),
resize: false,
})
// Markers (zero-length regions)
regions.addRegion({
start: 19,
content: 'Marker',
color: randomColor(),
})
regions.addRegion({
start: 20,
content: 'Second marker',
color: randomColor(),
})
})
regions.enableDragSelection({
color: 'rgba(255, 0, 0, 0.1)',
})
regions.on('region-updated', (region) => {
console.log('Updated region', region)
})
var regionTest = [];
// Listen for region creation
regions.on('region-created', (region) => {{
const now = Date.now();
// Add the new region with its timestamp
regionTest.push({ region, timestamp: now });
// If there is more than one recent region, remove all but the last
if (regionTest.length > 1) {{
const regionsToRemove = regionTest.slice(0, -1); // All but the last
console.log('regionsToRemove', regionsToRemove);
// Remove each region except the last
regionsToRemove.forEach(item => {{
console.log('removing region', item.region);
item.region.remove(); // Remove the region from Wavesurfer
}});
// Keep only the last region in the array
regionTest = [regionTest[regionTest.length - 1]];
}}
}});
/*
<html>
<div id="waveform"></div>
<p>
<label>
<input type="checkbox" checked="${loop}" />
Loop regions
</label>
<label style="margin-left: 2em">
Zoom: <input type="range" min="10" max="1000" value="10" />
</label>
</p>
<p>
📖 <a href="https://wavesurfer.xyz/docs/classes/plugins_regions.RegionsPlugin">Regions plugin docs</a>
</p>
</html>
*/
That's because you're adding and immediately removing regions. Adding a small timeout inside the region-created
callback will help.
I may not be doing it in a way that you suggested. I added a one second delay to see the outcome.
All of the regions were not removed. The goal is to have only one region be active, even when multiple ranges exist.
var regionTest = [];
// Listen for region creation
regions.on('region-created', (region) => {
const now = Date.now();
// Add the new region with its timestamp
regionTest.push({ region, timestamp: now });
// If there is more than one recent region, remove all but the last
if (regionTest.length > 1) {
const regionsToRemove = regionTest.slice(0, -1); // All but the last
console.log('regionsToRemove', regionsToRemove);
// Delay the removal of regions except the last one
setTimeout(() => {
// Remove each region except the last
regionsToRemove.forEach(item => {
console.log('removing region', item.region);
item.region.remove(); // Remove the region from Wavesurfer
});
// Keep only the last region in the array
regionTest = [regionTest[regionTest.length - 1]];
}, 1000); // 1000ms delay (1 second)
}
});
Jackpot --- What you said worked, I just had to think about it differently
var regionTest = [];
// Listen for region creation
regions.on('region-created', (region) => {
const now = Date.now();
// Add the new region with its timestamp
regionTest.push({ region, timestamp: now });
// If there is more than one recent region, remove all but the last
if (regionTest.length > 1) {
const regionsToRemove = regionTest.slice(0, -1); // All but the last
console.log('regionsToRemove', regionsToRemove);
// Remove each region with a delay
regionsToRemove.forEach((item, index) => {
const delay = 50 * (index + 1); // Delay increases for each region removed (e.g., 1s, 2s, 3s)
setTimeout(() => {
console.log('removing region', item.region);
item.region.remove(); // Remove the region from Wavesurfer
}, delay);
});
// Keep only the last region in the array
regionTest = [regionTest[regionTest.length - 1]];
}
});
Cool! I'll keep this issue open because ideally it should work w/o a delay. I suspect the root cause is a virtualized rendering.