From 01f6af2dfacca98d104a1ce28a6c5503103c708f Mon Sep 17 00:00:00 2001 From: zojgame Date: Mon, 25 Mar 2024 17:53:35 +0500 Subject: [PATCH] lazy loding --- src/app/page.tsx | 58 +++++++++++++++----- src/components/FeatureVideoViewBox.tsx | 75 ++++++++++++++++++-------- src/components/VideoSliderMobile.tsx | 10 ++-- 3 files changed, 105 insertions(+), 38 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 9fb5755..7476464 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -36,6 +36,17 @@ import LabelCard from "@components/CardYear"; import ProjectsSection from "@components/ProjectsSection"; import { motion } from "framer-motion"; +const VIDEOS = [ + "/videos/features/virtual_tour.mp4", + "/videos/features/nks_infra.mp4", + "/videos/features/uralsky.mp4", + "/videos/features/parametric.mp4", + "/videos/features/render.mp4", + "/videos/features/wish.mp4", + "/videos/features/integra_crm.mp4", + "/videos/features/send.mp4", +]; + function getSortedProjects(projects: IProject[]) { const sorted = [...projects].sort( (da, db) => getTime(db.releaseDate) - getTime(da.releaseDate) @@ -87,7 +98,33 @@ export default function App() { const [setModal] = useModalStore((state) => [state.setModal]); const [isShownAllProjects, setIsShownAllProjects] = useState(false); const [isBuffering, setIsBuffering] = useState(true); - const featureRef = useRef(null); + const [viewPortEntered, setViewPortEntered] = useState(false); + const featureRefDesktop = useRef(null); + const featureRefMobile = useRef(null); + + const handleOnViewportFeatureEnter = () => { + if (viewPortEntered) return; + + setViewPortEntered(true); + + if (!featureRefDesktop.current || !featureRefMobile.current) return; + const videoDesktopRefs = featureRefDesktop.current.children; + const videoMobileRefs = featureRefMobile.current.children; + + if (!videoDesktopRefs || !videoMobileRefs) return; + + for (let i = 0; i < videoDesktopRefs.length; i++) { + const videoMobileEl = videoDesktopRefs[i] as HTMLVideoElement; + const videoDesktopEl = videoMobileRefs[i] as HTMLVideoElement; + + if (videoMobileEl.dataset.src && videoDesktopEl.dataset.src) { + videoDesktopEl.src = videoDesktopEl.dataset.src; + videoMobileEl.src = videoMobileEl.dataset.src; + } + } + + setViewPortEntered(true); + }; async function getProjects() { try { @@ -336,10 +373,8 @@ export default function App() { - console.log("first", featureRef.current.firstElementChild) - } + viewport={{ margin: "-10%" }} + onViewportEnter={handleOnViewportFeatureEnter} >
@@ -416,14 +451,13 @@ export default function App() { /> */}
-
- -
+ - +
{/* */} diff --git a/src/components/FeatureVideoViewBox.tsx b/src/components/FeatureVideoViewBox.tsx index 15a8a97..876e0f3 100644 --- a/src/components/FeatureVideoViewBox.tsx +++ b/src/components/FeatureVideoViewBox.tsx @@ -1,36 +1,65 @@ import { useEffect, useRef } from "react"; interface FeatureVideoViewBoxProps { - video: string; + selectedVideo: string; + videos: string[]; + featureRef: React.LegacyRef; } -function FeatureVideoViewBox({ video }: FeatureVideoViewBoxProps) { +function FeatureVideoViewBox({ + selectedVideo, + videos, + featureRef, +}: FeatureVideoViewBoxProps) { // const videoRef = useRef(null); const videoContainerRef = useRef(null); + // useEffect(() => { + // if (!selectedVideo || !videoContainerRef.current) return; + + // const videoEl = document.createElement("video"); + // videoEl.src = selectedVideo; + // videoEl.muted = true; + // videoEl.autoplay = true; + // videoEl.loop = true; + // videoEl.playsInline = true; + // videoEl.preload = "metadata"; + // videoEl.classList.add("absolute", "h-fit"); + // // videoEl.onloadeddata = () => console.log("onloadeddata"); + + // videoContainerRef.current.appendChild(videoEl); + + // if (videoContainerRef.current.childElementCount > 1) { + // setTimeout(() => { + // videoContainerRef.current?.firstElementChild?.remove(); + // }, 5000); + // } + // }, [selectedVideo]); + useEffect(() => { - if (!video || !videoContainerRef.current) return; + return () => {}; + }, [selectedVideo]); - const videoEl = document.createElement("video"); - videoEl.src = video; - videoEl.muted = true; - videoEl.autoplay = true; - videoEl.loop = true; - videoEl.playsInline = true; - videoEl.preload = "metadata"; - videoEl.classList.add("absolute", "h-fit"); - // videoEl.onloadeddata = () => console.log("onloadeddata"); - - videoContainerRef.current.appendChild(videoEl); - - if (videoContainerRef.current.childElementCount > 1) { - setTimeout(() => { - videoContainerRef.current?.firstElementChild?.remove(); - }, 5000); - } - }, [video]); - - return
; + return ( +
+
+ {videos.map((video) => ( +
+
+ ); } export default FeatureVideoViewBox; diff --git a/src/components/VideoSliderMobile.tsx b/src/components/VideoSliderMobile.tsx index d3af0fc..6542a75 100644 --- a/src/components/VideoSliderMobile.tsx +++ b/src/components/VideoSliderMobile.tsx @@ -6,7 +6,11 @@ import ArrowLeftIcon from "./icons/ArrowLeftIcon"; import ArrowRightIcon from "./icons/ArrowRightIcon"; import { useSwipeable } from "react-swipeable"; -function VideoSliderMobile() { +interface IVideoSliderMobile { + featureRef: React.LegacyRef; +} + +function VideoSliderMobile({ featureRef }: IVideoSliderMobile) { const [items] = useState([ { title: "Виртуальный тур по жилому комплексу", @@ -102,7 +106,7 @@ function VideoSliderMobile() { className="xl:hidden flex flex-col sm:gap-6 gap-4 border-b border-[#3D425C] pb-5" >
@@ -110,7 +114,7 @@ function VideoSliderMobile() {