Day 11 - Custom HTML5 Video Player

2020. 11. 13. 14:07JavaScript30-Challenge

Demo

Day 11 - Custom HTML5 Video Player

HTML 코드

<body>
  <div class="player">
    <video class="player__video viewer" src="그랜드체이스-희망.mp4"></video>

    <div class="player__controls">
      <div class="progress">
       <div class="progress__filled"></div>
      </div>
      <button class="player__button toggle" title="Toggle Play">►</button>
      <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">
      <button data-skip="-10" class="player__button">« 10s</button>
      <button data-skip="10" class="player__button">10s »</button>
    </div>
  </div>
</body>

CSS 코드

너무 많아서 생략하겠음
깃헙코드에 올려두었음!

JavaScript 코드

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");

let mousedown = false;

function scrub(e) {
  // offset은 상대적 위치를 냅니다.
  // e.offsetX는 이벤트가 일어날 곳을 기준으로 x좌표를 매깁니다. 여기서는 progress가 기준이 됩니다.
  const scrubTime = (e.offsetX / progress.offsetWidth) * video.duration;
  video.currentTime = scrubTime;
}

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

function handleRangeUpdate() {
  // video속성을 range의 name값을 가져와 value값으로 설정합니다.
  // 전에 dataset으로 지정값을 가져오는 것과 비슷한 유형입니다.
  video[this.name] = this.value;
}

function skip() {
  // 여기서 중요한 것은 dataset.skip은 문자열이기 때문에 그냥 집어넣으면 타입에러가 납니다. -> 정수형으로 변경!
  video.currentTime += parseInt(this.dataset.skip);
}

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

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

  /* if(video.paused) {
    video.play();
  } else {
    video.pause();
  } */
}

function init() {
  video.addEventListener("click", togglePlay);
  toggle.addEventListener("click", togglePlay);
  video.addEventListener("play", updateButton);
  video.addEventListener("pause", updateButton);
  video.addEventListener("timeupdate", handleProgress);
  skipButtons.forEach((button) => button.addEventListener("click", skip));
  ranges.forEach((range) =>
    range.addEventListener("change", handleRangeUpdate)
  );
  ranges.forEach((range) =>
    range.addEventListener("mousemove", handleRangeUpdate)
  );
  progress.addEventListener("click", scrub);
  progress.addEventListener("mousemove", (e) => mousedown && scrub(e));
  progress.addEventListener("mousedown", () => (mousedown = true));
  progress.addEventListener("mouseup", () => (mousedown = false));
}

init();

전에 유튜브 클론 코딩을 하면서 비디오 커스텀을 해본 적이 있다.

한 번 해본 경험이 있어서 지루할 것 같았는데 내가 전에 만들었던 자바스크립트 코드보다 훨씬 간결하고 이렇게 쉽게 구현되는 것인지 알고서 놀랐다.

같은 방법인데 다르게 느껴져 허무한 느낌이 든다.

나와 다른 것들과 훨씬 더 좋다고 느낀 방법을 몇 가지 보자면 속성값을 []을 통해 더 짧은 코드로 변경할 수 있었다.

또한 dataset을 사용해 값을 변경하는 방법도 있었다.

그리고 init()함수 마지막을 보면 mousemove 이벤트를 주었지만 마우스를 눌러야만 mousedown 불린값이 변경되어 mousemove이벤트가 실행이된다. 이 또한 매우 좋은 방법이라고 생각한다.