Search code examples
javascriptjqueryember.jssoundmanager2jquery-knob

Knob.js as a progressbar for Soundmanager2


I am trying to use Knob.js (http://anthonyterrien.com/knob/) as a progress bar. I have found code for soundmanager2

$(".progBar").css('width', ((this.position/this.duration) * 100) + '%');

That works for a normal div width progress bar, but obviously with Knob, we must alter the value of the input.

I have seen those following code for updating the input value, but am unable to get it to properly work.

$(function() {
 $(".dial").knob({
  'draw' : function () { 
    $(this.i).val(this.cv + '%')
  }
 })
})

Some context of where my code is coming from... it is a music site where there are multiple songs, each with its own Knob circle. Each knob input has a unique ID of knob-###, or the variable 'knob_ID'

Here my entire code:

play: function(){ 
   var track_id = this.get('id');
   var knobID = $("#knob-" + track_id);
   var mySound = soundManager.createSound({
      id: track_id,
      url: 'mp3/path.mp3',
      autoplay: false,
      whileplaying: function() {
         var percentage = $((this.position/this.duration) * 100);
            $('#positionBar').css('width', ((this.position/this.duration) * 100) + '%'); 
            console.log(percentage);
            knobID.knob({
              'draw' : function () {
                 $(this.i).val(percentage + '%')
               }
            });
         },
    });
}

Solution

  • Here is a rough demo of updating the knob plugin as sound manager plays a file. You may need to do some more customization to make it a fully reusable and configurable component.

    SoundKnob2 view

    App.SoundKnob2 = Em.View.extend({
      knobInput: null,
      sound: null,
      playState: false,
      playStateLabel: function() {
        return this.get('playState')? 'PAUSE' : 'PLAY';
      }.property('playState'),
    
      initSound: function() {
        soundManager.setup({
      preferFlash: true,
          url: '//cdn.jsdelivr.net/soundmanager2/2.97a.20131201/cors/',
          onready: function() {
            var mySound = soundManager.createSound({
              autoLoad: true,
              autoPlay: false,
              id: 'aSound',
              url: 'http://www.schillmania.com/projects/soundmanager2/demo/_mp3/rain.mp3'
            });
    
            this.set('sound', mySound);
          }.bind(this),
          ontimeout: function() {
            console.log('timeout');
          }
        });
      }.on('init'),
    
      didInsertElement: function() {
        var knobInput = this.$().find('input');
        knobInput.knob({displayInput: false});
        this.set('knobInput', knobInput);
        //knobInput.val(50).trigger('change');
      },
    
      actions: {
        toggle: function() {
          this.toggleProperty('playState');
          var knob = this.get('knobInput');
    
          if(this.get('playState')) { 
            this.get('sound').play({
              onfinish: function() {
                knob.val(0).trigger('change');
                this.toggleProperty('playState');
              }.bind(this),
              whileplaying: function() {
                console.log(this.position);
                var pos = (this.position/ this.duration) * 100;
                knob.val(pos).trigger('change');
              }
            });
          } else {
            this.get('sound').pause();
          }
        }
      }
    });
    

    It can be used in a template like

    {{#view App.SoundKnob2 class="sound-knob2"}}
        <input />
        <button {{action 'toggle' target="view"}}>{{view.playStateLabel}}</button>
    {{/view}}