Skip to content

Commit

Permalink
Merge pull request #31 from JongMany/feat/refactor-architecture
Browse files Browse the repository at this point in the history
[Feat] 이미지 LazyLoad 기능 추가
  • Loading branch information
JongMany authored Jul 29, 2024
2 parents e89bd5b + 78e4f12 commit 4a638db
Show file tree
Hide file tree
Showing 13 changed files with 178 additions and 122 deletions.
1 change: 0 additions & 1 deletion fe/src/entities/projects/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export { default } from "./ui/project/Project";
export { default as ProjectContainer } from "./ui/project/ProjectContainer";
export { default as FileDownloadButton } from "./ui/download-button/FileDownloadButton";
38 changes: 38 additions & 0 deletions fe/src/entities/projects/ui/project/ImageContainer.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.blurred-img {
background-repeat: no-repeat;
background-size: cover;
}

@keyframes pulse {
0% {
opacity: 0;
}
50% {
opacity: 0.1;
}
100% {
opacity: 0;
}
}

.blurred-img::before {
content: "";
position: absolute;
inset: 0;
opacity: 0;
animation: pulse 2.5s infinite;
background-color: white;
}
.blurred-img.loaded::before {
animation: none;
content: none;
}

.blurred-img img {
opacity: 0;
transition: opacity 250ms ease-in-out;
}

.blurred-img.loaded img {
opacity: 1;
}
112 changes: 0 additions & 112 deletions fe/src/entities/projects/ui/project/Project.tsx

This file was deleted.

45 changes: 43 additions & 2 deletions fe/src/entities/projects/ui/project/ProjectContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { useDeviceSize } from "@/shared/libs";
import { PropsWithChildren, useRef } from "react";
import { PropsWithChildren, useEffect, useRef, useState } from "react";
import { motion, useInView } from "framer-motion";
import { Link } from "react-router-dom";
import "./ImageContainer.css";

type Props = {
isAlignReverse?: boolean;
};
Expand Down Expand Up @@ -44,18 +46,57 @@ function getAlignStyle(alignDirection: "row" | "col", alignReverse?: boolean) {
return "flex-row";
}

// https://blog.webdevsimplified.com/2023-05/lazy-load-images/
const ImageContainer = ({
image,
alt = "project",
smallImageUrl,
}: {
image: string;
alt?: string;
smallImageUrl: string;
}) => {
const device = useDeviceSize();
const imageStyle = device === "desktop" ? "w-full" : "w-[80vw] h-[40vh]";
const blurredImageDivRef = useRef<HTMLDivElement>(null);
const imageRef = useRef<HTMLImageElement>(null);
const [isLoaded, setIsLoaded] = useState(false);

useEffect(() => {
function loaded() {
if (blurredImageDivRef.current) {
setIsLoaded(true);
blurredImageDivRef.current.classList.add("loaded");
}
}

const img = imageRef.current;
if (img?.complete) {
loaded();
} else {
img?.addEventListener("load", loaded);
}

return () => {
img?.removeEventListener("load", loaded);
};
}, []);

return (
<div className="basis-[50%] flex flex-col items-center justify-center">
<img className={`${imageStyle}`} src={image} alt={alt} />
<div
style={{ backgroundImage: `url(${smallImageUrl})` }}
className={`blurred-img`}
ref={blurredImageDivRef}
>
<img
ref={imageRef}
className={`${imageStyle}`}
src={image}
alt={alt}
loading="lazy"
/>
</div>
</div>
);
};
Expand Down
54 changes: 54 additions & 0 deletions fe/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,57 @@
body {
margin: 0;
}

/* .blurred-img img {
opacity: 0;
}
.blurred-img {
background-repeat: no-repeat;
background-size: cover;
}
.blurred-img {
filter: blur(10px);
}
.blurred-img::before {
content: "";
position: absolute;
inset: 0;
opacity: 0;
animation: pulse 2.5s infinite;
background-color: white;
}
@layer components {
@keyframes pulse {
0% {
opacity: 0;
}
50% {
opacity: 0.1;
}
100% {
opacity: 0;
}
}
.blurred-img {
@apply relative bg-no-repeat bg-cover;
}
.blurred-img::before {
@apply content-[''] absolute inset-0 opacity-0 animation-pulse bg-text-color;
}
.blurred-img.loaded::before {
@apply animation-none content-none;
}
.blurred-img img {
@apply transition-opacity ease-in-out opacity-0 duration-250;
}
.blurred-img.loaded img {
@apply opacity-100;
}
} */
Binary file added fe/src/shared/assets/images/crypto-small.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fe/src/shared/assets/images/eyeve-small.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fe/src/shared/assets/images/portfolio-small.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fe/src/shared/assets/images/study-log-small.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@ import { ProjectContainer as Project } from "@/entities/projects/index";

// IMG Resources
import studyLogProjectImg from "@/shared/assets/images/study-log.png";
import studyLogProjectSmallImg from "@/shared/assets/images/study-log-small.png";
import readyToWorkProjectImg from "@/shared/assets/images/ready_to_work.png";
import readyToWorkProjectSmallImg from "@/shared/assets/images/ready_to_work-small.png";
import cryptoProjectImg from "@/shared/assets/images/crypto.png";
import cryptoProjectSmallImg from "@/shared/assets/images/crypto-small.png";
import eyeveProjectImg from "@/shared/assets/images/eyeve.png";
import eyeveProjectSmallImg from "@/shared/assets/images/eyeve-small.png";
import vscodeExtensionProjectImg from "@/shared/assets/images/vscode-extension.png";
import vscodeExtensionProjectSmallImg from "@/shared/assets/images/vscode-extension-small.png";
import portfolioProjectImg from "@/shared/assets/images/portfolio.png";
import portfolioProjectSmallImg from "@/shared/assets/images/portfolio-small.png";
import { withLoading } from "@/widgets/main/projectsShowcase/ui/withLoading/withLoading";

function ProjectsShowCase() {
Expand Down Expand Up @@ -58,7 +65,10 @@ function ProjectsShowCase() {
{/* Ready To Work Project */}
<ContentContainer>
<Project isAlignReverse={false}>
<Project.ImageContainer image={readyToWorkProjectImg} />
<Project.ImageContainer
image={readyToWorkProjectImg}
smallImageUrl={readyToWorkProjectSmallImg}
/>
<Project.Description
projectName="Ready To Work"
projectDescription="엔카의 김상범 대표님과 광운대학교의 IDEA Lab에서 진행한 프로젝트입니다. HR 도메인의 B2B 서비스이며, 문제 해결 방식을 통해 인재 채용을 쉽게 할 수 있도록 도움을 주고자 서비스를 기획하였습니다."
Expand All @@ -79,7 +89,10 @@ function ProjectsShowCase() {

<ContentContainer>
<Project isAlignReverse={true}>
<Project.ImageContainer image={eyeveProjectImg} />
<Project.ImageContainer
image={eyeveProjectImg}
smallImageUrl={eyeveProjectSmallImg}
/>
<Project.Description
projectName="Eyeve"
projectDescription="광운대학교 IDEA Lab에서 카메라를 통한 시선 추적을 통해 학생들의 집중도를 분석하는 연구용 서비스를 개발하였습니다. 2024년 춘계 산업공학회의 포스터 세션에 등록되기도 하였습니다."
Expand All @@ -103,7 +116,10 @@ function ProjectsShowCase() {
{/* 암호화폐 차트 */}
<ContentContainer>
<Project isAlignReverse={false}>
<Project.ImageContainer image={cryptoProjectImg} />
<Project.ImageContainer
image={cryptoProjectImg}
smallImageUrl={cryptoProjectSmallImg}
/>
<Project.Description
projectName="암호화폐 차트 그래프"
projectDescription="항해 플러스 프론트엔드 1기에서 진행한 프로젝트입니다. 암호화폐 차트 그래프를 보여주는 서비스를 개발하였습니다."
Expand All @@ -125,7 +141,10 @@ function ProjectsShowCase() {
{/* 웹 기반 스터디 인증 SNS */}
<ContentContainer>
<Project isAlignReverse={true}>
<Project.ImageContainer image={studyLogProjectImg} />
<Project.ImageContainer
image={studyLogProjectImg}
smallImageUrl={studyLogProjectSmallImg}
/>
<Project.Description
projectName="웹 기반 스터디 인증 SNS"
projectDescription="웹 서비스 설계 및 실습 수업에서 진행한 SNS 플랫폼 서비스입니다. 스터디 인증을 통해 사용자들이 서로 인증을 공유하고 소통할 수 있는 서비스를 개발하였습니다."
Expand All @@ -144,7 +163,10 @@ function ProjectsShowCase() {
{/* VSCode Extension */}
<ContentContainer>
<Project isAlignReverse={false}>
<Project.ImageContainer image={vscodeExtensionProjectImg} />
<Project.ImageContainer
image={vscodeExtensionProjectImg}
smallImageUrl={vscodeExtensionProjectSmallImg}
/>
<Project.Description
projectName="StudyLog VSCode Extension"
projectDescription="개발자의 개발 시간을 측정해주는 VSCode Extension을 개발하였습니다."
Expand All @@ -166,7 +188,10 @@ function ProjectsShowCase() {
</ContentContainer>
<ContentContainer>
<Project isAlignReverse={false}>
<Project.ImageContainer image={vscodeExtensionProjectImg} />
<Project.ImageContainer
image={portfolioProjectImg}
smallImageUrl={portfolioProjectSmallImg}
/>
<Project.Description
projectName="포트폴리오 사이트"
projectDescription="제가 개발한 프로젝트들을 소개하는 포트폴리오 사이트입니다. SEO 최적화를 위해 많은 노력을 기울였습니다."
Expand Down
13 changes: 12 additions & 1 deletion fe/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,18 @@
export default {
content: ["./index.html", "./src/**/*.{js,jsx,ts,tsx}"],
theme: {
extend: {},
extend: {
keyframes: {
pulse: {
"0%": { opacity: "0" },
"50%": { opacity: "0.1" },
"100%": { opacity: "0" },
},
},
animation: {
pulse: "pulse 2.5s infinite",
},
},
},
plugins: [require("tailwind-scrollbar-hide")],
};

0 comments on commit 4a638db

Please sign in to comment.