|
<template> |
|
<div class="editable-element-audio" |
|
:class="{ 'lock': elementInfo.lock }" |
|
:style="{ |
|
top: elementInfo.top + 'px', |
|
left: elementInfo.left + 'px', |
|
width: elementInfo.width + 'px', |
|
height: elementInfo.height + 'px', |
|
}" |
|
> |
|
<div |
|
class="rotate-wrapper" |
|
:style="{ transform: `rotate(${elementInfo.rotate}deg)` }" |
|
> |
|
<div |
|
class="element-content" |
|
v-contextmenu="contextmenus" |
|
@mousedown="$event => handleSelectElement($event)" |
|
@touchstart="$event => handleSelectElement($event)" |
|
> |
|
<IconVolumeNotice |
|
class="audio-icon" |
|
:style="{ |
|
fontSize: audioIconSize, |
|
color: elementInfo.color, |
|
}" |
|
/> |
|
<AudioPlayer |
|
class="audio-player" |
|
v-if="handleElementId === elementInfo.id" |
|
:style="{ ...audioPlayerPosition }" |
|
:src="elementInfo.src" |
|
:loop="elementInfo.loop" |
|
:scale="canvasScale" |
|
@mousedown.stop="" |
|
/> |
|
</div> |
|
</div> |
|
</div> |
|
</template> |
|
|
|
<script lang="ts" setup> |
|
import { computed } from 'vue' |
|
import { storeToRefs } from 'pinia' |
|
import { useMainStore, useSlidesStore } from '@/store' |
|
import type { PPTAudioElement } from '@/types/slides' |
|
import type { ContextmenuItem } from '@/components/Contextmenu/types' |
|
|
|
import AudioPlayer from './AudioPlayer.vue' |
|
|
|
const props = defineProps<{ |
|
elementInfo: PPTAudioElement |
|
selectElement: (e: MouseEvent | TouchEvent, element: PPTAudioElement, canMove?: boolean) => void |
|
contextmenus: () => ContextmenuItem[] | null |
|
}>() |
|
|
|
const { canvasScale, handleElementId } = storeToRefs(useMainStore()) |
|
const { viewportRatio, viewportSize } = storeToRefs(useSlidesStore()) |
|
|
|
const audioIconSize = computed(() => { |
|
return Math.min(props.elementInfo.width, props.elementInfo.height) + 'px' |
|
}) |
|
const audioPlayerPosition = computed(() => { |
|
const canvasWidth = viewportSize.value |
|
const canvasHeight = viewportSize.value * viewportRatio.value |
|
|
|
const audioWidth = 280 / canvasScale.value |
|
const audioHeight = 50 / canvasScale.value |
|
|
|
const elWidth = props.elementInfo.width |
|
const elHeight = props.elementInfo.height |
|
const elLeft = props.elementInfo.left |
|
const elTop = props.elementInfo.top |
|
|
|
let left = 0 |
|
let top = elHeight |
|
|
|
if (elLeft + audioWidth >= canvasWidth) left = elWidth - audioWidth |
|
if (elTop + elHeight + audioHeight >= canvasHeight) top = -audioHeight |
|
|
|
return { |
|
left: left + 'px', |
|
top: top + 'px', |
|
} |
|
}) |
|
|
|
const handleSelectElement = (e: MouseEvent | TouchEvent) => { |
|
if (props.elementInfo.lock) return |
|
e.stopPropagation() |
|
|
|
props.selectElement(e, props.elementInfo) |
|
} |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
.editable-element-audio { |
|
position: absolute; |
|
|
|
&.lock .audio-icon { |
|
cursor: default; |
|
} |
|
} |
|
.rotate-wrapper { |
|
width: 100%; |
|
height: 100%; |
|
} |
|
.element-content { |
|
width: 100%; |
|
height: 100%; |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
} |
|
.audio-icon { |
|
cursor: move; |
|
} |
|
.audio-player { |
|
position: absolute; |
|
} |
|
</style> |
|
|