[JavaScript 30 Days Challenge] Custom Video Player

yuza🍊·2021년 12월 20일
0
post-thumbnail

Day11-Custom Video Player

CODE

구현 사항: shift key로 여러 항목을 동시에 체크할 수 있는 체크리스트 구현

1) 각 변수에 컨트롤해야 하는 모든 요소들을 하나하나 할당해 둠

const player = document.querySelector(".player");
const video = player.querySelector(".viewer");
const progress = player.querySelector(".progress");
const progressBar = player.querySelector(".progress__filled");
const toggle = player.querySelector(".toggle");
const skipButtons = player.querySelectorAll("[data-skip]");
const ranges = player.querySelectorAll(".player__slider");

2) togglePlay() 함수를 video와 toggle(토글할 수 있는 play 버튼)에 click 이벤트 발생 시 실행되도록 할당

function togglePlay() {
  const method = video.paused ? "play" : "pause";
  video[method]();
}

video.addEventListener("click", togglePlay);
toggle.addEventListener("click", togglePlay);
  • video.paused는 영상이 재생되고 있으면 false, 멈췄을 때 true가 됨

  • video.play()는 영상을 재생시키며, video.pause()는 영상을 멈추므로, video.paused의 상태에 따라 재생되고 있지 않으면 video.play()를, 멈춰있으면 video.pause()를 하여 영상을 끄고 켜도록 함

3) updateButton() 함수를 video가 play, pause 될 때마다 싱행되도록 함

function updateButton() {
  const icon = this.paused ? "►" : "❚ ❚";
  toggle.textContent = icon;
}

video.addEventListener("play", updateButton);
video.addEventListener("pause", updateButton);
  • 여기서 this는 video이므로, 영상이 멈춰 있으면 해당 함수를 통해 재생 아이콘을 "►"로 업데이트 하며, 영상이 재생 중이면 "❚ ❚"로 업데이트 함

  • Node.textContent를 통해 텍스트 노드를 추가

4) skipButtons 각각에 click 이벤트 발생 시 skip() 함수 실행되도록 할당

<button data-skip="-10" class="player__button">« 10s</button>
<button data-skip="25" class="player__button">25s »</button>

function skip() {
  video.currentTime += parseFloat(this.dataset.skip);
}

skipButtons.forEach((button) => button.addEventListener("click", skip));
  • 영상의 현재 재생 시간에 버튼의 dataset.skip의 값을 더해서 재할당

  • 이때, parseFloat() 함수를 사용하여 문자열을 숫자로 변환

  • 10초 전으로 돌아가는 버튼의 dataset.skip은 -10, 25초 뒤로 넘어가는 버튼의 dataset.skip은 25

5) ranges에 change(input의 값이 변화될 때), mousemove(마우스로 범위 조절할 때) 이벤트 발생 시 handleRangeUpdate() 함수 실행되도록 할당

<input
  type="range"
  name="volume"
  class="player__slider"
  min="0"
  max="1"
  step="0.05"
  value="1"
/>
<input
  type="range"
  name="playbackRate"
  class="player__slider"
  min="0.5"
  max="2"
  step="0.1"
  value="1"
/>

function handleRangeUpdate() {
  video[this.name] = this.value;
}

ranges.forEach((range) => range.addEventListener("change", handleRangeUpdate));
ranges.forEach((range) =>
  range.addEventListener("mousemove", handleRangeUpdate)
);
  • 여기서 this는 range이므로 this.name은 각각 volume과 playbackRate

  • 따라서 range에 변화가 생기거나 마우스로 range를 조절할 때, 해당 input value로 영상의 volume, playbackRate를 설정하도록 함

6) video에 timeupdate (비디오의 재생 위치가 변경 될 때-빨리 감기, 뒤로 감기 등) 이벤트 발생 시 handleProgress() 함수 실행되도록 할당

function handleProgress() {
  const percent = (video.currentTime / video.duration) * 100;
  progressBar.style.flexBasis = `${percent}%`;
}

video.addEventListener("timeupdate", handleProgress);
  • 재생바를 이동시키거나 뒤로 넘어가기/앞으로 뛰어넘기 등의 이벤트 발생할 때 실행됨

  • 따라서 range에 변화가 생기거나 마우스로 range를 조절할 때, 해당 input value로 영상의 volume, playbackRate를 설정하도록 함

7) video에 timeupdate (비디오의 재생 위치가 변경 될 때-재생, 빨리 감기, 뒤로 감기 등) 이벤트 발생 시 handleProgress() 함수 실행되도록 할당

function handleProgress() {
  const percent = (video.currentTime / video.duration) * 100;
  progressBar.style.flexBasis = `${percent}%`;
}

video.addEventListener("timeupdate", handleProgress);

  • 재생바의 '채워지는 부분'이 이동되는 모든 상황(뒤로 넘어가기/앞으로 뛰어넘기 등 포함)의 이벤트 발생할 때 실행됨

  • video.currentTime은 현재 재생 시간, video.duration은 비디오의 전체 시간이므로 percent는 영상이 총 몇 퍼센트가 재생되었는지를 나타냄

  • 재생바의 '채워지는 부분'인 progressBar의 style에 접근하여 플렉스 아이템의 크기를 퍼센테이지로 설정

8) 재생바(전체)에 click, mousedown을 동반한 mousemove 이벤트 발생 시 scrub() 함수 실행

function scrub(e) {
  const scrubTime = (e.offsetX / progress.offsetWidth) * video.duration;
  video.currentTime = scrubTime;
}

let mousedown = false;
progress.addEventListener("click", scrub);
progress.addEventListener("mousemove", (e) => mousedown && scrub(e));
progress.addEventListener("mousedown", () => (mousedown = true));
progress.addEventListener("mouseup", () => (mousedown = false));
  • offsetX는 좌표를 출력하도록 하는 이벤트가 걸려있는 DOM node를 기준으로 x좌표를 표시하고 (참고) 일반적으로 엘리먼트의 전체 크기를 알 수 있는 offsetWidth를 사용하여, 전체 재생바를 기준으로 현재 마우스의 x좌표를 전체 재생바의 너비로 나눈 뒤 video의 전체 시간을 곱하여 현재 재생 시간을 구함 -> 비디오의 currentTime에 할당

  • 재생바를 클릭하거나, mousedown 상태로 재생바 위를 마우스를 움직일 때 scrub() 함수를 실행해야 하므로, mousedown 이벤트 발생 시 mousedown 변수에 true를 할당하고, mouseup 이벤트 발생시 false를 할당 -> mousemove 이벤트 발생 시 mousedown 변수의 t/f 여부를 scrub() 함수 실행의 조건으로 걸어 마우스를 클릭한 채로 재생바 이동해야 scrub() 함수가 실행되도록 함

내가 수정한 부분

function togglePlay() {
  video.paused ? video.play() : video.pause();
}
  • togglePlay() 함수 보다 간단하게 수정
profile
say hi to the world

0개의 댓글