Sabreena Sabreena - 2 months ago 7
Javascript Question

How to bind the src value to directive scope variable dynamically for each indices of an audio file array

I used a music frequency visualiser using D3.js and the Web Audio API in my AngularJS application.

I created a custom bower component inside that a directive and an templateUrl html file are there.

Directive.js



(function (angular) {
var ap=angular.module('audio-player-mod',[]);

ap.directive('audioPlayer', function () {
return {
restrict: 'EA',
scope: {
audioFile : "="
},
link: function (scope,element,attrs) {
$(document).ready(function () {

// scope.audios=scope.audioFile;
console.log(scope.audioFile);

var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var audioElement = document.getElementById('audioElement');
var audioSrc = audioCtx.createMediaElementSource(audioElement);
var analyser = audioCtx.createAnalyser();

// Bind our analyser to the media element source.
audioSrc.connect(analyser);
audioSrc.connect(audioCtx.destination);

//var frequencyData = new Uint8Array(analyser.frequencyBinCount);
var frequencyData = new Uint8Array(200);

var svgHeight = '500';
var svgWidth = '2000';
var barPadding = '1';

function createSvg(parent, height, width) {
return d3.select(parent).append('svg').attr('height', height).attr('width', width);
}

var svg = createSvg('body', svgHeight, svgWidth);

// Create our initial D3 chart.
svg.selectAll('rect')
.data(frequencyData)
.enter()
.append('rect')
.attr('x', function (d, i) {
return i * (svgWidth / frequencyData.length);
})
.attr('width', svgWidth / frequencyData.length - barPadding);

// Continuously loop and update chart with frequency data.
function renderChart() {
requestAnimationFrame(renderChart);

// Copy frequency data to frequencyData array.
analyser.getByteFrequencyData(frequencyData);

// Update d3 chart with new data.
svg.selectAll('rect')
.data(frequencyData)
.attr('y', function(d) {
return svgHeight - d;
})
.attr('height', function(d) {
return d;
})
.attr('fill', function(d) {
return 'rgb(0, 0, ' + d + ')';
});
}

// Run the loop
renderChart();

});


},
templateUrl: 'bower_components/audio-player/view/audio-player.html'
};
});

})(angular);





templateUrl.html (here it is audio-player.html)



<div>
<audio id="audioElement" crossorigin="anonymous" src="audioFile"></audio>
<div>
<button onclick="document.getElementById('audioElement').play()">Play</button>
<button onclick="document.getElementById('audioElement').pause()">Pause</button>
<button onclick="document.getElementById('audioElement').volume+=0.1">Increase Volume</button>
<button onclick="document.getElementById('audioElement').volume-=0.1">Decrease Volume</button>
</div>
</div>





and this audioPlayer directive is used in another html file in the views,code shown below



<div class="player-region" ng-if="recordingsCtrl.audioList[0].src">
<div>
<div class="player-control">
<div class="player-control-bottom">
<audio-player crossorigin="anonymous" audio-file="recordingsCtrl.audioList[0].src"></audio-player>
</div>
</div>
</div>
</div>





here the src value in the audio-player tag can be accessed from the directive.js (directive's name is audioPlayer) file ,

i tried printing {{audioFile}} in the view ,and it is showing the url for each indices of audios,

The problem is how can i get the value of src in the directive scope variable ? I get it for the first click, but when i click on another index ,scope is not getting updated with that src value!!

Answer

I tried reloading the directive , set a flag in html file

<div ng-if="recordingsCtrl.songChanged">
        <audio-player  crossorigin="anonymous" audio-file="recordingsCtrl.audioList[0].src"></audio-player>
      </div>

and then set a timeout function on click of every audio files,

function playAudio{
self.songChanged = false;
      setTimeout(function() {
        self.songChanged = true;
        $scope.$apply();
      }, 10);
  
  }

For the first time window loaded,the directive will be bind to html then if we want to change the directive scope variable we can do it by reloading the directive just like above

this is one of the way we can solve the problem, if any one of you have better solutions please answer below.