I am new to angular js - trying to build an audio play using Aplayer
Task:- 1. Play music dynamically 2. On click of album get json data and add to aplayer
(function() {
'use strict';
angular.module('app', []);
angular
.module('app')
.directive('aplayer', aplayer);
function aplayer() {
return {
restrict: 'AC',
link: function(scope, element, attrs) {
// `element` is the angular element the directive is attached to
// APlayer need the native one
var nativeElement = element[0];
var ap1 = new APlayer({
element: nativeElement,
narrow: false,
autoplay: true,
showlrc: false,
mutex: true,
theme: '#e6d0b2',
preload: 'metadata',
mode: 'circulation',
music: {
title: attrs["playerTitle"],
author: attrs["playerAuthor"],
url: attrs["playerUrl"],
pic: attrs["playerPic"]
}
});
ap1.on('play', function() {
console.log('play');
});
ap1.on('play', function() {
console.log('play play');
});
ap1.on('pause', function() {
console.log('pause');
});
ap1.on('canplay', function() {
console.log('canplay');
});
ap1.on('playing', function() {
console.log('playing');
});
ap1.on('ended', function() {
console.log('ended');
});
ap1.on('error', function() {
console.log('error');
});
}
};
}
})();
<!doctype html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/aplayer/1.6.0/APlayer.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div class="aplayer"
data-player-title="Preparation"
data-player-author="Hans Zimmer/Richard Harvey"
data-player-url="http://devtest.qiniudn.com/Preparation.mp3"
data-player-pic="http://devtest.qiniudn.com/Preparation.jpg"></div>
</body>
</html>
How to pass music files dynamically to Aplayer on click of an album.
According to Aplayer source code, it's not possible to replace music track or playlist dynamically. API only expose setMusic
method which allow to choose track index in music playlist.
To display your albums, you need to load them first using a service which will call your tracks API.
Once loaded, you can inject them to your aplayer directive and choose the index of the track to play.
Here is a sample snippet with :
a musicService to handle your music library
a TrackController to load and display your music library
a modified aplayer directive to handle tracks and current track index
Note: I'm using free music from Free Music Archive for this demo.
(function() {
'use strict';
angular.module('app', []);
angular
.module('app')
.factory('musicService', ['$timeout', musicService])
.controller('TracksController', ['$scope', 'musicService', TracksController])
.directive('aplayer', aplayer);
function musicService($timeout) {
return {
loadTracks: function() {
// Simulate a 1500 ms $http api call
return $timeout(function() {
return [{
title: 'Procrastinating in the Sun',
author: 'The Spin Wires',
url: 'https://freemusicarchive.org/music/download/e7fee95c2d7f7b1ea8d4260850a6128842eb85a4',
pic: 'https://freemusicarchive.org/file/images/artists/The_Spin_Wires_-_20170510154106040.jpg?width=290&height=290'
},
{
title: 'осоле',
author: 'Kosta T',
url: 'https://freemusicarchive.org/music/download/0e4d722be7bd7ca334970b5407b3e5654b95f7a2',
pic: 'https://freemusicarchive.org/file/images/tracks/Track_-_2017050264944176?method=crop&width=290&height=290'
}
];
}, 1500);
}
}
}
function TracksController($scope, musicService) {
$scope.loadingTracks = true;
$scope.showPlayer = false;
musicService.loadTracks()
.then(function(tracks) {
// Once tracks are loaded, update scope
$scope.tracks = tracks;
$scope.loadingTracks = false;
});
$scope.play = function(trackIndex) {
$scope.trackIndex = trackIndex;
$scope.showPlayer = true;
}
}
function aplayer() {
return {
restrict: 'AC',
scope: {
tracks: '=',
trackIndex: '='
},
link: link
};
function link(scope, element, attrs) {
var player = new APlayer({
narrow: true,
mode: "order",
music: scope.tracks
});
// Watch for trackIndex changes
scope.$watch(
function(scope) {
// Return the "result" of the watch expression as it's more efficient
// @see http://www.bennadel.com/blog/2852-understanding-how-to-use-scope-watch-with-controller-as-in-angularjs.htm
return scope.trackIndex;
},
function(currentIndex, previousIndex) {
// As currentIndex is an integer, if(0) equals if(false)
// But we can use a regular expression to check it's an integer
if (/\d/.test(currentIndex)) {
player.setMusic(parseInt(currentIndex));
player.play();
}
});
}
}
})();
<!doctype html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/aplayer/1.6.0/APlayer.min.js"></script>
<style>
ul li {
list-style-type: none;
}
ul li * {
vertical-align: middle
}
</style>
</head>
<body ng-controller="TracksController">
<div ng-if="loadingTracks">Loading tracks, please wait...</div>
<ul>
<li ng-repeat="track in tracks">
<img ng-src="{{track.pic}}" width="64" height="64">
<button ng-click="play($index)">Play</button> {{track.author}} / {{track.title}}
</li>
</ul>
<div ng-if="tracks && showPlayer">
<h2>Now playing</h2>
<div>{{tracks[trackIndex].author}} / {{tracks[trackIndex].title}}</div>
<div class="aplayer" data-tracks="tracks" data-track-index="trackIndex"></div>
</div>
</body>
</html>