类似于Angular change detection with HTMLAudioElement,但它的解决方案对我不起作用。
在我的角度应用程序中,我想使用Web音频播放简短的wav文件。在播放时,播放按钮应变为停止按钮,完成后,停止按钮应再次变为播放按钮。
我做了一个简单的音频服务,它在AudioBufferSourceNode.start(0)
之后立即触发一个可观察的对象,并且还在AudioBufferSourceNode.onended
中触发一个可观察的对象。我可以在控制台中看到事件触发,但UI不变。我进行了一次堆叠式演示,证明了我的问题https://stackblitz.com/edit/angular-x5ytjt-实际使用音频API(复选框集)时,UI不会更新,而仅触发可观察(未选中复选框)时,UI会更新。
在这种情况下,如何实现更新UI?
组件:
@Component({
selector: 'hello',
template: `
<input type="checkbox" [(ngModel)]="playReal">Real playback (vs. fake-events)<br>
Currently {{playing?"playing":"stopped"}}
<button type="button" *ngIf="!playing" (click)="play()">play</button>
<button type="button" *ngIf="playing" (click)="stop()">stop</button>
`,
styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent {
@Input() name: string;
playing: boolean = false;
subscription: Subscription;
playReal: boolean = true;
constructor(public audio: AudioService, public dataSvc: DataService, private ref: ChangeDetectorRef) { }
ngOnInit() {
this.subscription = this.audio.playing$.subscribe(value => {
this.playing = value;
console.debug('observer has fired. new value: ', value);
// solution from https://stackoverflow.com/questions/54030943/angular-change-detection-with-htmlaudioelement
this.ref.markForCheck();
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
play() {
this.dataSvc.getAudio().subscribe(
data => {
if (this.playReal) {
// do real playback
this.audio.playBlob(data);
} else {
// only fake playing (tell the audio service to emit the event)
this.audio.hackSetPlaying(true);
}
}
)
}
stop() {
if (this.playReal) {
this.audio.stopPlay();
} else {
this.audio.hackSetPlaying(false);
}
}
}
音频服务:
public playBlob( data: Blob ) {
// playBlob and play inspired by https://stackoverflow.com/questions/24151121/how-to-play-wav-audio-byte-array-via-javascript-html5
// create audio context if necessary
if (!this.audioCtx) {
this.audioCtx = new AudioContext();
}
// use file reader to convert blob to ArrayBuffer
let fr: FileReader = new FileReader();
fr.onload = () => {
// after loading decode and play the wav file
this.audioCtx.decodeAudioData(<ArrayBuffer>fr.result, (res) => {this.play(res);});
}
fr.readAsArrayBuffer(data);
}
private play(audioBuff: AudioBuffer) {
if (!this.audioSrc) {
this.audioSrc = this.audioCtx.createBufferSource();
}
this.audioSrc.buffer = audioBuff;
this.audioSrc.connect(this.audioCtx.destination);
this.audioSrc.start(0);
this.playing = true;
this.playingSubject.next(this.playing);
console.debug('audioService has set playing to true');
this.audioSrc.onended = () => {
this.playing = false;
this.playingSubject.next(this.playing);
console.debug('audioService set playing to false');
this.audioSrc = null; // audioSrc can only be used once
}
}
编辑:我刚刚了解到,我以前使用的是Web音频api,而不是html5音频。更正的标签,标题等。
答案 0 :(得分:1)
我在https://stackoverflow.com/a/46866433/2131459
中找到了答案我必须调用ChangeDetectorRef
的方法detectChanges()
而不是markForCheck()
。我已经更新了堆叠闪电战。