actual volume animation (in App)

This commit is contained in:
Tomáš Mládek 2020-01-10 16:34:48 +01:00
parent fd11ab1ca1
commit 382f2e34d4
2 changed files with 29 additions and 20 deletions

View file

@ -2,7 +2,7 @@
<div id="app"> <div id="app">
<div class="channels"> <div class="channels">
<template v-for="i in N_CHANNELS"> <template v-for="i in N_CHANNELS">
<Channel :url="defaultMedia[i-1]" :key="i" class="channel" ref="channels"/> <Channel :url="defaultMedia[i-1]" :volume="volumes[i-1]" :key="i" class="channel" ref="channels"/>
</template> </template>
</div> </div>
<button @click="start">START</button> <button @click="start">START</button>
@ -21,16 +21,41 @@ import Channel from "@/components/Channel.vue";
}) })
export default class App extends Vue { export default class App extends Vue {
private readonly N_CHANNELS = 6; private readonly N_CHANNELS = 6;
private readonly LFO_PERIOD = 30_000;
private readonly LFO_DEPTH = 33;
private readonly LFO_OFFSET = 66;
private volumes = Array(this.N_CHANNELS).fill(50);
private animateVolumeStart?: Date;
private animateVolumeInterval?: number;
private defaultMedia = [ private defaultMedia = [
"https://www.youtube.com/watch?v=q76bMs-NwRk" "https://www.youtube.com/watch?v=q76bMs-NwRk",
]; ];
private start() { private start() {
(this.$refs.channels as Channel[]).forEach((channel) => { (this.$refs.channels as Channel[]).forEach((channel) => {
channel.start(); channel.start();
this.animateVolume();
}); });
} }
private animateVolume() {
clearInterval(this.animateVolumeInterval);
this.animateVolumeStart = new Date();
this.animateVolumeInterval = setInterval(() => {
if (this.animateVolumeStart) {
const delta = new Date().getTime() - this.animateVolumeStart.getTime();
this.volumes = [...Array(this.N_CHANNELS).keys()]
.map((idx) => {
const offset = idx * (1 / this.N_CHANNELS);
const progress = delta / this.LFO_PERIOD + offset;
return Math.sin(progress * 2 * Math.PI) * this.LFO_DEPTH + this.LFO_OFFSET;
});
}
}, 1000 / 60);
}
} }
</script> </script>

View file

@ -32,14 +32,11 @@ enum ChannelState {
@Component @Component
export default class Channel extends Vue { export default class Channel extends Vue {
@Prop() private url: string | undefined; @Prop() public volume: number = 50;
@Prop() public url: string | undefined;
private youtubePlayer?: YouTubePlayer; private youtubePlayer?: YouTubePlayer;
private animateVolumeStart?: Date;
private animateVolumeInterval?: number;
private state = ChannelState.UNLOADED; private state = ChannelState.UNLOADED;
private title = ""; private title = "";
private volume: number = 50;
private get source() { private get source() {
if (this.url) { if (this.url) {
@ -63,7 +60,6 @@ export default class Channel extends Vue {
this.youtubePlayer.setVolume(this.volume); this.youtubePlayer.setVolume(this.volume);
this.youtubePlayer.playVideo(); this.youtubePlayer.playVideo();
this.state = ChannelState.PLAYING; this.state = ChannelState.PLAYING;
this.animateVolume();
} }
} }
@ -117,18 +113,6 @@ export default class Channel extends Vue {
this.onUrlChange(); this.onUrlChange();
} }
private animateVolume() {
clearInterval(this.animateVolumeInterval);
const LFO_PERIOD = 3000;
this.animateVolumeStart = new Date();
this.animateVolumeInterval = setInterval(() => {
if (this.animateVolumeStart) {
const delta = new Date().getTime() - this.animateVolumeStart.getTime();
this.volume = Math.sin(((delta % LFO_PERIOD) / LFO_PERIOD) * 2 * Math.PI) * 50 + 50;
}
}, 1000 / 60);
}
private static fetchYoutubeTitle(videoId: string): Promise<string> { private static fetchYoutubeTitle(videoId: string): Promise<string> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let url = `https://www.googleapis.com/youtube/v3/videos?part=snippet&id=${videoId}`; let url = `https://www.googleapis.com/youtube/v3/videos?part=snippet&id=${videoId}`;