actual volume animation (in App)
This commit is contained in:
parent
fd11ab1ca1
commit
382f2e34d4
2 changed files with 29 additions and 20 deletions
29
src/App.vue
29
src/App.vue
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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}`;
|
||||||
|
|
Loading…
Reference in a new issue