Video Control(JS, scss, pug)

김종민·2022년 11월 8일
0

Youtube

목록 보기
19/23

들어가기
JS를 이용해서, watch.pug에 비디오 controler를 만들어본다.
play, mute, fullScreen등등.
JS를 다시 복습하고 익혀 보도록 한다.


1. src/views/watch.pug


---------부분은 참고만 하라고 남겨둠.

extends base.pug

----------------------------------------------------
//- block head 
//-     title Watch | JmTube
-------------------------------------------------------
block content
    div#videoContainer
        video(src="/" + video.fileUrl)
        ///video 태그를 이용해 비디오파일을 불러준다.
        
        div#videoControls.videoControls
        ///#은 JS에서 사용하기위한 태그
        ///.은 scss에서 사용하기 위한 태그
        ///#은 scss에서도 사용가능한 태그(중복사용 가능)
            div.videoControls__play
                span#play.videoControls__playBtn
                    i.fas.fa-play
                    ///#은 JS에서 사용, .은 scss에서 사용
                    ///i.fas.fa-play은 base.pug에서 
                    ///import한 awesome icon을 사용하는것.
                div.videoControls__time
                    span#currenTime 00:00
                    span  / 
                    span#totalTime 00:00
                    
            input(type="range",step="1", value="0", min="0")#timeline.videoControls__timeline
            ///type이 rangef로 비디오가 얼마나 play됬는지 보여주는 바임. #이랑, .으로 js및 scss와 연결이 된다.
            
            div.videoControls__volume
                input(type="range",step="0.1", value=0.5, min="0", max="1")#volume
                span#mute
                    i.fas.fa-volume-up
            div
                span#fullScreen
                    i.fas.fa-expand
 --------------------------------------------------
    //-
        div
            p=video.description
            small=video.createdAt
        div
            small Uploaded by 
                a(href=`/users/${video.owner._id}`)=video.owner.name
        if String(video.owner._id) === String(loggedInUser._id)
            a(href=`${video.id}/edit`) Edit Video →
            br
            a(href=`${video.id}/delete`) Delete Video →
 ----------------------------------------------------------
 
block scripts
    script(src="/static/js/videoPlayer.js") 
    ///this pug 파일에 적용될 js파일을 불러줌.
--------------------------------------------------------
    
    //- div
    //-     h1=video.title
    //-     p=video.description
    //-     small=video.createdAt

    //- div 
    //-     small=video.owner.email 
    //-     br
    //-     small Uploaded by 
    //-             a(href=`/users/${video.owner._id}`) #{video.owner.username}
    //- each hashtag in video.hashtags 
    //-         li=hashtag
    //- h3 #{video.views} #{video.views === 1 ? "view" : "views"}
    //- if String(video.owner._id) === String(loggedInUser._id)
    //-     a(href=`${video.id}/edit`) Edit Video →
    //-     br
    //-     a(href=`${video.id}/delete`) Delete Video →
 --------------------------------------------------------

2. src/client/js/videoPlayer.js

const video = document.querySelector('video')
const playBtn = document.getElementById('play')
const playBtnIcon = playBtn.querySelector('i')
const muteBtn = document.getElementById('mute')
const muteBtnIcon = muteBtn.querySelector('i')
const volumeRange = document.getElementById('volume')
const currenTime = document.getElementById('currenTime')
const totalTime = document.getElementById('totalTime')
const timeline = document.getElementById('timeline')
const fullScreenBtn = document.getElementById('fullScreen')
const fullScreenIcon = fullScreenBtn.querySelector('i')
const videoContainer = document.getElementById('videoContainer')
const videoControls = document.getElementById('videoControls')
///pug 파일에서 #태그가 붙은 부분은 connect해줌.
/// video태그는 querySelector로 연결됨을 확인.
///그리고 playBtnIcon같은 경우는 #play아래 부분의 i.fas-fa-play
///부분은 connect하는것, 위의 태그인,
///playBtn.querySelector('i')로 connect한다.
///muteBtnIcon, fullScreenIcon도 마찬가지 방법임.


let controlsTimeout = null
let controlsMovementTimeout = null
let volumeValue = 0.5
///위의 3개는 global로 설정해서, 각각의 함수들이 getter, setter
///할 수 있게 함.
/// getter, setter은 값을 받고, 수정가능하게 하는거.

video.volume = volumeValue
///video 볼륨은 global로 설정한 volume으로 설정해 줌.

const handlePlayClick = (e) => {
  if (video.paused) {
    video.play()
  } else {
    video.pause()
  }
  //playBtn.innerText = video.paused ? "Play" : "Pause";
  playBtnIcon.classList = video.paused ? 'fas fa-play' : 'fas fa-pause'
}
///playBtn을 click했을떄, 작동되는 함수.
///video가 pause인지 play인지 여부에 따라, playBtnIcon의
///class가 (awesomeIcon)가 바뀌게 설정해 놓는다.

const handleMuteClick = (e) => {
  if (video.muted) {
    video.muted = false
  } else {
    video.muted = true
  }
  //muteBtn.innerText = video.muted ? "Unmute" : "Mute";
  muteBtnIcon.classList = video.muted
    ? 'fas fa-volume-mute'
    : 'fas fa-volume-up'
  volumeRange.value = video.muted ? 0 : volumeValue
}
///muteBtn을 click했을떄, 작동되는 함수.
///mute가 true인지 false인지 여부에 따라, playBtnIcon의
///class가 (awesomeIcon)가 바뀌게 설정해 놓는다.
//. volumeRange 값 역시, 연결해 준다.

const handleVolumeChange = (event) => {
  const {
    target: { value },
  } = event
  if (video.muted) {
    video.muted = false
    muteBtn.innerText = 'Mute'
  }
  volumeValue = value
  video.volume = value
}
///const volumeRange = document.getElementById('volume')
///이거를 connect해서, 
///volumeRange.addEventListener('input', handleVolumeChange) 
///connect함.
/// event발생시 value값을 target으로 얻는다.
///그 값을 video.volume에 넣어주고,
///volumeValue 값에 넣어준다.
///volumeValue는 위에 global로 설정해 놓았음.
///video.volume은 video player의 볼륨을 말한다.

const formatTime = (seconds) =>
  //new Date(seconds * 1000).toISOString().substr(11, 8);
  new Date(seconds * 1000).toISOString().substr(14, 5)
///요것은 video의 total시간 및 currentTime의 값은
/// 00:00:00의 형식으로 포맷해주는 함수.
/// 2015-12-20 14:34:23 ... 으로 나오는 new Date 값을
/// 14번쨰부터 5개를 뽑아낸다고 생각하면 된다.

const handleLoadedMetadata = () => {
  totalTime.innerText = formatTime(Math.floor(video.duration))
  timeline.max = Math.floor(video.duration)
}
///video.addEventListener('loadeddata', handleLoadedMetadata)
///video 파일의 전체 상영시간을 load해줌
///totalTime의 innerText를 video.duration을 불러줌으로
///전체 상영시간으로 찍힘.
///그리고 watch.pug의 timeline.max값 역시,
///video의 전체시간으로 찍힘.
/// formatTime은 함수로써, 00:00:00으로 표시되게 하는 함수.
///밑에서 만들어 놓았음.
///Math.floor은 소수점 아래를 버리게 해줌.

const handleTimeUpdate = () => {
  currenTime.innerText = formatTime(Math.floor(video.currentTime))
  timeline.value = Math.floor(video.currentTime)
}
///현재 몇분 상영되었는가를 나타내주는 함수.
///video.addEventListener('timeupdate', handleTimeUpdate)
///video 태그에 addEvent해준다는 것을 명심할것.

const handleTimelineChange = (event) => {
  const {
    target: { value },
  } = event
  video.currentTime = value
}
///상영중인 video를 플래이var에서 이리저리 옮기는것


const handleFullscreen = () => {
  const fullscreen = document.fullscreenElement
  if (fullscreen) {
    document.exitFullscreen()
    //  fullScreenBtn.innerText = "Enter Full Screen";
    fullScreenIcon.classList = 'fas fa-expand'
  } else {
    videoContainer.requestFullscreen()
    // fullScreenBtn.innerText = "Exit Full Screen";
    fullScreenIcon.classList = 'fas fa-compress'
  }
}
///fullScreen 버튼을 클릭함으로써 fullScreen을 true/false
///하는 함수.
/// const fullscreen은 화면이 현재 fullscreen인지 아닌지
///펀별하는것.
///fullscreen여부에 따라 아이콘도 바꾸어준다.

const hideControls = () => videoControls.classList.remove('showing')
///video화면에 마우스가 있는지 없는지 여부에 따라
///watch.pug파일에 showing이라는 class 를
///제거해 주는 함수.
///비디오에 마우스를 가져다대면, controls보여지는 것
/// &.showing이면 opacity:1, 아닐떄, opacity:0으로
/// scss에서 설정해 준다.

const handleMouseMove = () => {
  if (controlsTimeout) {
    clearTimeout(controlsTimeout)
    controlsTimeout = null
  }
  if (controlsMovementTimeout) {
    clearTimeout(controlsMovementTimeout)
    controlsMovementTimeout = null
  }
  videoControls.classList.add('showing')
  controlsMovementTimeout = setTimeout(hideControls, 3000)
}
///맨 위에 global로 
///let controlsTimeout = null
///let controlsMovementTimeout = null
///설정해 놓았음.
///마우스가 video에 있는지 없는지에 따라 showing이라는 class를
///보여주고 숨기는것. 
///그냥 hover로 설정하면 바로 끝남 ㅠㅠ

const handleMouseLeave = () => {
  controlsTimeout = setTimeout(hideControls, 3000)
}
///mouse가 video화면에서 벗어났을때, 3초후에 hideControls
///함수가 실행되게 한다.


playBtn.addEventListener('click', handlePlayClick)
muteBtn.addEventListener('click', handleMuteClick)
volumeRange.addEventListener('input', handleVolumeChange)
//video.addEventListener("loadedmetadata", handleLoadedMetadata);
video.addEventListener('loadeddata', handleLoadedMetadata)
video.addEventListener('timeupdate', handleTimeUpdate)
videoContainer.addEventListener('mousemove', handleMouseMove)
videoContainer.addEventListener('mouseleave', handleMouseLeave)
timeline.addEventListener('input', handleTimelineChange)
fullScreenBtn.addEventListener('click', handleFullscreen)
//video.addEventListener("mousemove", handleMouseMove);
//video.addEventListener("mouseleave", handleMouseLeave);

///맨위에서 pug파일과 연결한 단어들에 addEventListener를
///붙여서 동작을 넣는다. 
/// 버튼같은 경우는 'click'을 넣고 볼륨바,videoTimeLine같은
/// 바는 'input'으로 넣는다.
/// lodeddata는 video관련 data를 불러들이는 거고,
/// timeupdate는 실시간 video time을 catch하는 것임.
/// mousemove와 mouseleave는 video화면 위에 마우스가 있는지,
/// 없는지롤 catch하는 것이다.
/// ''뒷부분은 input이나, click를 했을떄, 작동되는 함수이다.

3. src/client/scss/components/video-play.scss

#videoContainer { 
///JS에 연결할떄뿐만 아니라, scss에서도 #으로 connect가 가능하다.
  width: 100%;
  position: relative; ///control var를 넣기위해 relative로 설정
  video {
    width: 100%;
  }
  .videoControls {
    opacity: 0;
    transition: opacity 0.5s ease-in-out;
    &.showing {
      opacity: 1;
    }
    ///opacity를 0으로 해서 안보이게 해놨다가,
    ///mouses가 들어오면, showing class가 생겨서
    ///opacity가 1로 바뀌어서 보이게 된다.
    
    align-items: center;
    border-radius: 10px;
    position: absolute; ///비디오 화면에 넣기 위해서.
    bottom: 10px;
    width: 95%;
    left: 0;
    right: 0;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 1fr 4fr 1fr auto; ///가로 크기조절
    gap: 10px;
    justify-content: space-between;
    background-color: #0f1117;
    padding: 10px;
    left: 0;
    box-sizing: border-box;
    .videoControls__play {
      display: flex;
      align-items: center;
      justify-content: space-around;
      .videoControls__playBtn {
        margin: 0px 15px;
      }
      .videoControls__time {
        font-size: 12px;
      }
    }
    .videoControls__volume {
      display: flex;
      align-items: center;
      span {
        margin-left: 10px;
        i {
          font-size: 20px;
        }
      }
    }
  }
}

비디오안에 비디오 콘트롤러를 만들어 보는 코딩.
JS와 pug파일을 연결하고, pug파일과 scss를 연결하는
부분은 다시한번 잘 봐둔다.

profile
코딩하는초딩쌤

2개의 댓글

comment-user-thumbnail
2023년 4월 26일

@basket random
비디오에서 비디오 컨트롤러를 생성하기 위해 코딩하는 방법에 대한 자습서에 감사드립니다.

답글 달기
comment-user-thumbnail
2024년 7월 26일

You ought to know that there are many attractive and stunning people in Sonam, and if you're looking for a companion to spend moments with a few of them, the Club Hotel is the place to be. We have Escorts in Moti Nagar girl who can provide you with complete pleasure, and our escorts will help you have an enjoyable and memorable time with them based on your preferences.

답글 달기