mirror of
https://github.com/DavidHDev/vue-bits.git
synced 2026-03-09 08:29:30 -06:00
Add prettier config, format codebase
This commit is contained in:
@@ -1,65 +1,87 @@
|
||||
<template>
|
||||
<figure ref="cardRef" class="relative w-full h-full [perspective:800px] flex flex-col items-center justify-center"
|
||||
<figure
|
||||
ref="cardRef"
|
||||
class="relative w-full h-full [perspective:800px] flex flex-col items-center justify-center"
|
||||
:style="{
|
||||
height: containerHeight,
|
||||
width: containerWidth,
|
||||
}" @mousemove="handleMouse" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
|
||||
width: containerWidth
|
||||
}"
|
||||
@mousemove="handleMouse"
|
||||
@mouseenter="handleMouseEnter"
|
||||
@mouseleave="handleMouseLeave"
|
||||
>
|
||||
<div v-if="showMobileWarning" class="absolute top-4 text-center text-sm block sm:hidden">
|
||||
This effect is not optimized for mobile. Check on desktop.
|
||||
</div>
|
||||
|
||||
<Motion tag="div" class="relative [transform-style:preserve-3d]" :style="{
|
||||
width: imageWidth,
|
||||
height: imageHeight,
|
||||
}" :animate="{
|
||||
<Motion
|
||||
tag="div"
|
||||
class="relative [transform-style:preserve-3d]"
|
||||
:style="{
|
||||
width: imageWidth,
|
||||
height: imageHeight
|
||||
}"
|
||||
:animate="{
|
||||
rotateX: rotateXValue,
|
||||
rotateY: rotateYValue,
|
||||
scale: scaleValue,
|
||||
}" :transition="springTransition">
|
||||
<img :src="imageSrc" :alt="altText"
|
||||
scale: scaleValue
|
||||
}"
|
||||
:transition="springTransition"
|
||||
>
|
||||
<img
|
||||
:src="imageSrc"
|
||||
:alt="altText"
|
||||
class="absolute top-0 left-0 object-cover rounded-[15px] will-change-transform [transform:translateZ(0)]"
|
||||
:style="{
|
||||
width: imageWidth,
|
||||
height: imageHeight,
|
||||
}" />
|
||||
height: imageHeight
|
||||
}"
|
||||
/>
|
||||
|
||||
<Motion v-if="displayOverlayContent && overlayContent" tag="div"
|
||||
class="absolute top-0 left-0 z-[2] will-change-transform [transform:translateZ(30px)]">
|
||||
<Motion
|
||||
v-if="displayOverlayContent && overlayContent"
|
||||
tag="div"
|
||||
class="absolute top-0 left-0 z-[2] will-change-transform [transform:translateZ(30px)]"
|
||||
>
|
||||
<slot name="overlay" />
|
||||
</Motion>
|
||||
</Motion>
|
||||
|
||||
<Motion v-if="showTooltip && captionText" tag="figcaption"
|
||||
<Motion
|
||||
v-if="showTooltip && captionText"
|
||||
tag="figcaption"
|
||||
class="pointer-events-none absolute left-0 top-0 rounded-[4px] bg-white px-[10px] py-[4px] text-[10px] text-[#2d2d2d] opacity-0 z-[3] hidden sm:block"
|
||||
:animate="{
|
||||
x: xValue,
|
||||
y: yValue,
|
||||
opacity: opacityValue,
|
||||
rotate: rotateFigcaptionValue,
|
||||
}" :transition="tooltipTransition">
|
||||
rotate: rotateFigcaptionValue
|
||||
}"
|
||||
:transition="tooltipTransition"
|
||||
>
|
||||
{{ captionText }}
|
||||
</Motion>
|
||||
</figure>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { Motion } from 'motion-v'
|
||||
import { ref, computed } from 'vue';
|
||||
import { Motion } from 'motion-v';
|
||||
|
||||
interface TiltedCardProps {
|
||||
imageSrc: string
|
||||
altText?: string
|
||||
captionText?: string
|
||||
containerHeight?: string
|
||||
containerWidth?: string
|
||||
imageHeight?: string
|
||||
imageWidth?: string
|
||||
scaleOnHover?: number
|
||||
rotateAmplitude?: number
|
||||
showMobileWarning?: boolean
|
||||
showTooltip?: boolean
|
||||
overlayContent?: boolean
|
||||
displayOverlayContent?: boolean
|
||||
imageSrc: string;
|
||||
altText?: string;
|
||||
captionText?: string;
|
||||
containerHeight?: string;
|
||||
containerWidth?: string;
|
||||
imageHeight?: string;
|
||||
imageWidth?: string;
|
||||
scaleOnHover?: number;
|
||||
rotateAmplitude?: number;
|
||||
showMobileWarning?: boolean;
|
||||
showTooltip?: boolean;
|
||||
overlayContent?: boolean;
|
||||
displayOverlayContent?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<TiltedCardProps>(), {
|
||||
@@ -74,64 +96,64 @@ const props = withDefaults(defineProps<TiltedCardProps>(), {
|
||||
showMobileWarning: true,
|
||||
showTooltip: true,
|
||||
overlayContent: false,
|
||||
displayOverlayContent: false,
|
||||
})
|
||||
displayOverlayContent: false
|
||||
});
|
||||
|
||||
const cardRef = ref<HTMLElement | null>(null)
|
||||
const xValue = ref(0)
|
||||
const yValue = ref(0)
|
||||
const rotateXValue = ref(0)
|
||||
const rotateYValue = ref(0)
|
||||
const scaleValue = ref(1)
|
||||
const opacityValue = ref(0)
|
||||
const rotateFigcaptionValue = ref(0)
|
||||
const lastY = ref(0)
|
||||
const cardRef = ref<HTMLElement | null>(null);
|
||||
const xValue = ref(0);
|
||||
const yValue = ref(0);
|
||||
const rotateXValue = ref(0);
|
||||
const rotateYValue = ref(0);
|
||||
const scaleValue = ref(1);
|
||||
const opacityValue = ref(0);
|
||||
const rotateFigcaptionValue = ref(0);
|
||||
const lastY = ref(0);
|
||||
|
||||
const springTransition = computed(() => ({
|
||||
type: 'spring' as const,
|
||||
damping: 30,
|
||||
stiffness: 100,
|
||||
mass: 2,
|
||||
}))
|
||||
mass: 2
|
||||
}));
|
||||
|
||||
const tooltipTransition = computed(() => ({
|
||||
type: 'spring' as const,
|
||||
damping: 30,
|
||||
stiffness: 350,
|
||||
mass: 1,
|
||||
}))
|
||||
mass: 1
|
||||
}));
|
||||
|
||||
function handleMouse(e: MouseEvent) {
|
||||
if (!cardRef.value) return
|
||||
if (!cardRef.value) return;
|
||||
|
||||
const rect = cardRef.value.getBoundingClientRect()
|
||||
const offsetX = e.clientX - rect.left - rect.width / 2
|
||||
const offsetY = e.clientY - rect.top - rect.height / 2
|
||||
const rect = cardRef.value.getBoundingClientRect();
|
||||
const offsetX = e.clientX - rect.left - rect.width / 2;
|
||||
const offsetY = e.clientY - rect.top - rect.height / 2;
|
||||
|
||||
const rotationX = (offsetY / (rect.height / 2)) * -props.rotateAmplitude
|
||||
const rotationY = (offsetX / (rect.width / 2)) * props.rotateAmplitude
|
||||
const rotationX = (offsetY / (rect.height / 2)) * -props.rotateAmplitude;
|
||||
const rotationY = (offsetX / (rect.width / 2)) * props.rotateAmplitude;
|
||||
|
||||
rotateXValue.value = rotationX
|
||||
rotateYValue.value = rotationY
|
||||
rotateXValue.value = rotationX;
|
||||
rotateYValue.value = rotationY;
|
||||
|
||||
xValue.value = e.clientX - rect.left
|
||||
yValue.value = e.clientY - rect.top
|
||||
xValue.value = e.clientX - rect.left;
|
||||
yValue.value = e.clientY - rect.top;
|
||||
|
||||
const velocityY = offsetY - lastY.value
|
||||
rotateFigcaptionValue.value = -velocityY * 0.6
|
||||
lastY.value = offsetY
|
||||
const velocityY = offsetY - lastY.value;
|
||||
rotateFigcaptionValue.value = -velocityY * 0.6;
|
||||
lastY.value = offsetY;
|
||||
}
|
||||
|
||||
function handleMouseEnter() {
|
||||
scaleValue.value = props.scaleOnHover
|
||||
opacityValue.value = 1
|
||||
scaleValue.value = props.scaleOnHover;
|
||||
opacityValue.value = 1;
|
||||
}
|
||||
|
||||
function handleMouseLeave() {
|
||||
opacityValue.value = 0
|
||||
scaleValue.value = 1
|
||||
rotateXValue.value = 0
|
||||
rotateYValue.value = 0
|
||||
rotateFigcaptionValue.value = 0
|
||||
opacityValue.value = 0;
|
||||
scaleValue.value = 1;
|
||||
rotateXValue.value = 0;
|
||||
rotateYValue.value = 0;
|
||||
rotateFigcaptionValue.value = 0;
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user