2021-01-10 21:55:40 +01:00
|
|
|
<template>
|
|
|
|
<audio ref="audio"
|
|
|
|
:src="definition.src"
|
2021-01-10 22:05:14 +01:00
|
|
|
loop preload="auto"/>
|
2021-01-10 21:55:40 +01:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
import {defineComponent, ref, watch} from "vue";
|
|
|
|
|
|
|
|
export default defineComponent({
|
|
|
|
name: "AudioArea",
|
|
|
|
props: {
|
|
|
|
definition: {
|
|
|
|
type: Object,
|
|
|
|
required: true
|
|
|
|
},
|
|
|
|
bbox: {
|
|
|
|
type: Object,
|
|
|
|
required: true
|
|
|
|
},
|
|
|
|
},
|
|
|
|
setup(props) {
|
|
|
|
const audio = ref<HTMLAudioElement | null>(null);
|
|
|
|
|
2021-01-11 20:20:55 +01:00
|
|
|
const MIN_SCALE = 0.02;
|
2021-01-11 20:56:44 +01:00
|
|
|
const MIN_VOLUME_MULTIPLIER = 0.33;
|
2021-01-11 20:20:55 +01:00
|
|
|
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;
|
|
|
|
const distance = Math.sqrt(Math.pow(x - props.definition.cx, 2) + Math.pow(y - props.definition.cy, 2));
|
|
|
|
|
|
|
|
if (distance < props.definition.radius) {
|
|
|
|
audio.value!.play();
|
2021-01-11 20:20:55 +01: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 {
|
|
|
|
audio.value!.pause();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
watch(props.bbox, onBBoxChange, {deep: true});
|
|
|
|
|
|
|
|
return {
|
|
|
|
audio
|
|
|
|
};
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
export interface AudioAreaDef {
|
|
|
|
cx: number,
|
|
|
|
cy: number,
|
|
|
|
radius: number,
|
|
|
|
src: string
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface BoundingBox {
|
|
|
|
x: number,
|
|
|
|
y: number,
|
|
|
|
w: number,
|
|
|
|
h: number
|
|
|
|
}
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
|
|
<style scoped>
|
|
|
|
</style>
|