Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically create multiple wavesurfer objects with unique names

Not sure I'm wording this correctly but here is what I'm trying to do.

I am using a function to render multiple instances of wavesurfer on a page.

Out of the box this is straight forward, as you just declare each separate instance of wavesurfer :

var wavesurfer1 = WaveSurfer.create({
  container: domEl,
  barWidth: 3,
  .....

var wavesurfer2 = WaveSurfer.create({
  container: domEl,
  barWidth: 3,
  .....

But I'm preloading JSON stored waveform data and NOT loading any audio file at page load, only when a user clicks the play button should the audio file load. Also the amount of instances and their id's will be created dynamically.

I've got the logic working but I'm having trouble targeting each unique instance of wavesurfer as, well, they are not unique - hence my question, and I can't find any information on the official site (or git) about targeting individual instances. I would assume that it's possible by the container but can't find any info about how to do this, so I'm trying it another way.

In the function that renders each instance of wavesurfer we have this (domEl is being passed into the function and creates a unique div and id for each waveform container) :

var wavesurfer = WaveSurfer.create({
  container: domEl,
  barWidth: 3,
  waveColor: '#CCC',
  progressColor: 'white',
  backend: 'MediaElement',
  mediaType:'audio',
  height: 80,
  cursorColor: 'white',
  responsive: true,
  hideScrollbar: true
});

And the function that loads the actual audio :

$('.m-btn-player').on('click', function() {

  id = $(this).data("id");
  var url = "/play?id="+id;
  wavesurfer.load(url);
  wavesurfer.play();

})

This works, but as each instance of wavesurfer is declared as wavesurfer it loads the audio into every single instance no matter which play button is clicked.

What I thought I could do was declare each instance of wavesurfer in the render function with a dynamically generated name i.e :

// `id` is passed to the function

var wavesurfer+id = WaveSurfer.create({
container: domEl,
barWidth: 3,
....

Then :

wavesurfer+id.load(url);
wavesurfer+id.play();

But this doesn't work (and I don't even think it's possible from what I've read about dynamic variable names).

I've also read that I should possibly be using hashmaps for something like this but have no idea how to use them, so if that is the case, or you can see another way I can make this work I would really appreciate some pointers.

If this approach is entirely wrong how do I target multiple instances of wavesurfer without declaring the object name for each one? I can't find anything that explains how to do this anywhere.

like image 561
spice Avatar asked Jan 03 '23 08:01

spice


1 Answers

After much trial and error I cracked it.

You need to set up an object array :

var wavesurfer = [];

And then pass each individual id into it when creating each instance inside your render function :

function render(id, selector, peaks, url) {

  var domEl = document.createElement('div');
  domEl.setAttribute("id", "t-"+id);
  document.querySelector(selector).appendChild(domEl);

  trackid = "t"+id;

  wavesurfer[trackid] = WaveSurfer.create({
    container: domEl,
    barWidth: 3,
    waveColor: '#CCC',
    progressColor: 'white',
    backend: 'MediaElement',
    mediaType:'audio',
    height: 80,
    cursorColor: 'white',
    responsive: true,
    hideScrollbar: true
  });

  // Make sure you reference each method the same way...

  wavesurfer[trackid].drawBuffer();
  wavesurfer[trackid].load(url, peaks, false); //false prevents preload of audio file

  return wavesurfer[trackid];
}

Call the render function :

render(1, ".tk1", [....], 'http://example.com/file.mp3');

Then you can target each player using the object identifier, in this instance the id passed to the function was 1:

wavesurfer[t1].playPause();

So a use case could be :

<div class="tk1">
  <button type="button" onClick="wavesurfer['t1'].playPause();">PLAY</button>
  <script>
  render(1, ".tk1", [-0.39,0.4,-0.9,0.91,-0.32,0.34,-0.95,0.98,-0.54,0.74,-0.9,0.91,-0.33,0.37,-0.96,0.98,-0.9,0.91,-0.79,0.76,-0.95,0.95,-0.88,0.87,-0.91,0.94,-0.55,0.6,-0.97,0.96,-0.43,0.43,-0.91,0.91,-0.51,0.4,-0.98,0.94,-0.55,0.76,-0.91,0.91,-0.33,0.37,-0.98,0.98,-0.39,0.41,-0.92,0.91,-0.31,0.34], 'http://example.com/file.mp3');
  </script>
</div>

<div class="tk2">
  <button type="button" onClick="wavesurfer['t2'].playPause();">PLAY</button>
  <script>
  render(2, ".tk2", [-0.39,0.4,-0.9,0.91,-0.32,0.34,-0.95,0.98,-0.54,0.74,-0.9,0.91,-0.33,0.37,-0.96,0.98,-0.9,0.91,-0.79,0.76,-0.95,0.95,-0.88,0.87,-0.91,0.94,-0.55,0.6,-0.97,0.96,-0.43,0.43,-0.91,0.91,-0.51,0.4,-0.98,0.94,-0.55,0.76,-0.91,0.91,-0.33,0.37,-0.98,0.98,-0.39,0.41,-0.92,0.91,-0.31,0.34], 'http://example.com/file2.mp3');
  </script>
</div>
like image 132
spice Avatar answered Jan 13 '23 12:01

spice