Files
hossein-por-shop/frontend/components/home/Preview.vue
T
2026-04-28 22:01:12 +03:30

188 lines
7.0 KiB
Vue

<script setup lang="ts">
// import
import useHomeData from "~/composables/api/home/useHomeData";
// state
const { data: homeData } = useHomeData();
const clipPathPercent = ref(49);
const activeSlideVideo = ref<"left" | "right" | "none">("none");
const draggableEl = ref<HTMLElement | null>(null);
const previewContainerEl = ref<HTMLElement | null>(null);
// const heymlzElement = useTemplateRef<HTMLDivElement>("heymlzElement");
// const heymlzElementIsVisible = useElementVisibility(heymlzElement, {
// rootMargin: "0px 0px -40% 0px",
// });
// const showHeymlzAnimation = ref(false);
const { x: dragAxisX } = useDraggable(draggableEl, {
initialValue: { x: 0, y: 0 },
axis: "x",
});
// watch
// watch(
// heymlzElementIsVisible,
// (newValue) => {
// if (newValue) {
// setTimeout(() => {
// showHeymlzAnimation.value = true;
// setTimeout(() => {
// showHeymlzAnimation.value = false;
// }, 3200);
// }, 400);
// }
// },
// {
// once: true,
// }
// );
watch(
() => clipPathPercent.value,
(newValue) => {
if (newValue > 80) {
activeSlideVideo.value = "right";
} else if (newValue < 20) {
activeSlideVideo.value = "left";
} else {
activeSlideVideo.value = "none";
}
}
);
watch(
() => dragAxisX.value,
(newValue) => {
const clientRect = previewContainerEl.value?.getBoundingClientRect()!;
const percent = clientRect.width / 100;
const clipPercent = (newValue + draggableEl.value!.clientWidth / 2 - clientRect.x - 8) / percent;
if (clipPercent >= 1 && clipPercent <= 99) {
clipPathPercent.value = clipPercent;
}
}
);
</script>
<template>
<div class="container select-none mb-40 lg:mb-40 lg:mt-20 3xl:mb-85">
<div>
<div class="flex flex-col items-center gap-3 mb-10 lg:mb-16">
<span class="typo-p-sm md:typo-p-md text-slate-500"> مقایسه محصولات </span>
<span class="typo-h-6 md:typo-h-5 lg:typo-h-3 text-black"> تفاوت محصلات ما را ببینید </span>
</div>
<div
ref="previewContainerEl"
class="rounded-200 overflow-hidden h-[70svh] max-h-200 relative"
>
<Transition name="fade">
<NuxtImg
v-if="activeSlideVideo !== 'right'"
:src="homeData!.difreance_section.image1"
class="select-none absolute size-full object-cover transition-[filter] duration-250 brightness-[95%]"
:alt="homeData!.difreance_section.title1"
loading="lazy"
fetch-priority="low"
/>
<video
v-else
autoplay
muted
playsinline
webkit-playsinline
src="/video/vid-3.mp4"
class="select-none absolute size-full object-cover brightness-[95%]"
/>
</Transition>
<div
class="absolute size-full right-0 w-full"
ref="heymlzElement"
>
<Transition name="fade">
<NuxtImg
v-if="activeSlideVideo !== 'left'"
:src="homeData!.difreance_section.image2"
class="overlay-image select-none absolute object-cover size-full transition-[filter] duration-250 brightness-[95%]"
:alt="homeData!.difreance_section.title2"
loading="lazy"
fetch-priority="low"
/>
<video
v-else
autoplay
muted
playsinline
webkit-playsinline
src="/video/vid-3.mp4"
class="overlay-image select-none absolute object-cover size-full brightness-[95%]"
/>
</Transition>
<div
:style="{
left: `${clipPathPercent}%`,
}"
:class="[activeSlideVideo !== 'none' ? 'opacity-10' : '']"
class="select-none w-[5px] sm:w-2 bg-black h-full absolute left-0 flex items-center justify-center transition-opacity duration-250"
>
<div
ref="draggableEl"
class="touch-none cursor-grab bg-black hover:scale-115 transition-transform rounded-full absolute size-9 sm:size-11 flex items-center justify-center"
>
<Icon
name="ci:arrows"
class="transition-all size-5 sm:size-6 **:stroke-white"
/>
</div>
</div>
</div>
<div class="absolute bottom-0 p-6 md:p-10 w-full flex justify-between items-end transition-opacity">
<div
class="flex flex-col gap-2 text-black transition-opacity"
:class="activeSlideVideo === 'right' ? 'opacity-0' : ''"
>
<span class="typo-p-sm md:typo-p-md">
{{ homeData!.difreance_section.description1 }}
</span>
<NuxtLink
:to="homeData!.difreance_section.link1"
class="typo-h-6 md:typo-h-5 lg:typo-h-3"
>
{{ homeData!.difreance_section.title1 }}
</NuxtLink>
</div>
<div
class="flex flex-col gap-2 text-black transition-opacity"
:class="activeSlideVideo === 'left' ? 'opacity-0' : ''"
>
<span class="typo-p-sm md:typo-p-md text-end">
{{ homeData!.difreance_section.description2 }}
</span>
<NuxtLink
:to="homeData!.difreance_section.link2"
class="typo-h-6 md:typo-h-5 lg:typo-h-3 text-end"
>
{{ homeData!.difreance_section.title2 }}
</NuxtLink>
</div>
</div>
</div>
</div>
</div>
</template>
<style>
.overlay-image {
clip-path: polygon(v-bind('clipPathPercent + "%"') 0, 100% 0, 100% 100%, v-bind('clipPathPercent + "%"') 100%);
}
</style>