Youtube Clone Coding (9. Video Player 만들기)

LeeJaeHoon·2021년 10월 28일
0
post-thumbnail

기본적으로 video를 제어할 수 있는 api가 존재함 → HTMLMediaElement

  1. video play and pause
    • tag, id불러오기
      const video = document.querySelector("video");
      const playBtn = document.getElementById("play");
    • video play/pause 시키기
      • playBtn을 눌렀을때 재생이 되야함 → HTMLMediaElement.paly() 메소드로 가능
        • 재생중일때는 눌렀을때 멈춰야 됨 → HTMLMediaElement.pause() 메소드로 가능

        • HTMLMediaElement.paused 메소드는 현재 video가 재생중 일때는 false 멈춰 있을때는 true를 반환함.

          const handlePlayClick = e => {
            if (video.paused) {
              video.play();
            } else {
              video.pause();
            }
          };
          playBtn.addEventListener("click", handlePlayClick);
    • video가 playBtn innerText바꾸기 → HTMLMediaElement의 play,pause event로 가능
      • video가 play됐을때는 innerText가 pause
      • video가 pause됐을때는 innerText가 play
        const handlePause = () => {
          playBtn.innerText = "play";
        };
        
        const handlePlay = () => {
          playBtn.innerText = "pause";
        };
        video.addEventListener("pause", handlePause);
        video.addEventListener("play", handlePlay);
      • 두번째 방법
        • handlePlayClick함수에서 바로 바꿔주기
          const handlePlayClick = e => {
            if (video.paused) {
              video.play();
            } else {
              video.pause();
            }
            playBtn.innerText = video.paused ? "Play" : "Pause";
          };
  2. video mute/unmute
    • HTMLMediaElement.muted 메소드를 활용
      • 오디오가 음소거되었는지 여부를 결정하는 Bolean. 오디오가 음소거되면 true이고 그렇지 않으면 false
    • 오디오가 음소거가 안됐을 때 (HTMLMediaElement.muted = false) muteBtn을 click
      • 음소거가 돼야함 → HTMLMediaElement.muted = true
      • innerText가 Unmute가 돼야함
      • volum이 0이 돼야함
    • 오디오가 음소거가 됐을 때(HTMLMediaElement.muted = true) muteBtn을 click
      • 음소거가 안돼야함 → HTMLMediaElement.muted = false

      • ineerText가 Mute가 돼야함

      • volum이 0.5가 돼야함

        const volumeRange = document.getElementById("volume");
        const handleMute = e => {
          if (video.muted) {
            video.muted = false;
          } else {
            video.muted = true;
          }
          muteBtn.innerText = video.muted ? "Unmute" : "Mute";
          volumeRange.value = video.muted ? 0 : 0.5;
        };
        
        muteBtn.addEventListener("click", handleMute);
  3. input(type="range")로 value를 바꿀 때 volumn제어
    • input event사용 → input의 value가 바뀔때마다 event발생
      volumeRange.addEventListener("input", handleVolumnChange);
    • 전역변수로 let volumeValue = 0.5(초기 볼륨설정)을 만들고 video.volumn에 volumeValue넣기
      • HTMLMediaElement.volume
        • HTMLMediaElement.volume 속성은 video 볼륨을 설정하는 메소드
      • input의 value가 바뀔때 바뀐 value를 volumeValue에 넣어주고 video.volumn에 volumeValue넣기
        const handleVolumnChange = e => {
          const {
            target: { value },
          } = e;
          volumeValue = value;
          video.volume = volumeValue;
        };
        volumeRange.addEventListener("input", handleVolumnChange);
    • input event로 조정한 volumeValue을 기억 하는법
      • muteBtn을 눌러서 muted가 되고 다시 muteBtn을 눌렀을때 설정해놓은 video.volumn은 volumeValue가 되야함
        const handleMute = e => {
          if (video.muted) {
            video.muted = false;
          } else {
            video.muted = true;
          }
          muteBtn.innerText = video.muted ? "Unmute" : "Mute";
          volumeRange.value = video.muted ? 0 : volumeValue;
        };
    • input event로 input의 value가 0이됐을때 video.muted가 true가 되어야하고 muteBtn.innerText은 Unmute되야함
    • input event로 input의 value가 0이아닐때 video.muted가 false가 되어야하고 muteBtn.innerText은 Mute가되야함
      const handleVolumnChange = e => {
        const {
          target: { value },
        } = e;
        if (parseFloat(value) === 0) {
          video.muted = true;
        } else {
          video.muted = false;
        }
        muteBtn.innerText = video.muted ? "Unmute" : "Mute";
        volumeValue = value;
        video.volume = volumeValue;
      };
  4. video 시간 구하기
    • HTMLMediaElement.duration으로 video의 총시간을 구할 수 있다.
      • HTMLMediaElement: loadedmetadata event는 video가 load될때 발생되는 event이다
      • video가 load되고나서 video.duration을 구할 수 있다.
      • video.durating은 소숫점까지 나타내므로 Math.floor로 내림 해준다
        const handleLoadedMetadata = () => {
          totalTime.innerText = Math.floor(video.duration);
        };
        video.addEventListener("loadedmetadata", handleLoadedMetadata);
    • HTMLMediaElement.currentTime으로 video의 현재 재생시간을 알 수 있다.
      • HTMLMediaElement: timeupdate event는 video.currentTime이 update되면발생하는 event이다.
      • video.currentTime은 소숫점까지 나타내므로 Math.floor로 내림 해준다
        const handleTimeUpdate = () => {
          currentTime.innerText = Math.floor(video.currentTime);
        };
        video.addEventListener("timeupdate", handleTimeUpdate);
    • currentTime,totalTime 00:00:00형식으로 나타내 주기
      const formatTime = seconds =>
        new Date(seconds * 1000).toISOString().substr(11, 8);
      • new Date()의 인자로 ms를 넣어주면 1970년 1월 1일 이후에 인자로 넣어준 ms후를 리턴한다.
        • 인자로 1000을 넣은겨우
          • Thu Jan 01 1970 09:00:01 GMT+0900 (한국 표준시)
        • 인자로 우리가 구한시간 * 1000을 해주면 초단위로 바뀌어 나타내준다.
      • new Date.toISOString()을 쓰면 리턴값이 YYYY-MM-DDTHH:mm:ss.sssZ 형식으로 바뀐다.
        • ex) '1970-01-01T00:00:01.000Z'
      • String.prototype.substr()은 문자열에서 특정 위치에서 시작하여 특정 문자 수 만큼의 문자들을 반환한다.
        • 인자로 substr(11,8)을 넣어주면 해당 문자열 12번째부터 19번째문자열까지 반환한다는 뜻.
        • ex) '00:00:01'
      • 위의 formatTime 함수에 인자로 currentTime,totalTime을 주면 00:00:00형식으로 나타내 줄 수 있다.
        const formatTime = seconds =>
          new Date(seconds * 1000).toISOString().substr(11, 8);
        
        const handleLoadedMetadata = () => {
          totalTime.innerText = formatTime(Math.floor(video.duration));
        };
        
        const handleTimeUpdate = () => {
          currentTime.innerText = formatTime(Math.floor(video.currentTime));
        };
    • Bug Fix
      • JS에서 eventlistener을 추가하기 전에 video가 전부 로딩이 되어서, handleLoadedMetadata() 가 아예 불러지지 않을 수 있다
        • 밑의 코드를 사용해 해결할 수 있다.
          • video.readyState가 4라는 뜻은 video가 충분히 불러와져서 사용이 가능하다는 뜻

            if (video.readyState == 4) {
              handleLoadedMetadata();
            }
  5. video timeline
    • pug에 id가 timeline인 input만들기
      • video마다 총시간이 다르기 때문에 max는 설정 안함.

        input(type="range", value=0, step="1", min="0")#timeline
    • HTMLMediaElement: loadedmetadata event와 video.duration을 이용해 timeline의 max값 구하기
      const handleLoadedMetadata = () => {
        totalTime.innerText = formatTime(Math.floor(video.duration));
        timeline.max = Math.floor(video.duration);
      };
      video.addEventListener("loadedmetadata", handleLoadedMetadata);
    • HTMLMediaElement: timeupdate event는 video.currentTime이 update되면발생하는 event이다.
      • timeupdate event를 이용해 video.currentTime에 맞춰서 input.value변화시키기
        const handleTimeUpdate = () => {
          currentTime.innerText = formatTime(Math.floor(video.currentTime));
          timeline.value = Math.floor(video.currentTime);
        };
        video.addEventListener("timeupdate", handleTimeUpdate);
    • input의 input event와 video.currentTime를 이용해서 사용자가 timeline의 value를 변경했을 때 video.currentTime 변경 시키기
      const handleTimelineChange = e => {
        const {
          target: { value },
        } = e;
        video.currentTime = value;
      };
      timeline.addEventListener("input", handleTimelineChange);
  6. video fullScreen으로 만들기
    • document.fullscreenElement
      • 현재 전체 화면 모드로 표시되는 요소를 반환하거나 전체 화면 모드가 현재 사용 중이 아니면 null을 반환한다.
    • Element.requestFullscreen() 메소드로 전체화면으로 만들 수 있다.
      • Element에 video를 넣으면 video만 커지고 내가만든 video controls은 전체 화면이 안되어 pug에서 video와 video controls 둘다 감싸주는 div#videoContainer을 만들어 만든 div를 Element자리에 써주어야 한다.
    • Document.exitFullscreen() 메소드로 전체화면에서 이전 상태로 복원 할 수 있다.
    • button을 click했을때 현재 document.fullscreenElement이 null이면 Element.requestFullscreen()을 해주고 document.fullscreenElement이 true이면 Document.exitFullscreen() 을 한다.
      const handleFullScreen = () => {
        const fullScreen = document.fullscreenElement;
        if (fullScreen) {
          document.exitFullscreen();
          fullScreenBtn.innerText = "Enter Full Screen";
        } else {
          videoContainer.requestFullscreen();
          fullScreenBtn.innerText = "Exit Full Screen";
        }
      };
      fullScreenBtn.addEventListener("click", handleFullScreen);
  7. video controls 마우스 이벤트
    • video에 mouse가 들어갔을때 controls 보여주기
      • video에 mousemove event를 주고 video에서 마우스가 이동했을때 showing class추가하면됨.
        const handleMouseMove = e => {
          videoControls.classList.add("showing");
        };
        video.addEventListener("mousemove", handleMouseMove);
      • video에서 마우스가 빠져 나갔을때 mouseleave event를 이용해서 showing class삭제해야함.
        • video에서 마우스가 빠져 나갔을 때 바로 showing class를 삭제하는게 아니라 조금 텀을 주고 삭제해야 더 부드럽게 보임.

          const handleMouseLeave = () => {
            setTimeout(() => {
              videoControls.classList.remove("showing");
            }, 3000);
          };
          video.addEventListener("mouseleave", handleMouseLeave);
      • video에서 마우스가 빠져나고 3초가 안지난 상태에서 다시 video에 마우스가 들어왔을때 showing class가 지워지는 버그를 고쳐야함.
        • setTimeout함수는 id를 리턴하는데 clearTimeout()의 인자로 id를 주면 해당 setTimeout함수를 지울 수 있음.
        • video에 마우스가 이동할때 clearTineout(id)를 해주면됨.
          let controlsTimeout = null;
          const handleMouseMove = e => {
            if (controlsTimeout) {
              clearTimeout(controlsTimeout);
              controlsTimeout = null;
            }
            videoControls.classList.add("showing");
          };
          
          const handleMouseLeave = () => {
            controlsTimeout = setTimeout(() => {
              videoControls.classList.remove("showing");
            }, 3000);
          };
          video.addEventListener("mousemove", handleMouseMove);
          video.addEventListener("mouseleave", handleMouseLeave);
      • video에서 마우스를 3초동안 가만히 나둘때 showing class가 사라지게 만들어야함
        • handleMouseMove함수에서 setTImout함수를 만들어 3초후에 showing class 지우기.
        • setTimeout함수에 id를 줘서 id가 있을때 clearTimeout해주기
          • 마우스가 움직이는 동안에는 setTimeout함수가 실행되면 안되므로 clearTimeout을 해주어야한다.
          • 마우스가 멈췄을때는 mousemove event가 발생하지 않으므로 clearTimeout이 실행이 안되어 setTimeout함수가 호출된다.
            let controlsMovementTimeout = null;
            const hideContorls = () => videoControls.classList.remove("showing");
            
            const handleMouseMove = e => {
              if (controlsTimeout) {
                clearTimeout(controlsTimeout);
                controlsTimeout = null;
              }
              if (controlsMovementTimeout) {
                clearTimeout(controlsMovementTimeout);
                controlsMovementTimeout = null;
              }
              videoControls.classList.add("showing");
              controlsMovementTimeout = setTimeout(hideContorls, 3000);
            };
            video.addEventListener("mousemove", handleMouseMove);

0개의 댓글