My goal is to incorporate a transform effect that only applies to the hovered video or image. The effect is dynamically computed and cannot be implemented directly in a Vue method, but I am exploring the option of modifying the target element for the useMouseInElement()
. The component WorkThumbnail.vue
is part of a v-for loop and displays multiple videos/images.
I'm trying to figure out how to access the current DOM Element in the :style attribute. Using $event doesn't seem to be the solution 😅
WorkThumbnail.vue
<template>
<div
v-if="work.video === false"
class="work_thumbnail"
:style="{
backgroundImage: 'url(' + require(`@/assets/img/works/${work.thumbnail}.jpg`) + ')',
transition: 'transform 0.25s ease-out', transform: [currentWork === selectWork($event) ? { cardTransform } : '']}"
@mouseover="selectWork($event)"
>
<div class="WorkHeadline">{{work.name}}</div>
</div>
<div
v-if="work.video === true"
class="work_thumbnail"
@click="showWork(work)"
:style="{
transform: [currentWork === selectWork($event) ? { cardTransform } : ''],
transition: 'transform 0.25s ease-out'
}"
@mouseover="selectWork($event)"
>
<div class="WorkHeadline">{{work.name}}</div>
<video :poster="require(`@/assets/img/works/${work.vidPreview}.jpg`)" autoplay loop>
<source
:src="require(`@/assets/img/works/${work.thumbnail}.mp4`)"
type="video/mp4">
</video>
</div>
</template>
<script>
import {
useMouseInElement
} from '@vueuse/core'
import {computed } from 'vue'
var currentWork
const {
elementX,
elementY,
elementHeight,
elementWidth,
isOutside
} = useMouseInElement(currentWork)
const cardTransform = computed(() => {
const Max_Rotation = 40
const rX = (
Max_Rotation / 2 -
(elementY.value / elementHeight.value) * Max_Rotation).toFixed(2)
const rY = (
(elementX.value / elementWidth.value) * Max_Rotation - Max_Rotation / 2).toFixed(2)
return isOutside.value
? ''
: `perspective(${elementWidth.value}px) rotateX(${rX}deg) rotateY(${rY}deg)`
})
export default {
props: {
work: {
type: Object,
required: true
},
index: {
type: Number,
required: true
}
},
methods: {
showWork(work) {
if (work.direct === true) {
window.open(work.link, '_blank').focus();
}
},
selectWork(event) {
currentWork = event.target
return event.target
},
},
setup() {
return {
cardTransform,
elementX,
elementY,
elementHeight,
elementWidth,
currentWork
}
}
}
</script>
Parent Component (Explore.vue)
<template>
<div class="Section Explore">^
<div class="WorkList flex_c_h flex_wrap gap1">
<WorkThumbnail v-for="(work, index) in works" :key="work" :work="work" :index="index"/>
</div>
</div>
</template>
<script>
import WorkThumbnail from '@/components/Explore/WorkThumbnail.vue'
export default {
name: 'Explore',
components: {
WorkThumbnail
},
computed: {
works() {
return this.$store.state.works
}
},
}
</script>