text customization

This commit is contained in:
2025-12-02 12:18:41 +01:00
parent a739910315
commit de5ebd5ab7
2 changed files with 57 additions and 34 deletions

View File

@@ -1,5 +1,6 @@
<script setup lang="ts">
import {motion, frame} from "motion-v";
const {
name,
img = undefined,
@@ -9,6 +10,8 @@ const {
scaleFactor = 2,
initialWidth = undefined,
initialHeight = undefined,
topTextOffset = undefined,
bottomTextOffset = undefined,
} = defineProps<{
name: string,
img?: string,
@@ -18,12 +21,18 @@ const {
scaleFactor?: number,
initialWidth?: string,
initialHeight?: string,
topTextOffset?: string,
bottomTextOffset?: string,
}>()
const emit = defineEmits(['positionChanged'])
const isHoveringParent = ref(false)
const roundedDivClass = `rounded-full w-full h-full absolute ${color}`
const imageMaskClass = `avatar mask mask-squircle ${initialWidth ? initialWidth : 'w-30'} ${initialHeight ? initialHeight : 'h-30'}`
const roundedDivClass = `rounded-full absolute ${color} ${initialWidth ? initialWidth : 'w-30'} ${initialHeight ? initialHeight : 'h-30'}`
const topTextClass = `absolute w-full text-center ${topTextOffset ? topTextOffset : '-top-30'}`
const bottomTextClass = `absolute w-full text-center ${bottomTextOffset ? bottomTextOffset : '-bottom-30'}`
function getRandomArbitrary(min: number, max: number): number {
return Math.random() * (max - min) + min;
@@ -42,8 +51,8 @@ const handlePointerMove = ({clientX, clientY}: { clientX: number; clientY: numbe
const element = elementRef.value?.$el
if (!element) return
frame.read(() => {
xPoint.set((clientX - element.offsetLeft - element.offsetWidth / 2)/moveFactorValue)
yPoint.set((clientY - element.offsetTop - element.offsetHeight / 2)/moveFactorValue)
xPoint.set((clientX - element.offsetLeft - element.offsetWidth / 2) / moveFactorValue)
yPoint.set((clientY - element.offsetTop - element.offsetHeight / 2) / moveFactorValue)
})
}
@@ -53,8 +62,8 @@ useRafFn(() => {
return
emit(
'positionChanged',
x.get() + element.offsetLeft + element.offsetWidth/2,
y.get() + element.offsetTop + element.offsetHeight/2,)
x.get() + element.offsetLeft + element.offsetWidth / 2,
y.get() + element.offsetTop + element.offsetHeight / 2,)
})
onMounted(() => {
@@ -65,43 +74,50 @@ onUnmounted(() => {
window.removeEventListener("pointermove", handlePointerMove)
})
const baseElementClass = ref(`${initialWidth ? initialWidth : 'w-30'} ${initialHeight ? initialHeight : 'h-30'} avatar absolute`)
</script>
<template>
<motion.div
ref="elementRef"
:class="baseElementClass"
:style="{ x, y }"
class="w-60 h-24 absolute flex items-center justify-center"
:style="{ x, y }">
<motion.div
v-if="img !== undefined"
:class="imageMaskClass"
:while-hover="{ scale: scaleFactor }"
@hover-start="event => {isHoveringParent=true}"
@hover-end="event => {isHoveringParent=false}">
<div v-if="img !== undefined" class="mask mask-squircle w-full">
<NuxtImg :src="img"/>
</div>
<div v-else :class="roundedDivClass"/>
</motion.div>
<motion.div
v-else
:class="roundedDivClass"
:while-hover="{ scale: scaleFactor }"
@hover-start="event => {isHoveringParent=true}"
@hover-end="event => {isHoveringParent=false}"/>
<AnimatePresence>
<motion.p
v-if="textTop"
v-show="isHoveringParent"
class="-top-8 absolute text-xs"
:initial="{ opacity: 0 }"
:animate="{ opacity: 1 }"
:exit="{ opacity: 0 }">
:class="topTextClass"
:initial="{ opacity: 0, scale: 0 }"
:animate="{ opacity: 1, scale: 1 }"
:exit="{ opacity: 0, scale: 0 }">
{{ name }}
</motion.p>
<motion.p
v-else
v-show="isHoveringParent"
class="-bottom-8 absolute text-xs"
:initial="{ opacity: 0 }"
:animate="{ opacity: 1 }"
:exit="{ opacity: 0 }">
:class="bottomTextClass"
:initial="{ opacity: 0, scale: 0 }"
:animate="{ opacity: 1, scale: 1 }"
:exit="{ opacity: 0, scale: 0 }">
{{ name }}
</motion.p>
</AnimatePresence>
</motion.div>
</template>

View File

@@ -6,8 +6,12 @@ const nodes = [
img: "/face.jpg",
textTop: true,
moveFactor: 6,
initialWidth: 'w-50',
initialHeight: 'h-50',
scaleFactor: 2,
hOffset: 'left-1/3',
vOffset: 'top-1/3',
topTextOffset: '-top-50',
},
{
name: "DevOps engineer",
@@ -17,6 +21,7 @@ const nodes = [
initialWidth: 'w-2',
initialHeight: 'h-2',
scaleFactor: 10,
bottomTextOffset: '-bottom-10'
},
{
name: "Game developer",
@@ -98,6 +103,8 @@ useRafFn(() => {
:scale-factor="node.scaleFactor"
:initial-width="node.initialWidth"
:initial-height="node.initialHeight"
:top-text-offset="node.topTextOffset"
:bottom-text-offset="node.bottomTextOffset"
@position-changed="(x, y) => { nodeMoved(index, x, y) }"/>
</li>
</ul>