我在AngularJS应用程序中使用了一个使用D3.js和Web Audio API的音乐频率可视化器。
我在里面创建了一个自定义的bower组件,里面有一个指令和一个templateUrl html文件。
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(这里是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>
和这个audioPlayer指令在视图中的另一个html文件中使用,代码如下
<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>
这里audio-player标签中的src值可以从directive.js (directive的名字是audioPlayer)文件
我尝试在视图中打印{{audioFile}},它显示了每个音频索引的url,
问题是我如何在指令范围变量中获得src的值?我得到它的第一次点击,但当我点击另一个索引,范围没有得到更新的src值!!
我尝试重新加载指令,在html文件中设置一个标志
<div ng-if="recordingsCtrl.songChanged">
<audio-player crossorigin="anonymous" audio-file="recordingsCtrl.audioList[0].src"></audio-player>
</div>
,然后设置每个音频文件点击的超时功能,
function playAudio{
self.songChanged = false;
setTimeout(function() {
self.songChanged = true;
$scope.$apply();
}, 10);
}
对于第一次加载窗口,该指令将被绑定到html,然后如果我们想要改变指令的范围变量,我们可以通过重新加载指令来做到这一点,就像上面的
这是我们解决这个问题的方法之一,如果你们谁有更好的解决方案,请在下面回答。