유튜브 클론코딩(영상 부분편)

TaeHyun Lee·2022년 9월 19일
0

유튜브 클론코딩

목록 보기
5/7

영상 부분 만들기

만든 부분 - 2022 / 09 / 12


뭐를 만든거지 싶을 정도로 아무것도 안 해버렸다...


NextJS 코드 (VideoPart.js)

import React from 'react'
import styles from "../styles/VideoPart.module.css"

const VideoPart = () => {
  return (
    <>
        <div className={styles.Video}></div>
        <div className={styles.Video_info_box}>
            <div className={styles.Video_title_box}>
                <span>#SeeYouAgain</span>
                <p>Wiz Khalifa - See You Again ft. Charlie Puth [Official Video] Furious 7 Soundtrack</p>
            </div>
            {/* <div>
                <img />
                <div>
                    <span>Wiz Khalifa</span>
                    <p>구독자</p>
                </div>
                <div>구독</div>
                <div>
                    <div className={styles.}></div>
                </div>
            </div> */}
        </div>
    </>
  )
}

export default VideoPart

CSS 코드 (VideoPart.module.css)

.Video {
    margin-top: 30px;
    background-color: black;
    width: 95%;
    height: 530px;
    margin-bottom: 10px;
}
.Video_info_box {
    width: 95%;
    height: 40px;
    /* background-color: antiquewhite; */
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}
.Video_info_box span {
    color: rgb(0, 85, 255);
    font-size: 12px;
}
.Video_info_box p {
    margin: 0;
    font-size: 20px;
    font-weight: 600;

}

현재까지의 전체 화면


전체 화면으로 보니 괜찮아 보인다! ㅎㅎ


만든 부분 - 2022 / 09 / 15


오늘은 영상을 시청할 때 나오는 화면에서 제목 아래에 있는 부분을 만들어보았다. 보기에 간단하지만 이 부분에는 조금의 기능이 있다.

이런식으로 좋아요 아이콘과 싫어요 아이콘, 공유 아이콘, 오프라인 저장 아이콘에 마우스오버를 하면 아래에 작은 박스와 글이 생긴다. 그리고 마우스리브를 하면 다시 사라진다. 이러한 기능이 헤더부분에도 있어서 헤더부분도 같이 수정해주었다.


NextJS 코드 (VideoPart.js)

import React, { useState } from 'react'
import styles from "../styles/VideoPart.module.css"
import { FiThumbsUp, FiThumbsDown } from "react-icons/fi"
import { RiShareForwardLine, RiScissorsLine, RiPlayListAddLine } from "react-icons/ri"
import { HiDownload, HiOutlineDotsHorizontal } from "react-icons/hi"

const VideoPart = () => {
    const [isLikeMouseOver, setIsLikeMouseOver] = useState(false);
    const [isUnlikeMouseOver, setIsUnlikeMouseOver] = useState(false);
    const [isShareMouseOver, setIsShareMouseOver] = useState(false);
    const [isDownloadMouseOver, setIsDownloadMouseOver] = useState(false);
    return (
        <>
            <div className={styles.Video}></div>
            <div className={styles.Video_info_box}>
                <div className={styles.Video_title_box}>
                    <span>#SeeYouAgain</span>
                    <p>Wiz Khalifa - See You Again ft. Charlie Puth [Official Video] Furious 7 Soundtrack</p>
                </div>
                <div className={styles.Video_option}>
                    <div className={styles.Uploader_info_box}>
                        <div className={styles.Uploader_info}>
                            <img src='https://yt3.ggpht.com/ytc/AMLnZu9I_o5dok5_ZSuZQPzS5__4R2g6IqYpNAncmQee=s88-c-k-c0x00ffffff-no-rj' />
                            <div>
                                <span>essential;</span>
                                <p>구독자 100만명</p>
                            </div>
                        </div>
                        <div className={styles.Subscribe_button}>구독</div>
                    </div>
                    <div className={styles.Box_in_option}>
                        <div className={styles.OptionBox_container}>
                            <div 
                                onMouseOver={() => {setIsLikeMouseOver(true)}}
                                onMouseLeave={() => {setIsLikeMouseOver(false)}}
                            >
                                <FiThumbsUp size={22} />
                                <span>4.2</span>
                            </div>
                            <div 
                                onMouseOver={() => {setIsUnlikeMouseOver(true)}}
                                onMouseLeave={() => {setIsUnlikeMouseOver(false)}}
                            >
                                <FiThumbsDown size={22} />
                                <span>싫어요</span>
                            </div>
                            <div 
                                onMouseOver={() => {setIsShareMouseOver(true)}}
                                onMouseLeave={() => {setIsShareMouseOver(false)}}
                            >
                                <RiShareForwardLine size={22} />
                                <span>공유</span>
                            </div>
                            <div 
                                onMouseOver={() => {setIsDownloadMouseOver(true)}}
                                onMouseLeave={() => {setIsDownloadMouseOver(false)}}
                            >
                                <HiDownload size={22} />
                                <span>오프라인저장</span>
                            </div>
                            <div>
                                <HiOutlineDotsHorizontal size={22} />
                            </div>
                        </div>
                    </div>
                </div>
                <hr className={styles.Line_under_option} />
                <div className={styles.Video_explanation_box}>
                    { isLikeMouseOver && <div className={styles.Like_popup_box}>이 동영상이 마음에 듭니다.</div> }
                    { isUnlikeMouseOver  && <div className={styles.Unlike_popup_box}>이 동영상이 마음에 들지 않습니다.</div> }
                    { isShareMouseOver && <div className={styles.Share_popup_box}>공유</div> }
                    { isDownloadMouseOver && <div className={styles.Download_popup_box}>오프라인저장</div> }
                </div>
            </div>
        </>
    )
}

export default VideoPart

마우스오버를 했을 때 생기는 박스들은 조건부 랜더링을 사용해서 해주었다.


CSS 코드 (VideoPart.module.css)

.Video {
    margin-top: 30px;
    background-color: black;
    width: 95%;
    height: 530px;
    margin-bottom: 10px;
}
.Video_info_box {
    width: 95%;
    height: auto;
    /* background-color: antiquewhite; */
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}
.Video_info_box span {
    color: rgb(0, 85, 255);
    font-size: 12px;
}
.Video_info_box p {
    margin: 0;
    font-size: 17px;
    font-weight: 500;
}
.Uploader_info_box {
    width: 50%;
    height: 50px;
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
}
.Uploader_info {
    width: 50%;
    height: 100%;
    display: flex;
    flex-direction: row;
    align-items: center;
}
.Uploader_info div {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    margin-left: 10px;
}
.Uploader_info span {
    font-size: 15px;
    color: black;
}
.Uploader_info p {
    font-size: 12px !important;
}
.Uploader_info_box img {
    height: 100%;
    border-radius: 50%;
}
.Subscribe_button {
    width: 75px;
    height: 38px;
    background-color: rgb(201, 21, 21);
    color: white;
    border-radius: 4px;
    text-align: center;
    line-height: 38px;
    font-size: 14px;
}
.Video_option {
    width: 100%;
    height: 50px;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    margin-top: 15px;
    /* background-color: rgb(0, 0, 0); */
}
.Video_option p {
    font-size: 14px;
    color: grey;
    font-weight: 400;
}
.Box_in_option {
    width: 450px;
    height: 100%;
    /* background-color: beige; */
}
.OptionBox_container {
    width: 100%;
    height: 100%;
    /* background-color: aquamarine; */
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-evenly;
}

.OptionBox_container div {
    display: flex;
    align-items: center;
    justify-content: center;
}
.OptionBox_container span {
    margin-left: 5px !important;
    color: black !important;
    font-size: 14px !important;
}

.Line_under_option {
    width: 100%;
    height: 2px;
    background-color: rgb(226, 226, 226);
    border: none;
}
.Video_explanation_box {
    width: 100%;
    height: 60px;
    /* background-color: aqua; */
}
.Like_popup_box, .Unlike_popup_box, .Share_popup_box, .Download_popup_box {
    display: inline-block;
    position: relative;
    width: auto;
    height: 35px;
    font-size: 12px;
    background-color: grey;
    line-height: 35px;
    padding-left: 5px;
    padding-right: 5px;
    opacity: 0.9;
    color: white;
}
.Like_popup_box {
    left: 490px;
    bottom: 10px;
}
.Unlike_popup_box {
    left: 560px;
    bottom: 10px;
}
.Share_popup_box {
    left: 720px;
    bottom: 10px;
}
.Download_popup_box {
    left: 800px;
    bottom: 10px;
}

현재까지의 전체 화면

완전 유튜브다!!

만든 부분 - 2022 / 09 / 16


영상의 제목 아래에 있는 설명란과 나의 댓글 부분을 만들었다. 사진에서 볼 수 있는 설명란 부분의 '더보기'를 누르면 가려진 부분을 더 볼 수 있도록 만들었다.

이런 식으로 만들었다.


NextJS 코드 ( VideoPart.js의 한 부분)

				<div className={styles.More_info_box}>
                    <div>{commenter}</div>
                    <span onClick={() => {setIsShowMore(!isShowMore)}}>
                        {(comment.length > textLimit.current) && 
                            (isShowMore ? '간략히' : '더보기')}
                    </span>
                </div>
                <hr style={{top: "0"}} className={styles.Line_under_option} />
                <div className={styles.Comment_box}>
                    <div className={styles.Comment_sort_box}>
                        <span className={styles.Comment_number}>댓글 1</span>
                        <div>
                            <MdSort size={30}/>
                            <span className={styles.Comment_sort}>정렬 기준</span>
                        </div>
                    </div>
                    <div className={styles.Comment_input_part}>
                        <img src='https://yt3.ggpht.com/ytc/AMLnZu9Jzp859A5IesAX3WqVFY0ocYhG3_oFkYuLlNlH1KPJhA=s88-c-k-c0x00ffffff-no-rj-mo'/>
                        <div className={styles.Comment_input_box}>
                            <input placeholder='댓글 추가...'/>
                            <div>
                                <div id={styles.Comment_btn1} className={styles.Comment_buttons}>취소</div>
                                <div id={styles.Comment_btn2} className={styles.Comment_buttons}>댓글</div>
                            </div>
                        </div>

                    </div>
                </div>

CSS 코드 (VideoPart.module.css의 한 부분)

.More_info_box {
    position: relative;
    top: 10px;
    width: 65%;
    height: auto;
    margin-left: 6%;
    margin-bottom: 10px;
    /* background-color: beige; */
}
.More_info_box div {
    font-size: 14px;
}
.More_info_box span {
    margin-top: 20px !important;
    color: grey;
    cursor: pointer;
}
.Comment_box {
    width: 100%;
}
.Comment_sort_box {
    width: 200px;
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
}
.Comment_sort_box div {
    display: flex;
    flex-direction: row;
    align-items: center;  
    justify-content: space-between;  
}
.Comment_sort {
    color: black !important;
    font-size: 14px !important;
}
.Comment_number {
    font-size: 16px !important;
    color: black !important;
}
.Comment_input_part {
    width: 100%;
    display: flex;
    flex-direction: row;
    align-items: center;
    /* background-color: aquamarine; */
}
.Comment_input_part img {
    width: 40px;
    height: 40px;
    border-radius: 100px;
    margin-bottom: 20px;
    margin-right: 10px;
}
.Comment_input_box {
    width: 100%;
}
.Comment_input_box div {
    float: right;
    display: flex;
    flex-direction: row;
}
.Comment_input_box input {
    width: 100%;
    height: 35px;
    background-color: transparent;
    border: none;
    border-bottom: 1px solid black;
}
.Comment_buttons {
    width: 72px;
    height: 37px;
    line-height: 37px;
    margin: 7px;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 3px;
    color: #909090;
    font-size: 13px;
}
#Comment_btn1 {
    background-color: rgb(246, 246, 246);
    color: #787878;
}
#Comment_btn2 {
    background-color: rgb(225, 225, 225);
}

현재까지의 전체화면


설명란의 글이 더러운 것 빼고는 완전 유튜브다!

마무리

영상 부분의 유튜브 클론코딩을 해보았는데, 이렇게 해보고 느낀점은 클론코딩을 할 때 작은 기능이라도 작업하는 데에는 시간이 걸린다는 것을 느꼈다. 다음은 댓글 부분을 클론코딩할 것이다.

profile
서커스형 개발자

0개의 댓글