robinyoon-dev / plan-bingo-project

This repository is about Plan Bingo which I made as a project.
0 stars 0 forks source link

๐Ÿž ์•„์ดํŒจ๋“œ์—์„œ '์ด๋ฏธ์ง€๋กœ ์ €์žฅํ•˜๊ธฐ' ๊ธฐ๋Šฅ์ด ์ž‘๋™ ์•ˆ ๋˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ #42

Open robinyoon-dev opened 1 year ago

robinyoon-dev commented 1 year ago

Description

์•„์ดํŒจ๋“œ safari์—์„œ ์ด๋ฏธ์ง€ ์ €์žฅ ์•ˆ ๋˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐํ•˜์ž.

Todo

์•„์ดํฐ, ๋งฅ๋ถ ํ”ผ๋“œ๋ฐฑ

  1. ์•„์ดํฐ ํฌ๋กฌ์—์„œ๋„ ์ž‘๋™ X image

์ž๋ฃŒ

์•„์ดํฐ, ์•„์ดํŒจ๋“œ์˜ ์‚ฌํŒŒ๋ฆฌ์—์„œ ๊ฐœ๋ฐœ์ž ๋„๊ตฌ ์—ด๊ธฐ(SAFARI DEBUGGING) file-saver ๊ณต์‹ ๋ฌธ์„œ [React] ํ™”๋ฉด(DOM) ์บก์ณ ๋ฐ ์ €์žฅ ๊ธฐ๋Šฅ ๊ตฌํ˜„ํ•˜๊ธฐ (feat. html2canvas, file-saver)

robinyoon-dev commented 1 year ago

file-saver๋ฅผ ์‚ฌ์šฉํ–ˆ์œผ๋‚˜ safari์—์„  ๋™์ž‘์„ ์•ˆํ•จ.

ํ˜„์žฌ ์ฝ”๋“œ

import { MongoClient, ObjectId } from "mongodb";
import ShareBoard from "@/components/boards/ShareBoard";
import Layout from "@/components/layout/Layout";
import { useState, useEffect, useRef } from "react";
import styles from "@/styles/style.module.css";
import Link from "next/link";
import Grid1fr from "@/components/layout/Grid1fr";
import LoadingSpinner from "@/components/parts/LoadingSpinner";
import Head from "next/head";
import Confetti from "@/components/parts/Confetti";
import config from "@/config/mongo.config";
import html2canvas from "html2canvas";
import Image from "next/image";
import btnStyles from "@/components/layout/Button.module.css";
import saveAs from "file-saver";

function SharePage({ newBoard, bingoData, data }) {
  const [showCopiedMessage, setShowCopiedMessage] = useState(false);

  const [isLoading, setIsLoading] = useState(true);

  const divRef = useRef(null);
  const canvasRef = useRef(null);

  useEffect(() => {
    if (data !== null) {
      setIsLoading(false);
    }
  }, []);

  if (isLoading) {
    return <LoadingSpinner />;
  }

  const bingoUrl = getBingoUrl(bingoData);

  const shareUrl = `https://planbingo.vercel.app/fromLink?id=${data.id}${bingoUrl}`;

  const handleCopyClick = () => {
    navigator.clipboard.writeText(shareUrl);
    setShowCopiedMessage(true);
  };

  const downloadCanvasDiv = () => {
    const div = divRef.current;
    const canvas = canvasRef.current;

    canvas.width = div.offsetWidth;
    canvas.height = div.offsetHeight;

    html2canvas(div).then((canvas) => {
      canvas.toBlob((blob) => {
        if (blob != null) {
          saveAs(blob, `${data.title}.png`);
        }
      });
    });
  };

  return (
    <>
      <Head>
        <title>ํ”Œ๋žœ ๋น™๊ณ </title>
      </Head>

      <Layout>
        {newBoard.newBoard && <Confetti />}
        {data.bingoCount === 8 && <Confetti />}
        {newBoard.newBoard && (
          <div className={styles.fontSize}>
            ์ฒ˜์Œ์œผ๋กœ ํ”Œ๋žœ ๋น™๊ณ ๋ฅผ ๋งŒ๋“ค์—ˆ์–ด์š”!
          </div>
        )}
        {newBoard.newBoard === false && data.bingoCount !== 8 && (
          <div className={styles.fontSize}> ๐Ÿ‘๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ–ˆ๊ตฐ์š”!๐Ÿ‘</div>
        )}
        {data.bingoCount === 8 && (
          <div className={styles.fontSize}>
            {" "}
            ๐ŸŽ‰์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ๋น™๊ณ ๋ฅผ ์™„์„ฑํ–ˆ์–ด์š”!๐ŸŽ‰
          </div>
        )}

        <canvas ref={canvasRef} className={styles.canvas}></canvas>

        <div ref={divRef} className={styles.canvasDiv}>
          <ShareBoard
            bingoData={bingoData}
            main={data.main}
            title={data.title}
            value1={data.value1}
            value2={data.value2}
            value3={data.value3}
            value4={data.value4}
            value5={data.value5}
            value6={data.value6}
            value7={data.value7}
            value8={data.value8}
            value9={data.value9}
            bgColor={data.bgColor}
            cubeColor={data.cubeColor}
            bingoCount={data.bingoCount}
            patternArray={data.patternArray}
          />
        </div>

        {newBoard.newBoard && (
          <div className={styles.fontSizeS}>๋ชฉํ‘œ๋ฅผ ๊ณต์œ ํ•ด๋ณผ๊นŒ์š”?</div>
        )}
        {newBoard.newBoard === false && data.bingoCount !== 8 && (
          <div className={styles.fontSizeS}> ํ”Œ๋žœ ๋น™๊ณ ๋ฅผ ๊ณต์œ ํ•ด๋ด์š”๐Ÿ˜Š</div>
        )}
        {data.bingoCount === 8 && (
          <div className={styles.fontSizeS}>
            {" "}
            ์™„์„ฑํ•œ ํ”Œ๋žœ ๋น™๊ณ ๋ฅผ ์ž๋ž‘ํ•ด๋ด์š”!
          </div>
        )}

        {showCopiedMessage && (
          <div className={styles.alarm}>๋งํฌ๊ฐ€ ๋ณต์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!</div>
        )}
        <Grid1fr>
          <button
            className={[btnStyles.button, styles.btnColor].join(" ")}
            onClick={downloadCanvasDiv}
          >
            <Image
              src={"/download.svg"}
              alt={"download an image"}
              width={30}
              height={30}
            />{" "}
            <p>์ด๋ฏธ์ง€๋กœ ์ €์žฅํ•˜๊ธฐ</p>
          </button>

          <button
            onClick={handleCopyClick}
            className={[btnStyles.button, styles.btnColor].join(" ")}
          >
            <Image
              src={"/link.svg"}
              alt={"share a link"}
              width={30}
              height={30}
            />{" "}
            <p>๋งํฌ ๋ณต์‚ฌํ•˜๊ธฐ</p>
          </button>

          <Link
            className={[btnStyles.button, styles.btnNoneColor].join(" ")}
            href="/home"
          >
            <Image
              src={"/home.svg"}
              alt={"back to home"}
              width={30}
              height={30}
            />{" "}
            <p>ํ™ˆ์œผ๋กœ</p>
          </Link>
        </Grid1fr>
      </Layout>
    </>
  );
}

export async function getServerSideProps(ctx) {
  let newBoard, bingoData, data;

  if (ctx.query.bingoData) {
    bingoData = JSON.parse(ctx.query.bingoData);
  } else {
    bingoData = {
      bingo123: false,
      bingo456: false,
      bingo789: false,
      bingo147: false,
      bingo258: false,
      bingo369: false,
      bingo159: false,
      bingo357: false,
    };
  }

  data = JSON.parse(ctx.query.data);

  if (data.newBoard) {
    newBoard = true;
  } else {
    newBoard = false;
  }

  // fetch data from an API
  const client = await MongoClient.connect(config.mongoClient);
  const db = client.db();

  const boardsCollection = db.collection("boards");

  const board = await boardsCollection.findOne({ _id: ObjectId(data._id) });

  client.close();

  return {
    props: {
      newBoard: {
        newBoard,
      },
      bingoData: {
        bingo123: bingoData.bingo123,
        bingo456: bingoData.bingo456,
        bingo789: bingoData.bingo789,
        bingo147: bingoData.bingo147,
        bingo258: bingoData.bingo258,
        bingo369: bingoData.bingo369,
        bingo159: bingoData.bingo159,
        bingo357: bingoData.bingo357,
      },
      data: {
        id: board._id.toString(),
        user: board.user,
        main: board.main,
        title: board.title,
        value1: board.value1,
        value2: board.value2,
        value3: board.value3,
        value4: board.value4,
        value5: board.value5,
        value6: board.value6,
        value7: board.value7,
        value8: board.value8,
        value9: board.value9,
        bgColor: board.bgColor,
        cubeColor: board.cubeColor,
        bingoCount: board.bingoCount,
        patternArray: board.patternArray,
      },
    },
  };
}

export function getBingoUrl(bingoData) {
  const bingoNumbers = [
    "bingo123",
    "bingo456",
    "bingo789",
    "bingo147",
    "bingo258",
    "bingo369",
    "bingo159",
    "bingo357",
  ];

  const tempArray = bingoNumbers.map((bingoNumber) => {
    if (bingoData[bingoNumber]) {
      return `&bingo=${bingoNumber}`;
    } else {
      return;
    }
  });

  return tempArray.join("");
}

export default SharePage;
robinyoon-dev commented 1 year ago

blob์„ url๋กœ ๋ฐ”๊ฟจ์œผ๋‚˜ safari์—์„œ๋Š” ์—ฌ์ „ํžˆ ๋‹ค์šด๋กœ๋“œ ๋ถˆ๊ฐ€

์ฝ”๋“œ

    html2canvas(div).then((canvas) => {

      const dataURL = canvas.toDataURL("image/png");
      saveAs(dataURL, `${data.title}.png`);

};