[TIL] 211210

Lee Syong·2021년 12ė›” 10ėž
0

TIL

ëŠĐ록 ëģīęļ°
114/204
post-thumbnail

📝 ė˜Ī늘 한 ęēƒ

  1. video player - webpack ė„Īė • / playBtn / muteBtn / volume bar

📚 ë°°ėšī ęēƒ

video player

1. webpack ė„Īė •

1) entry / output

video playerëĨž ëŠĻ든 페ėīė§€ė—ė„œ 로드할 필ėš”는 ė—†ë‹Ī. video가 ėžˆëŠ” 페ėīė§€ė— ë“Īė–ī갔ė„ 때만 로드되도록 하ęļ° ėœ„í•ī video player ėžë°”ėŠĪ큎ëĶ―íŠļ 파ėžė„ í•īë‹đ 파ėž ė•ˆė—ë§Œ 폎í•Ļė‹œėžœėĪ„ ęēƒėīë‹Ī. ėīëĨž ėœ„í•ī 멇 가ė§€ ęģžė •ė„ ęą°ėģė•ž 한ë‹Ī.

현ėžŽ entry point는 하나ëŋėīë‹Ī. videoPlayer.js 파ėžė„ 만든 후 ė˜ĪëļŒė íŠļëĨž ėīėšĐí•ī ėķ”ę°€í•œë‹Ī.
output 또한 현ėžŽëŠ” ëŽīėĄ°ęąī main.js 파ėžė— ėƒė„ąë˜ëŊ€ëĄœ ėīęēƒë„ webpackė—ė„œ ė§€ė›í•˜ëŠ” ë°Đė‹ė„ ėīėšĐí•ī ėˆ˜ė •í•œë‹Ī.

// webpack.config.json
const path = require("path");

module.exports = {
  entry: {
    main: "src/client/js/main.js",
    videoPlayer: "src/client/js/videoPlayer.js", // ėķ”ę°€ ❗
  },
  output: {
    filename: "js/[name].js", // ėˆ˜ė • ❗
    path: path.resolve(__dirname, "assets"),
  }
};

watch 페ėīė§€ė— ë“Īė–ī갔ė„ 때 video player가 로드될 ėˆ˜ ėžˆë„록 watch.pug 파ėžėī videoPlayer.jsëĨž 가ė ļė™€ė•ž 한ë‹Ī. ėĶ‰, watch.pug 파ėžė— script 태ę·ļëĨž ë„Ģė–īė•ž 한ë‹Ī.
ėīëĨž ėœ„í•ī base.pug 파ėžė— block scriptsëĨž ėķ”ę°€í•œ 후, watch.pug 파ėžė—ė„œ scriptëĨž ėķ”가할 ėˆ˜ ėžˆë‹Ī.

//- base.pug

block scripts
//- watch.pug

block scripts
  script(src="/static/js/videoPlayer.js")

ðŸ’Ą ėī때 ęļ°ėĄīė— base.pugė— ėžˆë˜ script(src="/static/js/main.js")ëĨž ė‚­ė œí•ī도 ė—ëŸŽëŠ” 발ėƒí•˜ė§€ ė•ŠëŠ”ë‹Ī.

main.js 파ėžė€ client íī더 ė•ˆė˜ styles.scss 파ėžė„ import 하는 파ėžëĄœėĻ main.js 파ėž ė•ˆė˜ ė―”ë“œę°€ ė‹Ī행되는ė§€ 확ėļ하ęļ° ėœ„í•œ ëŠĐė ėœžëĄœ console.log()ė™€ í•Ļęŧ˜ base.pug 파ėžė—ė„œ 가ė ļė™”던 파ėžėīë‹Ī.

따띾ė„œ, ėīëĨž base.pug 파ėžė—ė„œ ė‚­ė œí•˜ë”띞도 (client íī더 ė•ˆė˜ styles.scss 파ėžė„ import 하는) main.js 파ėžë§Œ ėĄīėžŽí•œë‹ĪëĐī, webpackė€ ėīëĨž 확ėļ하ęģ  clientė— ėĄīėžŽí•˜ëŠ” ëģ€í™˜ë“Īė„ assetsė— 바ęŋ”ėĪ„ ęēƒėīë‹Ī.

ė •ëĶŽí•˜ėžëĐī, output ėŠĪ큎ëĶ―íŠļ는 cssëĨž 가ė ļė˜Īė§€ ė•Šęģ , input ėŠĪ큎ëĶ―íŠļ만ėī cssëĨž 가ė ļė˜ĪëĐ°, ėī는 webpackėœžëĄœ ęĩŽëķ„된ë‹Ī.


2. video player 만ë“Īęļ°

MDN - HTMLMediaElement ė°ļęģ 
HTMLVideoElement는 HTMLMediaElementëĨž ėƒė†í•œë‹Ī. 따띾ė„œ, video 태ę·ļ는 HTMLMediaElementė˜ ė†ė„ąęģž ëДė„œë“œëĨž ė‚ŽėšĐ할 ėˆ˜ ėžˆë‹Ī.

1) HTML 마큎ė—…

watch.pug 파ėžė—ė„œ video playerëĨž 만든ë‹Ī.

//- watch.pug

block content
  video(src="/" + video.fileUrl, width="800", controls)
  div
    button#playBtn Play
    button#muteBtn Mute
    span#time 00:00/00:00
    input(type="range", step="0.1", min="0", max="1")#volume

각 ėš”ė†Œë“Īė„ videoPlayer.js 파ėžëĄœ 가ė ļė˜Ļë‹Ī.

// videoPlayer.js
const video = document.querySelector("video");
const playBtn = document.getElementById("plyBtn");
const muteBtn = document.getElementById("muteBtn");
const time = document.getElementById("time");
const volumeRange = document.getElementById("volume");

ëģžëĨĻ bar가 ëŊļëĶŽ ėž‘ė„ąí•ī놓ė€ input ė„Īė • 값 때ëŽļė— ė›í•˜ëŠ” 대로 ëģīėīė§€ ė•Šė•„ forms.scssëĨž ėˆ˜ė •í–ˆë‹Ī.

// forms.scss
input:not(input[type="range"]) { ... }

2) playBtn

video.paused는 boolean 값ė„ return 한ë‹Ī.
ėīëĨž ėīėšĐí•ī video가 ėžŽėƒ ėĪ‘ėļė§€ 확ėļ할 ėˆ˜ ėžˆë‹Ī.

ėžŽėƒ ė—Žëķ€ė— 따띾 button ė•ˆė˜ text도 바ęūļ도록 한ë‹Ī.

// videoPlayer.js
const handlePlayBtnClick = (e) => {
  if (video.paused) {
    video.play();
  } else {
    video.pause();
  }
  playBtn.innerText = video.paused ? "Play" : "Pause";
};

playBtn.addEventListener("click", handlePlayBtnClick);

3) muteBtn

(1) mute / unmute

video.muted는 boolean 값ė„ return 한ë‹Ī.
video.pasuedė™€ 닮ëĶŽ ė―ęģ  ė“°ëŠ” ęēƒėī ëŠĻ두 가ëŠĨ하ë‹Ī.
ėĶ‰, ėŒė†Œęą° ėƒíƒœėļė§€ 확ėļ할 ėˆ˜ë„ ėžˆęģ , ėŒė†Œęą° ėƒíƒœëĄœ 만ë“Ī ėˆ˜ë„ ėžˆë‹Ī.

ėŒė†Œęą° ė—Žëķ€ė— 따띾 button ė•ˆė˜ text도 바ęūļ도록 한ë‹Ī.

// videoPlayer.js
const handleMute = () => {
  if (video.muted) {
    video.muted = false;
  } else {
    video.muted = true;
  }
  muteBtn.innerText = video.muted ? "Unmute" : "Mute";
};

muteBtn.addEventListener("click", handleMute);

(2) video.volumeęģž input[type="range"] ė—°ęē°

ė‹Īė œ ëģžëĨĻęģž ëģžëĨĻ 바ëĨž ė—°ë™í•īė•ž 한ë‹Ī.

ðŸ’Ą ëģžëĨĻ 바ė˜ 폎ėļ터ëĨž ė›€ė§ėž 때마ë‹Ī ëģžëĨĻė˜ 큎ęļ°ę°€ ëģ€í•˜ë„록

ėŒė†Œęą° ëē„튞ė„ 누ëĨīëĐī ëģžëĨĻ 바ė˜ 폎ėļ터가 ë§Ļ ė™žėŠ―ėœžëĄœ ė˜Ī도록 만ë“Īė–īė•ž 한ë‹Ī.
ėĶ‰, video.volumeė˜ 값ęģž input[type="range"]ė˜ valueëĨž ė—°ęē°í•īė•ž 한ë‹Ī.

ėīëĨž ėœ„í•ī input ėīëēĪíŠļëĨž ėīėšĐ할 ėˆ˜ ėžˆë‹Ī.
volumeRange inputė— input ėīëēĪíŠļëĨž 등록í•Ļė— 따띾 inputė˜ value 값ėī ëģ€í•  때마ë‹Ī handleVolumeChange ėīëēĪíŠļ í•ļë“Ī럮 í•Ļėˆ˜ę°€ ė‹Ī행된ë‹Ī.

// videoPlayer.js
const handleVolumeChange = (event) => {
  const { target: { value } } = event;
  video.volume = value;
};

volumeRange.addEventListener("input", handleVolumeChange);

ėīė œ ëģžëĨĻ 바ė˜ 폎ėļ터ëĨž ėĒŒėš°ëĄœ ė›€ė§ėž 때마ë‹Ī videoė˜ ė‹Īė œ ëģžëĨĻėī ëģ€í•˜ëŠ” ęēƒė„ 확ėļ할 ėˆ˜ ėžˆë‹Ī.

ðŸ’Ą ėŒė†Œęą° ėƒíƒœėž 때, ëģžëĨĻ 바 ė›€ė§ėīëĐī, ę·ļė— 맞ėķ° ëģžëĨĻ 큎ęļ°ę°€ ëģ€í•˜ë„록

ę·ļ럮나, ėŒė†Œęą° ëē„튞ė„ ëĻžė € 눌럮 ėŒė†Œęą° ėƒíƒœėž 때는 ëģžëĨĻ 바ëĨž ė›€ė§ė—Žë„ ę·ļ대로 ėŒė†Œęą° ėƒíƒœėīë‹Ī.

volumeRangeė˜ value 값ęģž video.volumeė˜ 값ėī ëŠĻ두 ëģ€í•˜ęļī 하ė§€ë§Œ, video.muted가 true 값ė„ 가ė§€ęļ° 때ëŽļė— ęģ„ė† ėŒė†Œęą° ėƒíƒœę°€ ėœ ė§€ë˜ëŠ” ęēƒėīë‹Ī.

따띾ė„œ, handleVolumeChange í•Ļėˆ˜ ė•ˆė—ė„œ video.muted가 true 값ėļ ęē―ėš°ëĨž ėķ”ę°€ëĄœ ë‹ĪëĪ„ėĪ˜ė•ž 한ë‹Ī.

const handleVolumeChange = (event) = {
  const { target: { value } } = evenvt;
  if (video.muted) {
    video.muted = false;
    muteBtn.innerText: "Mute";
  }
  video.volume = value;
};

ėīė œ ėŒė†Œęą° ėƒíƒœėļ ęē―ėš°ė—ë„ ëģžëĨĻ 바ëĨž ė›€ė§ėīëĐī ė›í•˜ëŠ” 대로 ëģžëĨĻėī ėĄ°ė •ë˜ëŠ” ęēƒė„ 확ėļ할 ėˆ˜ ėžˆë‹Ī.

ðŸ’Ą ėŒė†Œęą° ėƒíƒœėž 때, ėŒė†Œęą° ëē„튞 ë‹Īė‹œ 한ëēˆ 누ëĨīëĐī, ė†ŒëĶŽę°€ 돌ė•„ė˜Ī도록

ę·ļ럮나, ėŒė†Œęą° ėƒíƒœė—ė„œ ėŒė†Œęą° ëē„튞ė„ ë‹Īė‹œ 눌럮 ëģžëĨĻė„ 돌ė•„ė˜ĪęēŒ 만ë“Īė–ī도, ëģžëĨĻ 바는 ėŒė†Œęą° ėīė „ė˜ ėƒíƒœëĄœ 돌ė•„ė˜Īė§€ ė•Šęģ  ę·ļ대로 ë§Ļ ė™žėŠ―ė— ë‚Ļė•„ ėžˆë‹Ī.

video.volumeė„ ęļ°ė–ĩ하ęģ  ė—…데ėīíŠļ하ė—Ž ėŒė†Œęą° ė—Žëķ€ė— 따띾 inputė˜ value 값ėī 닮띾ė§€ë„록 한ë‹Ī.

// videoPlayer.js
const volumeValue = 0.3;
video.volume = volumeValue;

const handleMute = () => {
  if (video.muted) {
    video.muted = false;
  } else {
    video.muted = true;
  }
  muteBtn.innerText = video.muted ? "Mute" : "Unmute";
  volumeRange.value = video.muted ? 0 : volumeValue; // ėŒė†Œęą° ėƒíƒœ í•īė œë˜ëĐī ėīė „ ëģžëĨĻėī ë‹Īė‹œ 돌ė•„ė˜ī
};

const handleVolumeChange = (event) => {
  const { target: { value } } = event;
  if (video.muted) {
    video.muted = false;
    muteBtn.innerText = "Mute";
  }
  volumeValue = value;
  video.volume = volumeValue;
};

âœĻ ë‚īėž 할 ęēƒ

  1. video player
profile
ëŠĨ동ė ėœžëĄœ ė‚īėž, 행ëģĩ하ęēŒðŸ˜

0개ė˜ 댓ęļ€