11. Custom Video Player

yoxxin·2022년 2월 11일
3

javascript30

목록 보기
9/9

1. 목표

<video>를 커스텀해보자

2. 정리

원래 <video controls> 와 같이
controls attribute를 주면 위와 같이 브라우저 기본 비디오 UI를 제공해준다.
이 UI를 입맛대로 커스텀하려면, 하나부터 열까지 다 뜯어고쳐야한다.

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>HTML Video Player</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div class="player">
      <video class="player__video viewer" src="652333414.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="25" class="player__button">25s »</button>
      </div>
    </div>

    <script src="scripts.js"></script>
  </body>
</html>

JS

const video = document.querySelector('.viewer');
const progress = document.querySelector('.progress');
const progressBar = document.querySelector('.progress__filled');
const toggle = document.querySelector('.toggle');
const volume = document.querySelectorAll('.player__slider')[0];
const playbackRate = document.querySelectorAll('.player__slider')[1];
const skipButtons = document.querySelectorAll('[data-skip]');

/* function */
function playVideo() {
  const method = video.paused ? 'play' : 'pause';
  video[method]();
}

// toggle icon 변경
function updateButton() {
  const icon = this.paused ? '►' : '❚ ❚';
  toggle.innerHTML = icon;
}

function updateVolume(e) {
  video.volume = this.value;
}

function updatePlaybackRate() {
  video.playbackRate = this.value;
}

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

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

function scrubVideo(e) {
  video.currentTime =
    video.duration * (e.offsetX / progress.getBoundingClientRect().width);
}

/*  EventListener */
video.addEventListener('click', playVideo);
video.addEventListener('play', updateButton);
video.addEventListener('pause', updateButton);
video.addEventListener('timeupdate', handleProgressBar);
toggle.addEventListener('click', playVideo);
volume.addEventListener('mousemove', updateVolume);
playbackRate.addEventListener('mousemove', updatePlaybackRate);
skipButtons.forEach((skipButton) => {
  skipButton.addEventListener('click', handleSkip);
});
let mousedown;
progress.addEventListener('click', scrubVideo);
progress.addEventListener('mousemove', (e) => mousedown && scrubVideo(e));
progress.addEventListener('mousedown', () => (mousedown = true));
progress.addEventListener('mouseup', () => (mousedown = false));

Scrub video

progress bar를 클릭중인 마우스로 잡고 끌어 당기는 행위

function scrubVideo(e) {
  video.currentTime =
    video.duration * (e.offsetX / progress.getBoundingClientRect().width);
}
let mousedown;
progress.addEventListener('click', scrubVideo);
progress.addEventListener('mousemove', (e) => mousedown && scrubVideo(e));
progress.addEventListener('mousedown', () => (mousedown = true));
progress.addEventListener('mouseup', () => (mousedown = false));

mousedown 전역변수를 이용해서,
mousedown, mouseup, mousemove event handler를 등록해서 적용한다.
mousedown이 true일때만 scrubVideo를 수행한다.

속성 접근자

Bracket notation

Element안 속성(메소드)을 대괄호로 접근

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

video[method]();
다음과 같이 Bracket notation 방법으로 Element안의 속성을 접근할 수 있다.

보통은 video.play(), video.pause()와 같이
Dot notation 방법으로 접근한다

0개의 댓글