Я пытаюсь интегрировать библиотеку p5.js в мое приложение AngularJS, чтобы мой код выполнялся в директиве.
В моих простых файлах JavaScript я могу запустить метод draw () после импортаглобальная библиотека p5.
Мой оригинальный код (не проблема):
var mic
var playButton
var volHistory = []
var micIsOn = false
function setup(){
createCanvas(400, 150)
createButtons()
mic = new p5.AudioIn()
}
function draw(){
background(245)
stroke(0, 109, 203)
//populate volHistory
if(micIsOn){
var vol = mic.getLevel()
//check to see if array is empty, if it is empty we do not want to push 0 volume
if(volHistory.length > 0 && vol > 0){
volHistory.push(vol)
//if recording has started, we can now take in vol
} else if(vol > 0) {
volHistory.push(vol)
console.log(volHistory.length)
}
}
//iterate through volHistory and draw
fill(0, 109, 203)
var barWidth = 2;
var offsetWidth = 5;
var offset = 5;
for(var i = 0; i < volHistory.length; i++){
var barHeight = map(volHistory[i], 0, 1, 1, height)
rect(i + offset, (height/2.0) - (barHeight/2.0), barWidth, barHeight, 15);
offset += offsetWidth;
}
//moves wavelength 1 index at a time and account for bar width and offset width
if(volHistory.length * (offsetWidth + barWidth) > width){
volHistory.splice(0, 1)
}
//draw vertical line
stroke(250, 30, 100)
line(volHistory.length + offset, 0, volHistory.length + offset, height)
}
function createButtons(){
playButton = createButton("<img style='width: 50px' src='playbutton.png'/>")
playButton.mousePressed(toggleRecord)
playButton.position(162, 50)
playButton.style("background-color", color(0,0,0,0))
playButton.style("border", 0)
}
//toggle recording of audio
function toggleRecord(){
if(!micIsOn){
mic.start()
micIsOn = true
} else {
mic.stop()
micIsOn = false
}
}
Приведенный выше код позволяет мне создать визуализатор звука, который подключается к микрофону пользователя, рисуяхолст, который отображает уровень их звука.Выглядит примерно так:
Однако, когда я пытаюсь использовать библиотеку в своей директиве Angular, я не могу заставить метод draw () работать так, как ожидается.Функция draw () не работает непрерывно, как вне директивы Angular.
Самое близкое, что я получил, чтобы заставить это работать, - это создание $watch
для переменной, чтобы отследить, является ли пользователь записывающим пользователем,Если isRecording - true, я бы использовал setInterval для непрерывного вызова draw ().К сожалению, это кажется неправильным использованием метода draw (), так как он должен выполнять код внутри него непрерывно самостоятельно после первого выполнения.
Угловой код:
(function () {
angular.module('icSdkPwp').directive('icAudioRecordingUpload', icAudioRecordingUpload);
function icAudioRecordingUpload($stateSvc, $rS, $utilSvc) {
return {
scope: {
model: '=',
config: '=',
updateState: '='
},
link: function ($s, e, a) {
$s.hasRecording = false;
$s.isRecording = false;
$s.recordingPaused = false;
$s.recordingProcessing = false;
$s.volHistory = []
$s.micIsOn = false
$s.p5mic = null
$s.playButton = null
var gumStream;
var rec;
var input;
var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext
$s.startRecording = function(e) {
if($s.recordingProcessing)
return;
var constraints = { audio: true, video:false }
setup()
$s.isRecording = true;
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
audioContext = new AudioContext();
gumStream = stream;
input = audioContext.createMediaStreamSource(stream);
rec = new Recorder(input,{numChannels:2})
rec.record()
}).catch(function(err) {
$s.isRecording = true;
});
}
var redrawInt = null;
$s.$watch("isRecording", function (n, o, s) {
if(s.isRecording){
redrawInt = setInterval(function(){
draw()
},0);
}
else{
clearInterval(redrawInt);
}
});
function setup(){
createCanvas(400, 150)
$s.p5mic = new p5.AudioIn()
$s.p5mic.start()
$s.micIsOn = true
background(245)
}
function draw(){
stroke(0, 109, 203)
//populate volHistory
if($s.isRecording){
var vol = $s.p5mic.getLevel()
//check to see if array is empty, if it is empty we do not want to push 0 volume
if($s.volHistory.length > 0 && vol > 0){
$s.volHistory.push(vol)
//if recording has started, we can now take in vol
} else if(vol > 0) {
$s.volHistory.push(vol)
}
}
//iterate through volHistory and draw
fill(0, 109, 203)
var barWidth = 2;
var offsetWidth = 5;
var offset = 5;
for(var i = 0; i < $s.volHistory.length; i++){
var barHeight = map($s.volHistory[i], 0, 1, 1, height)
rect(i + offset, (height/2.0) - (barHeight/2.0), barWidth, barHeight, 15);
offset += offsetWidth;
}
//moves wavelength 1 index at a time and account for bar width and offset width
if($s.volHistory.length * (offsetWidth + barWidth) > width){
$s.volHistory.splice(0, 1)
}
//draw vertical line
stroke(250, 30, 100)
// debugger
line($s.volHistory.length + offset, 0, $s.volHistory.length + offset, height)
}
}
};
}
}());
Кнопка, которая вызывает startRecording (), инициируя процесс
<div class="IX_recordControls clearfix">
<div class="rcrow row1">
<div ng-click="recordingProcessing || startRecording($event)"
ng-if="!hasRecording">
</div>
</div>
Это дает мне действительно странный холст, который, я полагаю, ожидается, так как я не должен вызывать draw () так много разно я не могу найти способ заставить его вызывать один раз и работать непрерывно.
Это определенно похоже на проблему с областью действия, где ничья() метод не может выполнить свой собственный цикл.