Home > OS >  How can I place a rectangle over a javascript rendered div?
How can I place a rectangle over a javascript rendered div?

Time:09-22

I am working with a waveform display/play library called wavesurfer. In the snippet that I created below, I have two such wavesurfer objects rendered and placed inside "container" type div elements. I would like to place my own rectangle over one of these wavesurfer objects, and control it's position using javascript.

My problem is I do not want to use absolute coordinates referenced for the browser window. I want to use relative coordinates based on the position within the wavesurfer object. Furthermore, as you can see, the rectangle is not overlayed over the waveform, even if I place it within the same div container.

I am new to javascript and realize that this could be a very basic question about overlaying shapes on top of things like pictures, but so far I haven't been able to find a solution that works for the waveform objects I am working with.

var wavesurfer = WaveSurfer.create({
  container: "#waveform",
  waveColor: "darkorange",
  progressColor: "skyblue",
  interact: false
});

wavesurfer.load("https://ia902606.us.archive.org/35/items/shortpoetry_047_librivox/song_cjrg_teasdale_64kb.mp3");


var wavesurfer2 = WaveSurfer.create({
  container: "#waveform2",
  waveColor: "silver",
  progressColor: "gainsboro",
  interact: false
});

wavesurfer2.load(  "https://ia902606.us.archive.org/35/items/shortpoetry_047_librivox/song_cjrg_teasdale_64kb.mp3"
);
<body>
  <script src="https://unpkg.com/wavesurfer.js"></script>
  <script src="https://unpkg.com/wavesurfer.js/dist/wavesurfer.min.js"></script>
  <script src="https://unpkg.com/wavesurfer.js/dist/plugin/wavesurfer.regions.min.js"></script>
  
<div class="container" style="display: flex">
  <div id="waveform" style="width:60%"></div>
</div>

<div class="container" style="display: flex">
  <div id="waveform2" style="width:60%"></div>
</div>

  <div>
    <input type="range" id="slider" name="range_slider" min="0" max="11">
    <label for="range_slider">Range Slider</label>
  </div>
  
  
  <div id="selector">
      <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
        <rect x="10" y="10" width="50" height="100" stroke="black" stroke-width="5" fill="none" />
      </svg>
    </div>

CodePudding user response:

You can use getBoundingClientRect to get the offset height and the offset left of the desired element, based on these values you can easly position any elements relatively to these values.

As described here: https://stackoverflow.com/a/52477551/7457356

CodePudding user response:

A slightly different approach would be to put a pseudo element on each waveform (or on whichever waveform you want).

This can then be positioned in % terms, the % being relative to the width of the waveform.

This snippet draws the rectangle by putting a border round the pseudo element but it could have an image as the background if a less simple shape is required.

A class waveform is introduced to make it simpler to style these elements.

var wavesurfer = WaveSurfer.create({
  container: "#waveform",
  waveColor: "darkorange",
  progressColor: "skyblue",
  interact: false
});

wavesurfer.load("https://ia902606.us.archive.org/35/items/shortpoetry_047_librivox/song_cjrg_teasdale_64kb.mp3");


var wavesurfer2 = WaveSurfer.create({
  container: "#waveform2",
  waveColor: "silver",
  progressColor: "gainsboro",
  interact: false
});

wavesurfer2.load("https://ia902606.us.archive.org/35/items/shortpoetry_047_librivox/song_cjrg_teasdale_64kb.mp3");
.waveform {
  position: relative;
}

.waveform::before {
  content: '';
  width: 20px;
  height: 50px;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  border: solid 5px;
  left: var(--left);
}

#waveform {
  --left: 60%;
}

#waveform2 {
  --left: 8%;
}
<body>
  <script src="https://unpkg.com/wavesurfer.js"></script>
  <script src="https://unpkg.com/wavesurfer.js/dist/wavesurfer.min.js"></script>
  <script src="https://unpkg.com/wavesurfer.js/dist/plugin/wavesurfer.regions.min.js"></script>

  <div class="container" style="display: flex">
    <div id="waveform" class="waveform" style="width:60%"></div>
  </div>

  <div class="container" style="display: flex">
    <div id="waveform2" class="waveform" style="width:60%"></div>
  </div>

  <div>
    <input type="range" id="slider" name="range_slider" min="0" max="11">
    <label for="range_slider">Range Slider</label>
  </div>

CSS variables have been used to set the distance along a waveform that the selector is to sit. For any particular waveform element this can be changed by setting the style --left property e.g. element.style.setProperty('--left', '60%');

  • Related