如何在 angular 项目中预加载音频文件?
How to preload audio files in angular project?
我在angular做了一个项目。我想在按钮单击事件上播放小的 mp3 文件,当用户单击 UI 中的各种按钮时,应根据所选按钮播放音乐。我想预加载所有 mp3 格式的音乐文件,只有在 angular 中加载 mp3 文件后,我的 UI 才应该在屏幕上可见。我该怎么做?
提前致谢
Angular 路由器提供了一个解析 属性,它采用路由解析器并允许您的应用程序在导航到路由(即解析路由数据)之前获取数据。
您可以通过实现 Resolve 接口来创建路由解析器。
例如:
音频-resolver.service.ts:
import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
@Injectable()
export class AudioResolver implements Resolve<Promise<string[]>>{
audioFiles = [
"http://www.teanglann.ie/CanC/nua.mp3",
"http://www.teanglann.ie/CanC/ag.mp3",
"http://www.teanglann.ie/CanC/dul.mp3",
"http://www.teanglann.ie/CanC/freisin.mp3"
];
resolve = (): Promise<string[]> => Promise.all(this.audioFiles.map(this.preloadAudio))
preloadAudio = (url: string): Promise<string> => {
const audio = new Audio();
audio.src = url;
return new Promise((res, req) => audio.addEventListener('canplaythrough', () => res(url), false))
// once file is loaded, the promise will be resolved
// the file will be kept by the browser as cache
}
}
如您所见,实现 Angular 路由器的 Resolve 接口的唯一要求是我们的 class 有一个 resolve 方法。从该方法返回的任何内容都将是已解析的数据,在我们的例子中,返回值是 Promise<string[]>
,它将被解析为 urls 数组。
现在您可以设置我们的路由模块以包含我们的解析器:
app.routing.module.ts:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { PlayerComponent } from './components/player/player.component';
import { AudioResolver} from './services/audio-resolver.service';
const routes: Routes = [
{ path: "", component: PlayerComponent, resolve: { songs: ResolverService } }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [AudioResolver]
})
export class AppRoutingModule { }
在组件中,我们可以使用ActivatedRoute的快照对象的数据属性来访问解析后的数据。
player.component.ts:
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-player',
templateUrl: './player.component.html',
styleUrls: ['./player.component.scss']
})
export class PlayerComponent implements OnInit {
songs: string[];
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.songs = this.route.snapshot.data.songs;
}
}
player.component.html:
<audio *ngFor="let src of songs" [src]="src" controls="" ><br></audio>
现在,如果您继续查看浏览器网络,您会看到文件在 PlayerComponent
初始化之前正在加载,并且再也不会加载。
我在angular做了一个项目。我想在按钮单击事件上播放小的 mp3 文件,当用户单击 UI 中的各种按钮时,应根据所选按钮播放音乐。我想预加载所有 mp3 格式的音乐文件,只有在 angular 中加载 mp3 文件后,我的 UI 才应该在屏幕上可见。我该怎么做?
提前致谢
Angular 路由器提供了一个解析 属性,它采用路由解析器并允许您的应用程序在导航到路由(即解析路由数据)之前获取数据。 您可以通过实现 Resolve 接口来创建路由解析器。 例如:
音频-resolver.service.ts:
import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
@Injectable()
export class AudioResolver implements Resolve<Promise<string[]>>{
audioFiles = [
"http://www.teanglann.ie/CanC/nua.mp3",
"http://www.teanglann.ie/CanC/ag.mp3",
"http://www.teanglann.ie/CanC/dul.mp3",
"http://www.teanglann.ie/CanC/freisin.mp3"
];
resolve = (): Promise<string[]> => Promise.all(this.audioFiles.map(this.preloadAudio))
preloadAudio = (url: string): Promise<string> => {
const audio = new Audio();
audio.src = url;
return new Promise((res, req) => audio.addEventListener('canplaythrough', () => res(url), false))
// once file is loaded, the promise will be resolved
// the file will be kept by the browser as cache
}
}
如您所见,实现 Angular 路由器的 Resolve 接口的唯一要求是我们的 class 有一个 resolve 方法。从该方法返回的任何内容都将是已解析的数据,在我们的例子中,返回值是 Promise<string[]>
,它将被解析为 urls 数组。
现在您可以设置我们的路由模块以包含我们的解析器:
app.routing.module.ts:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { PlayerComponent } from './components/player/player.component';
import { AudioResolver} from './services/audio-resolver.service';
const routes: Routes = [
{ path: "", component: PlayerComponent, resolve: { songs: ResolverService } }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [AudioResolver]
})
export class AppRoutingModule { }
在组件中,我们可以使用ActivatedRoute的快照对象的数据属性来访问解析后的数据。
player.component.ts:
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-player',
templateUrl: './player.component.html',
styleUrls: ['./player.component.scss']
})
export class PlayerComponent implements OnInit {
songs: string[];
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.songs = this.route.snapshot.data.songs;
}
}
player.component.html:
<audio *ngFor="let src of songs" [src]="src" controls="" ><br></audio>
现在,如果您继续查看浏览器网络,您会看到文件在 PlayerComponent
初始化之前正在加载,并且再也不会加载。