diff --git a/package.json b/package.json index e3d88c39..96d6d553 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "dependencies": { "@types/react-gtm-module": "^2.0.1", "axios": "^0.26.0", + "compressorjs": "^1.1.1", "qs": "^6.11.0", "react": "^18.1.0", "react-dom": "^18.1.0", diff --git a/src/@components/JoinPage/UserProfilePage/ProfileImage/index.tsx b/src/@components/JoinPage/UserProfilePage/ProfileImage/index.tsx index a2cc6957..8995e6bf 100644 --- a/src/@components/JoinPage/UserProfilePage/ProfileImage/index.tsx +++ b/src/@components/JoinPage/UserProfilePage/ProfileImage/index.tsx @@ -2,30 +2,37 @@ import { useState } from "react"; import { IcAddProfileBtn } from "../../../../asset/icon"; import { ImgDefaultBigProfile } from "../../../../asset/image"; +import compressImage from "../../../../util/imageCompressor"; import { St } from "./style"; interface ProfileImageProps { - setImage: (file: File) => void; + setProfileImage: (file: File) => void; } +const MAX_IMAGE_SIZE = 80 * 2; + export default function ProfileImage(props: ProfileImageProps) { - const { setImage } = props; - const [imgUrl, setImgUrl] = useState(""); + const { setProfileImage } = props; + const [previewImgUrl, setPreviewImgUrl] = useState(""); const handleImagePatch = async (e: React.ChangeEvent) => { if (e.target.files === null) return; const selectedImg = e.target.files[0]; - setImgUrl(URL.createObjectURL(selectedImg)); + const compressedSelectedImg = await compressImage(selectedImg, { + maxWidth: MAX_IMAGE_SIZE, + maxHeight: MAX_IMAGE_SIZE, + }); - setImage(selectedImg); + setProfileImage(compressedSelectedImg); + setPreviewImgUrl(URL.createObjectURL(compressedSelectedImg)); }; return ( - + diff --git a/src/@components/JoinPage/UserProfilePage/index.tsx b/src/@components/JoinPage/UserProfilePage/index.tsx index d4747aa0..12b8cf1a 100644 --- a/src/@components/JoinPage/UserProfilePage/index.tsx +++ b/src/@components/JoinPage/UserProfilePage/index.tsx @@ -20,7 +20,7 @@ export default function UserProfilePage() { const [birthData, setBirthData] = useState(""); // 생년월일 // TODO :: 변수명 gender로 바꾸기 const [isSelected, setIsSelected] = useState(""); // 성별 - const [image, setImage] = useState(ImgDefaultBigProfile); // 이미지 + const [profileImage, setProfileImage] = useState(ImgDefaultBigProfile); // 이미지 const [isChecked, setIsChecked] = useState(false); //닉넴 중복 확인 const [isInComplete, setisInComplete] = useState(false); // 다음으로 버튼 @@ -44,7 +44,7 @@ export default function UserProfilePage() { currentFormData.append("birthday", birthData); if (isSelected) currentFormData.append("gender", isSelected); - if (image) currentFormData.append("imgFile", image); + if (profileImage) currentFormData.append("imgFile", profileImage); return currentFormData; }); @@ -64,7 +64,8 @@ export default function UserProfilePage() { 프로필을 설정해주세요 프로필 사진(선택) - + + 닉네임(필수) ※ 한글, 영문, 숫자 상관없이 8자 이내 {bannerImage.map((img, index) => ( - + ))} diff --git a/src/asset/asset.d.ts b/src/asset/asset.d.ts index ae434a6c..62931e98 100644 --- a/src/asset/asset.d.ts +++ b/src/asset/asset.d.ts @@ -2,6 +2,7 @@ declare module "*.jpg"; declare module "*.png"; declare module "*.jpeg"; declare module "*.gif"; +declare module "*.webp"; declare module "*.svg" { import React = require("react"); diff --git a/src/asset/image/banner_1.webp b/src/asset/image/banner_1.webp new file mode 100644 index 00000000..c6bf4d19 Binary files /dev/null and b/src/asset/image/banner_1.webp differ diff --git a/src/asset/image/banner_2.webp b/src/asset/image/banner_2.webp new file mode 100644 index 00000000..3b856790 Binary files /dev/null and b/src/asset/image/banner_2.webp differ diff --git a/src/asset/image/banner_3.webp b/src/asset/image/banner_3.webp new file mode 100644 index 00000000..83a77031 Binary files /dev/null and b/src/asset/image/banner_3.webp differ diff --git a/src/asset/image/categoryBanner.webp b/src/asset/image/categoryBanner.webp new file mode 100644 index 00000000..512c5993 Binary files /dev/null and b/src/asset/image/categoryBanner.webp differ diff --git a/src/asset/image/defaultBigProfile.webp b/src/asset/image/defaultBigProfile.webp new file mode 100644 index 00000000..073d8fd9 Binary files /dev/null and b/src/asset/image/defaultBigProfile.webp differ diff --git a/src/asset/image/defaultProfile.webp b/src/asset/image/defaultProfile.webp new file mode 100644 index 00000000..4a6659df Binary files /dev/null and b/src/asset/image/defaultProfile.webp differ diff --git a/src/asset/image/index.tsx b/src/asset/image/index.tsx index 00481598..20fa728e 100644 --- a/src/asset/image/index.tsx +++ b/src/asset/image/index.tsx @@ -1,8 +1,8 @@ -export { default as ImgBanner1 } from "./banner_1.png"; -export { default as ImgBanner2 } from "./banner_2.png"; -export { default as ImgBanner3 } from "./banner_3.png"; -export { default as ImgCategoryBanner } from "./categoryBanner.png"; -export { default as ImgDefaultBigProfile } from "./defaultBigProfile.png"; -export { default as ImgDefaultProfile } from "./defaultProfile.png"; -export { default as ImgPiickleLoading } from "./piickleLoading.gif"; -export { default as ImgVoteBanner } from "./voteBanner.png"; +export { default as ImgBanner1 } from "./banner_1.webp"; +export { default as ImgBanner2 } from "./banner_2.webp"; +export { default as ImgBanner3 } from "./banner_3.webp"; +export { default as ImgCategoryBanner } from "./categoryBanner.webp"; +export { default as ImgDefaultBigProfile } from "./defaultBigProfile.webp"; +export { default as ImgDefaultProfile } from "./defaultProfile.webp"; +export { default as ImgPiickleLoading } from "./piickleLoading.webp"; +export { default as ImgVoteBanner } from "./voteBanner.webp"; diff --git a/src/asset/image/banner_1.png b/src/asset/image/origin/banner_1.png similarity index 100% rename from src/asset/image/banner_1.png rename to src/asset/image/origin/banner_1.png diff --git a/src/asset/image/banner_2.png b/src/asset/image/origin/banner_2.png similarity index 100% rename from src/asset/image/banner_2.png rename to src/asset/image/origin/banner_2.png diff --git a/src/asset/image/banner_3.png b/src/asset/image/origin/banner_3.png similarity index 100% rename from src/asset/image/banner_3.png rename to src/asset/image/origin/banner_3.png diff --git a/src/asset/image/categoryBanner.png b/src/asset/image/origin/categoryBanner.png similarity index 100% rename from src/asset/image/categoryBanner.png rename to src/asset/image/origin/categoryBanner.png diff --git a/src/asset/image/defaultBigProfile.png b/src/asset/image/origin/defaultBigProfile.png similarity index 100% rename from src/asset/image/defaultBigProfile.png rename to src/asset/image/origin/defaultBigProfile.png diff --git a/src/asset/image/defaultProfile.png b/src/asset/image/origin/defaultProfile.png similarity index 100% rename from src/asset/image/defaultProfile.png rename to src/asset/image/origin/defaultProfile.png diff --git a/src/asset/image/piickleLoading.gif b/src/asset/image/origin/piickleLoading.gif similarity index 100% rename from src/asset/image/piickleLoading.gif rename to src/asset/image/origin/piickleLoading.gif diff --git a/src/asset/image/voteBanner.png b/src/asset/image/origin/voteBanner.png similarity index 100% rename from src/asset/image/voteBanner.png rename to src/asset/image/origin/voteBanner.png diff --git a/src/asset/image/piickleLoading.webp b/src/asset/image/piickleLoading.webp new file mode 100644 index 00000000..69058442 Binary files /dev/null and b/src/asset/image/piickleLoading.webp differ diff --git a/src/asset/image/voteBanner.webp b/src/asset/image/voteBanner.webp new file mode 100644 index 00000000..c6192245 Binary files /dev/null and b/src/asset/image/voteBanner.webp differ diff --git a/src/util/imageCompressor.ts b/src/util/imageCompressor.ts new file mode 100644 index 00000000..f9cc08df --- /dev/null +++ b/src/util/imageCompressor.ts @@ -0,0 +1,26 @@ +import Compressor from "compressorjs"; + +interface CompressorImageOption { + maxWidth: number; + maxHeight: number; + quality?: number; +} + +// TODO :: File | Blob 호환성 +export default function compressImage(file: File, option?: CompressorImageOption): Promise { + return new Promise((resolve, reject) => { + new Compressor(file, { + maxWidth: option?.maxWidth, + maxHeight: option?.maxHeight, + quality: option?.quality ?? 0.6, + + success: (result) => { + // if(result instance File) + resolve(new File([result], file.name)); + }, + error: (result) => { + reject(result); + }, + }); + }); +} diff --git a/yarn.lock b/yarn.lock index d4238b31..a9481c38 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4722,6 +4722,11 @@ bluebird@^3.5.5: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== +blueimp-canvas-to-blob@^3.29.0: + version "3.29.0" + resolved "https://registry.yarnpkg.com/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz#d965f06cb1a67fdae207a2be56683f55ef531466" + integrity sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg== + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -5553,6 +5558,14 @@ compression@^1.7.4: safe-buffer "5.1.2" vary "~1.1.2" +compressorjs@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/compressorjs/-/compressorjs-1.1.1.tgz#54c147cf37fb38828b08c48646d0258d52faf050" + integrity sha512-SysRuUPfmUNoq+RviE0iMFVUmoX2q/x+7PkEPUmk6NGkd85hDrmvujx0Qtp8UCGA6KMe5kuodsylPQcNaLf60w== + dependencies: + blueimp-canvas-to-blob "^3.29.0" + is-blob "^2.1.0" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -8614,6 +8627,11 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-blob@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-blob/-/is-blob-2.1.0.tgz#e36cd82c90653f1e1b930f11baf9c64216a05385" + integrity sha512-SZ/fTft5eUhQM6oF/ZaASFDEdbFVe89Imltn9uZr03wdKMcWNVYSMjQPFtg05QuNkt5l5c135ElvXEQG0rk4tw== + is-boolean-object@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719"