Изменение атрибута "src" источника html5 не влияет на угловые
У меня есть список аудиофайлов, представленных в виде ссылок и <audio>
html5. Каждая ссылка вызывает функцию, которая меняет src тега <source>
в <audio>
:
<audio controls="controls" preload="none">
<source type="audio/mpeg" src="{{selectedSongPath}}"/>
</audio>
...
<div class="songEntry" ng-repeat="song in songs">
<a href="" ng-click="songSelect(song.path)">{{song.name}}</a>
</div>
...
$scope.songSelect = function(songPath) {
$scope.selectedSongPath = songPath;
}
Я вижу изменение src, но ничего не воспроизводится. Пути в порядке; если я инициализирую src одним из путей, плеер работает.
Что я делаю неправильно?
Ответы
Ответ 1
Вот пара подходов angular:
1) Используйте ng-src= вместо src=
Документы angular объясняют, почему это работает:
http://docs.angularjs.org/api/ng.directive:ngSrc
На этапе компиляции angular расширит элемент, включив в него правильный атрибут src=.
Это изменит атрибут src для аудио-элемента HTML5, но, к сожалению, этого недостаточно для создания новой песни. Вам нужно подтолкнуть аудио-элемент к тому, чтобы сделать что-то, вызвав метод .play().
Отстой: (
Дальнейший взлом по этому же пути предполагает использование DOM-манипуляции внутри контроллера. Это, как правило, признак того, что это неправильное решение.
Лучшее решение - использовать службы!!!
2) Аудио с помощью службы angular
// Define a simple audio service
mpApp.factory('audio',function ($document) {
var audioElement = $document[0].createElement('audio'); // <-- Magic trick here
return {
audioElement: audioElement,
play: function(filename) {
audioElement.src = filename;
audioElement.play(); // <-- Thats all you need
}
// Exersise for the reader - extend this service to include other functions
// like pausing, etc, etc.
}
});
Теперь, в вашем контроллере (-ах), вы можете вводить "аудио" и делать все, что вам нужно с ним.
например:
function myAstoundingAudioCtrl($scope, audio) { //<-- NOTE injected audio service
$scope.songSelect = function(songPath) {
audio.play(songPath); // <--- Thats All You Need !
}
}
Теперь вы можете добавить "звук" в качестве параметра к любому из ваших контроллеров, которые должны иметь возможность
изменить музыку и использовать тот же самый вызов API, определенный здесь.
Будучи "службой", для всего приложения существует только один экземпляр. Все вызовы на "звук" указывают на один и тот же объект. Это справедливо для всех служб в angular. Только то, что нам нужно в этом случае.
Служба создает невидимый элемент HTML5 в корневом документе вашего приложения, поэтому нет необходимости добавлять тег в свои представления в любом месте. Это добавляет бонус к сохранению воспроизведения песни, пока пользователь переходит к различным представлениям.
См. http://docs.angularjs.org/api/ng. $document для определения службы $document.
Надеюсь, что поможет спарить:)
Ответ 2
У меня была та же проблема, даже после использования $sce.trustAsResourceUrl, а затем я понял, что проблема связана с HTML. Источник должен войти в сам тег аудио:
<audio controls data-ng-src="{{yourTrustedUrl}}" ></audio>
Ответ 3
<audio ng-src="{{getAudioUrl()}}" audioplayer controls></audio>
$scope.getAudioUrl = function() {
return $sce.trustAsResourceUrl('your url');
};
Это работает для меня, вам нужно обезопасить вас.
Ответ 4
ngSrc не работает для видео в AngularJS, работает только для изображения. Мое решение:
в представлении:
<video controls="controls" name="Video Name" ng-src="{{getVideoUrl()}}"></video>
в контроллере:
$scope.getVideoUrl=function(){
return $sce.trustAsResourceUrl("media/"+$scope.groupedProjList[$scope.routeId].CONTACTNAME+".mp4");
};
замените мой URL следующим образом:
$sce.trustAsResourceUrl('your Url');
Не забудьте добавить $sce
в свой модуль:
angular.module('myApp.controllers', [])
.controller('MyCtrl1', function($scope,$http,$routeParams,$sce) {
Ответ 5
У меня была аналогичная проблема с загрузкой источников видео в меню выпадающего меню. Я обнаружил, что $scope.$apply();
было все, что мне нужно было добавить. Не успел взять ваш код и протестировать эту реализацию, но я бы рекомендовал попробовать:
$scope.songSelect = function(songPath) {
$scope.selectedSongPath = songPath;
$scope.$apply();
}
Там какой-то спор об использовании $scope.$apply()
в отношении обработки ошибок. Я считаю, что правильная реализация на самом деле выглядит следующим образом:
$scope.songSelect = function(songPath) {
$scope.$apply(function() {
$scope.selectedSongPath = songPath;
});
}
Это предположительно лучше справляется, если songPath
возвращает undefined; увы, я не могу найти ссылку, где я узнал этот трюк. Если я это сделаю, я отправлю его в качестве комментария к этому ответу.
Надеюсь, что это поможет:)
Ответ 6
Вы также можете использовать это:
<div ng-bind-html-unsafe="audioPlayer"></div>
На вашем контроллере:
$scope.audioPlayer="<br /><audio controls><source src=\""+ audiosource + "\" type=\"audio/mpeg\"> Your browser does not support the audio element. </audio>"
Внимание:
Вы должны использовать эту директиву, только если директива ngBindHtml тоже ограничительный и когда вы абсолютно доверяете источнику контента вы привязываетесь к.
далее здесь
Ответ 7
Подход @SteveOC 64 связан с созданием нового экземпляра Audio. Если у вас уже есть тег Audio, например
<audio id="audio" controls></audio>
Вы можете попробовать приведенный ниже код
app.factory('audio', function($document) {
var audioElement = $document[0].getElementById('audio');
audioElement.autoPlay = true; // as per your requirement
return {
audioElement: audioElement,
play: function(filename) {
audioElement.src = filename;
audioElement.play();
},
resume: function() {
audioElement.play();
},
pause: function() {
audioElement.pause();
},
stop: function() {
audioElement.pause();
audioElement.src = audioElement.currentSrc; /** http://stackoverflow.com/a/16978083/1015046 **/
},
incVol: function() {
if (audioElement.volume < 1) {
audioElement.volume = (audioElement.volume + 0.1).toFixed(2);
}
return audioElement.volume;
},
decVol: function() {
if (audioElement.volume > 0) {
audioElement.volume = (audioElement.volume - 0.1).toFixed(2);
}
return audioElement.volume;
},
timer: function(callback) {
audioElement.ontimeupdate = function() {
callback(audioElement.duration, audioElement.currentTime)
};
},
}
});
И в вашем контроллере после инъекции audio
factory вы можете называть его как
audio.play('/api/resource?resource=' + uri);
если это событие управляется, как в звуке воспроизведения при нажатии другого элемента
$scope.$apply(function() {
$scope.audioPlayer = true;
audio.play('/api/resource?resource=' + uri);
$scope.isAudioPlaying = true;
});
И если кто-то ищет видео factory:
HTML
<video id="video" controls></video>
Factory
app.factory('video', function($document) {
var videoElement = $document[0].getElementById('video');
videoElement.autoPlay = true;
return {
videoElement: videoElement,
play: function(filename) {
videoElement.src = filename;
videoElement.play();
},
resume: function() {
videoElement.play();
},
pause: function() {
videoElement.pause();
},
stop: function() {
videoElement.pause();
videoElement.src = videoElement.currentSrc; /** http://stackoverflow.com/a/16978083/1015046 **/
},
incVol: function() {
if(videoElement.volume < 1) {
videoElement.volume = (videoElement.volume + 0.1).toFixed(2);
}
return videoElement.volume;
},
decVol: function() {
if(videoElement.volume > 0) {
videoElement.volume = (videoElement.volume - 0.1).toFixed(2);
}
return videoElement.volume;
},
timer: function(callback) {
videoElement.ontimeupdate = function() {
callback(videoElement.duration, videoElement.currentTime)
};
},
}
});
И вы можете вызвать его как video.play('/api/resource?resource=' + uri);
Надеюсь, это поможет!
Ответ 8
Решение, которое я нашел, - загрузить видео, как только вы получите URL-адрес видео от вызова ajax.
var video = angular.element('#video_id');
video.load();
Ответ 9
Никогда не пробовался с тегом audio
, но src
должен быть интерполирован, поэтому он должен быть между {{}}
.
<audio controls="controls" preload="none">
<source type="audio/mpeg" src="{{selectedSongPath}}"/>
</audio>
Вы уже пробовали это?
Ответ 10
После изменения src вы также должны загрузить этот файл, поэтому попробуйте добавить к своей функции songselect
после $scope.selectedSongPath = songPath;
следующее:
$scope.load();
Я не знаю, что такое $scope в вашем случае, но метод load()
должен выполняться внутри объекта вашего звукового тега. В простой JS это будет выглядеть так:
<audio id="audio-tag" controls="controls" preload="none"> //need the ID to get element
<source type="audio/mpeg" src="{{selectedSongPath}}"/>
</audio>
....
$scope.selectedSongPath = songPath; //you're changing the src
document.getElementById("audio-tag").load(); //here you load the file (you need equivalent in your framework)
Надеюсь, что это поможет.
Ответ 11
Раньше я использовал ngAudio и сталкивался с проблемой одновременного воспроизведения нескольких аудиофайлов. Когда вы пытались использовать аудиотекст HTML5, вместо того, чтобы иметь аудио и источник как 2 тега, только 1 тег решил мою проблему.
<audio controls ng-src='{{trusted_url }}'></audio>