Search code examples
javascripthtmlaudiocanvasimage-masking

Canvas Mask Help w/ custom audio player scrubber / waveform


I have two pngs, one white and the other red.

<img class="rangeHorizontal" id="seek"     src="http://i.imgur.com/hRHH9VO.png">
            <img id="seekFill" src="http://i.imgur.com/WoJggN0.png">

When the song it not playing it should be white, and when the song is going it should fill red as the song progresses, and also when scrubbed backwards and forwards respectively.

I have been able to muddle through most of the play functionality except the Canvas portion.

Currently the two pngs are overlays on top of each other and when the song plays the whole red png overlays on top, .. instead of just showing a portion,.. its pretty hard to explain but I have a fiddle so things become clearer.

https://jsfiddle.net/tallgirltaadaa/q9qgyob0/

The desired result would like this player, it also uses a two png method:

http://codecanyon.net/item/zoomsounds-neat-html5-audio-player/full_screen_preview/4525354?ref=hkeyjun

If anyone could help me out a bit I would love it.. I have been masking and trying to use canvas all morning with no luck.


Solution

  • There is a bit too much code to go through, but here is one technique use can use to draw a clipped version of an image. Implement as needed -

    Live Example

    At each timeupdate:

    • Canvas is cleared
    • The white bottom image is drawn in (you can scale these as you wish)
    • Progress is calculated (currentTime / duration)
    • The red top image is drawn in using the clipping arguments:

    ie.

    ctx.drawImage(image, sx, sy, sw, sh,  dx, dy, dw, dh);
    

    Full example code (had to replace the music due to the API usage) -

    var imgBg = new Image(),
        imgFg = new Image(),
        count = 2;
    imgBg.onload = imgFg.onload = init;
    imgBg.src = "http://i.imgur.com/hRHH9VO.png";
    imgFg.src = "http://i.imgur.com/WoJggN0.png";
    
    function init() {
      if (--count) return;   // makes sure both images are loaded
      
       var canvas = document.querySelector("canvas"),
           ctx = canvas.getContext("2d"),
           audio =  document.querySelector("audio");
      
      canvas.width = imgBg.naturalWidth;
      canvas.height = imgBg.naturalHeight;
      
      render();
      
      audio.volume = 0.5;
      audio.addEventListener("timeupdate", render);
      
      function render() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(imgBg, 0, 0);
        
        // calc progress
        var pst = audio.currentTime / audio.duration;
        
        // draw clipped version of top image
        if (pst > 0) {
          ctx.drawImage(imgFg, 0, 0, (canvas.width * pst)|0, canvas.height,  // source
                               0, 0, (canvas.width * pst)|0, canvas.height); // dst
        }
      }
    }
    body {background:#ccc}
    canvas {width:600px;height:auto}
    <audio src="https://raw.githubusercontent.com/epistemex/free-music-for-test-and-demo/master/music/kf_colibris.mp3" controls></audio>
    <canvas></canvas>