line-and-surface/src/components/AudioArea.vue

80 lines
2.0 KiB
Vue
Raw Normal View History

2021-01-10 21:55:40 +01:00
<template>
2021-04-22 11:33:33 +02:00
<audio ref="audio" :src="definition.src" loop preload="auto" />
2021-01-10 21:55:40 +01:00
</template>
<script lang="ts">
2021-04-22 11:33:33 +02:00
import { defineComponent, PropType, ref, watch } from "vue";
import { BoundingBox } from "@/components/SVGContent.vue";
2021-01-10 21:55:40 +01:00
export default defineComponent({
name: "AudioArea",
props: {
definition: {
2021-01-12 18:05:28 +01:00
type: Object as PropType<AudioAreaDef>,
2021-04-22 11:33:33 +02:00
required: true,
2021-01-10 21:55:40 +01:00
},
bbox: {
2021-01-12 18:05:28 +01:00
type: Object as PropType<BoundingBox>,
2021-04-22 11:33:33 +02:00
required: true,
2021-01-10 21:55:40 +01:00
},
},
setup(props) {
const audio = ref<HTMLAudioElement | null>(null);
2021-01-11 23:10:40 +01:00
console.debug(`[AUDIOAREA] Initializing ${props.definition.src}...`);
console.debug(props.definition);
const MIN_SCALE = 0.02;
2021-01-11 20:56:44 +01:00
const MIN_VOLUME_MULTIPLIER = 0.33;
const vol_x = (1 - MIN_VOLUME_MULTIPLIER) / (1 - MIN_SCALE);
const vol_b = 1 - vol_x;
2021-01-10 21:55:40 +01:00
const onBBoxChange = () => {
const x = props.bbox.x + props.bbox.w / 2;
const y = props.bbox.y + props.bbox.h / 2;
2021-04-22 11:33:33 +02:00
const distance = Math.sqrt(
Math.pow(x - props.definition.cx, 2) +
Math.pow(y - props.definition.cy, 2)
);
2021-01-10 21:55:40 +01:00
if (distance < props.definition.radius) {
2021-01-11 23:10:40 +01:00
if (audio.value!.paused) {
2021-04-22 11:33:33 +02:00
console.debug(
`[AUDIOAREA] Entered audio area "${props.definition.src}", starting playback...`
);
2021-01-11 23:10:40 +01:00
audio.value!.play();
}
2021-04-22 11:33:33 +02:00
const volume =
(props.definition.radius - distance) / props.definition.radius;
audio.value!.volume =
volume * (props.bbox.z < 1 ? props.bbox.z * vol_x + vol_b : 1);
2021-01-10 21:55:40 +01:00
} else {
2021-01-11 23:10:40 +01:00
if (!audio.value!.paused) {
2021-04-22 11:33:33 +02:00
console.debug(
`[AUDIOAREA] Left audio area "${props.definition.src}", pausing playback...`
);
2021-01-11 23:10:40 +01:00
audio.value!.pause();
}
2021-01-10 21:55:40 +01:00
}
};
2021-04-22 11:33:33 +02:00
watch(props.bbox, onBBoxChange, { deep: true });
2021-01-10 21:55:40 +01:00
return {
2021-04-22 11:33:33 +02:00
audio,
2021-01-10 21:55:40 +01:00
};
2021-04-22 11:33:33 +02:00
},
2021-01-10 21:55:40 +01:00
});
export interface AudioAreaDef {
2021-04-22 11:33:33 +02:00
id: string;
cx: number;
cy: number;
radius: number;
src: string;
2021-01-10 21:55:40 +01:00
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>