[TIL] 211211

dev·2021년 12ė›” 11ėž
0

TIL

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

📝 ė˜Ī늘 한 ęēƒ

  1. video player - currentTime / duration / input ėīëēĪíŠļ / fullscreen

  2. mouse events - mousemove / mouseleave / mouse stop


📚 ë°°ėšī ęēƒ

video player

1. Time (currentTime / Duration)

1) watch.pug

div
  span#currentTime 00:00
  span  / 
  span#totalTime 00:00

2) videoPlayer.js

(1) ë°Đëē• 1: ëŠŦ / 나ëĻļė§€ ėīėšĐ

ėīˆ ë‹Ļėœ„ëĨž ëŠŦęģž ë‚˜ëĻļė§€ ė‹ė„ ėīėšĐí•ī ëķ„·ėīˆ ë‹Ļėœ„ëĄœ 바ęūž 후 padStart()ëĨž ėīėšĐí•ī ėžëĶŽėˆ˜ëĨž 맞ėķ°ėĢžė—ˆë‹Ī. (ë‚ī가 ė‚ŽėšĐ한 ë°Đëē•)

const currentTime = document.getElementById("currentTime");
const totalTime = document.getElementById("totalTime");

const makeVideoTime = (seconds) => {
  const min = Math.floor(seconds / 60); // ëŠŦ
  const second = seconds % 60; // 나ëĻļė§€
  return `${String(min).padStart(2, "0")}:${String(second).padStart(2, "0")}`;
};

const handleLoadedMetaData = () => {
  totalTime.innerText = makeVideoTime(Math.floor(video.duration));
};

const handleTimeUpdate = () => {
  currentTime.innerText = makeVideoTime(Math.floor(video.currentTime));
};

video.addEventListener("loadedmetadata", handleLoadedMetaData);
video.addEventListener("timeupdate", handleTimeUpdate);

(2) ë°Đëē• 2: date formatter ėīėšĐ

밀ëĶŽėīˆ ë‹Ļėœ„ëĨž date 객ėēī로 만든 후 substr()ëĨž ėīėšĐí•ī ëķ„·ėīˆ ë‹Ļėœ„ë§Œ ėž˜ëžëƒˆë‹Ī. (ę°•ė˜ė—ė„œ ė‚ŽėšĐ한 ë°Đëē•)

const currentTime = document.getElementById("currentTime");
const totalTime = document.getElementById("totalTime");

const formatTime = (seconds) => new Date(seconds * 1000).toISOString().substr(14, 5);

const handleLoadedMetaData = () => {
  totalTime.innerText = formatTime(Math.floor(video.duration));
};

const handleTimeUpdate = () => {
  currentTime.innerText = formaTime(Math.floor(video.currentTime));
};

video.addEventListener("loadedmetadata", handleLoadedMetaData);
video.addEventListener("timeupdate", handleTimeUpdate);

2. Timeline

1) watch.pug

max ę°’ė€ video마ë‹Ī ęļļėī가 ë‹ĪëĨīëŊ€ëĄœ ė‚Žė „ė— ė„Īė •í•˜ė§€ ė•ŠëŠ”ë‹Ī.

input(type="range", step="1", value="0", min="0")#timeline

2) videoPlayer.js

(1) ëđ„ë””ė˜Ī ė‹œę°„ėī ëģ€í•  때마ë‹Ī íƒ€ėž„ëžėļėī 뛀링ėī도록

ëĻžė €, videoė˜ metadata가 로드되ëĐī videoė˜ ęļļėīëĨž ë°›ė•„ė™€ė„œ ėīëĨž inputė˜ max ę°’ėœžëĄœ ė„Īė •í•īėĪ€ë‹Ī.

video가 ėžŽėƒė„ ė‹œėž‘í•˜ëĐī video ė‹œę°„ė— 맞ėķ° íƒ€ėž„ëžėļ ėƒė˜ 폎ėļ터가 ėī동하도록 video.currentTimeėī timeline.valueė˜ 값ėī 되도록 한ë‹Ī.

const timeline = document.getElementById("timeline");

const handleLoadedMetaDate = () => {
  totalTime.innerText = formatTime(Math.floor(video.duration));
  timeline.max = Math.floor(video.duration); // ėķ”ę°€ ❗
};

const handleTimeUpdate = () => {
  currentTime.innerText = formatTime(Math.floor(video.currentTime));
  timeline.value = Math.floor(video.currentTime); // ėķ”ę°€ ❗
};

video.addEventListener("loadedmetadata", handleLoadedMetaData);
video.addEventListener("timeupdate", handleTimeUpdate);

(2) íƒ€ėž„ëžėļėī ė›€ė§ėž 때마ë‹Ī ëđ„ë””ė˜Ī ė‹œę°„ėī ëģ€í•˜ë„록

input ėīëēĪíŠļëĨž ėīėšĐí•ī íƒ€ėž„ëžėļ ėƒė—ė„œ 폎ėļ터ëĨž ėīë™ė‹œí‚Ž 때마ë‹Ī timeline.value가 video.currentTimeė˜ 값ėī 되도록 한ë‹Ī.

const timeline = document.getElementById("timeline");

const handleTimelineChange = (event) => {
  const { target: { value} } = event;
  video.currentTime = value;
};

timeline.addEventListener("input", handleTimelineChange);

3. Fullscreen

MDN - Using fullscreen mode ė°ļęģ 

1) watch.pug

div
  button#fullScreen Enter Full Screen

2) videoPlayer.js

element.requestFullscreen()ė„ ėīėšĐí•ī í•īë‹đ ėš”ė†ŒëĨž ė „ėēī 화ëĐīėœžëĄœ 만ë“Īęģ , document.exitFullscreen()ė„ ėīėšĐí•ī ė „ėēī 화ëĐīė„ ė›ëž˜ëŒ€ëĄœ 되돌ëĶī 눘 ėžˆë‹Ī.

ėī때 video.requestFullscreen()ė„ ė‚ŽėšĐ하ëĐī video만 ė „ėēī 화ëĐīėī 된ë‹Ī.
ėŧĻíŠļëĄĪ럮ęđŒė§€ ė „ėēī화ëĐīėœžëĄœ 만ë“Īë ĪëĐī watch.pug íŒŒėžė˜ ė―”ë“œëĨž ėˆ˜ė •í•īė•ž 한ë‹Ī.
ëđ„ë””ė˜ĪëĨž 폎í•Ļí•˜ė—Ž ė•žė„œ 만ë“Īė–ī둔 ëŠĻ든 ëđ„ë””ė˜Ī 플레ėīė–ī ęī€ë Ļ ė―”ë“œëĨž div#videoContainer ė•ˆė— ë„Ģė–īėĪŽë‹Ī.

document.fullscreenElement는 ė „ėēī 화ëĐī ėƒíƒœėž 때는 ę·ļ ėš”ė†ŒëĨž 반환하ęģ , ė „ėēī 화ëĐī ėƒíƒœę°€ ė•„ë‹ 때는 nullė„ 반환한ë‹Ī.

const fullScreenBtn = document.getElementById("fullScreenBtn");

const handleFullscreen = () => {
  const fullscreen = document.fullscreenElement;
  if (fullscreen) {
    videoContainer.requestFullscreen();
    fullScreenBtn.innerText = "Exit Full Screen";
  } else {
    document.exitFullscreen();
    fullScreenBtn.innerText = "Enter Full Screen";
  }
};

fullScreenBtn.addEventListener("click", handleFullscreen);

4. Mouse Events

ë§ˆėš°ėŠĪ ėŧĪė„œëĨž ëđ„ë””ė˜Ī ėœ„ė— ė˜ŽëĶŽëĐī ëđ„ë””ė˜Ī ėŧĻíŠļëĄĪ럮ëĨž ëģīė—ŽėĢžęģ , ë§ˆėš°ėŠĪ ėŧĪė„œëĨž ëđ„ë””ė˜Ī ë°–ėœžëĄœ ėī동 후 3ėīˆę°€ ė§€ë‚˜ëĐī ëđ„ë””ė˜Ī ėŧĻíŠļëĄĪ럮ëĨž ėˆĻęēĻėĪ„ ęēƒėīë‹Ī.

ëđ„ë””ė˜Ī ė•ˆė—ė„œë„ ë§ˆėš°ėŠĪ가 ęģ„ė† 뛀링ėļë‹ĪëĐī ëđ„ë””ė˜Ī ėŧĻíŠļëĄĪ럮ëĨž ëģīė—ŽėĢžęģ , ë§ˆėš°ėŠĪ ėŧĪė„œę°€ 3ėīˆ ë™ė•ˆ 뛀링ėīė§€ ė•ŠëŠë‹ĪëĐī ëđ„ë””ė˜Ī ėŧĻíŠļëĄĪ럮ëĨž ėˆĻęēĻėĪ„ ęēƒėīë‹Ī.

1) watch.pug

div#videoContainer
  video(src="/" + video.fileUrl, widht="800")
  div#videoControls
    button#playBtn Play
    button#muteBtn Mute
    div
      span#currentTime 00:00
      span  / 
      sapn#totalTime 00:00
    input(type="range", step="0.1", value="0.3", min="0", max="1")
    input(type="range", step="1", value="0", min="0")
    div
      button#fullScreenBtn Enter Full Screen

2) videoPlayer.js

(1) mousemove / mouseleave

classëĨž ėīėšĐí•ī css ėŠĪíƒ€ėžė„ 렁ėšĐė‹œí‚Īë Īęģ  í•œë‹Ī.
ėžë‹Ļ ë§ˆėš°ėŠĪ ėŧĪė„œëĨž ëđ„ë””ė˜Ī ėœ„ëĄœ ė˜ŽëĶŽëĐī 'showing' class가 ėķ”ę°€ë˜ë„ëĄ 하ęģ , ë°–ėœžëĄœ ėī동 후 3ėīˆę°€ ė§€ë‚˜ëĐī ė‚­ė œë˜ë„ëĄ 한ë‹Ī.

const videoControls = document.getElementById("videoControls");

// ë§ˆėš°ėŠĪ ėŧĪė„œëĨž ëđ„ë””ė˜Ī ėœ„ëĄœ ė˜ŽëĶŽëĐī
const handleMouseMove = () => {
  videoControls.classList.add("showing");
};

// ë§ˆėš°ėŠĪ ėŧĪė„œëĨž ëđ„ë””ė˜Ī ë°–ėœžëĄœ ėī동하ëĐī
const handleMouseLeave = () => {
  setTimeout(() => {
    videoControls.classList.remove("showing");
  }, 3000);
};

video.addEventListener("mousemove", handleMouseMove);
video.addEventListener("mouseleave", handleMouseLeave);

(2) clearTimeout()

ę·ļ럮나 ėī렇ęēŒë§Œ ėž‘ė„ąí•˜ëĐī ë§ˆėš°ėŠĪ ėŧĪė„œëĨž ëđ„ë””ė˜Ī ėœ„ëĄœ ė˜Žë ļë‹Ī가 ë°–ėœžëĄœ 나간 후 ë‹Īė‹œ ë“Īė–īė™€ë„ 'showing' class가 ëģīėīė§€ ė•Šęģ  ė‚Žëžė§€ëŠ” ëŽļė œę°€ ë°œėƒí•œë‹Ī.

ë§ˆėš°ėŠĪ ėŧĪė„œëĨž ëđ„ë””ė˜Ī ėœ„ëĄœ ë‹Īė‹œ ė˜Žë ļė„ 때 'showing' class가 ë‚Ļė•„ėžˆë„ëĄ 하ë ĪëĐī, ë§ˆėš°ėŠĪ ėŧĪė„œëĨž ëđ„ë””ė˜Ī ėœ„ëĄœ ë‹Īė‹œ ė˜Žë ļė„ 때 clearTimeout()ė„ ėīėšĐí•ī setTimeout()ė„ ė·Ļė†Œí•īė•ž 한ë‹Ī.
ėīëĨž ėœ„í•īė„œëŠ” timerëĨž ęģĩ뜠í•īė•ž 한ë‹Ī.

const videoControls = document.getElementById("videoControls");

let controlsTimeout = null;

const handleMouseMove = () => {
  videoControls.classList.add("showing");
  if (controlsTimeout) {
    clearTimeout(controlsTimeout);
    controlsTimeout = null;
  }
};

const handleMouseLeave = () => {
  controlsTimeout = setTimeout(() => {
    videoControls.classList.remove("showing");
  }, 3000);
};

video.addEventListener("mousemove", handleMouseMove);
video.addEventListener("mouseleave", handleMouseLeave);

(3) mouse stop

ëđ„ë””ė˜Ī ė•ˆė—ė„œ ë§ˆėš°ėŠĪ가 ęģ„ė† 뛀링ėļë‹ĪëĐī ëđ„ë””ė˜Ī ėŧĻíŠļëĄĪ럮ëĨž ęģ„ė† ëģīė—ŽėĢžëĐī ë˜ė§€ë§Œ, ëđ„ë””ė˜Ī ė•ˆė—ė„œë„ ë§ˆėš°ėŠĪ ėŧĪė„œę°€ 3ėīˆ ë™ė•ˆ 뛀링ėīė§€ ė•ŠëŠ”ë‹ĪëĐī ëđ„ë””ė˜Ī ėŧĻíŠļëĄĪ럮ëĨž ėˆĻęēĻėĪ˜ė•ž 한ë‹Ī.

mousestopėī띾는 ėīëēĪíŠļ는 ė—†ęļ° ë•ŒëŽļ뗐 mousemove ėīëēĪíŠļ ëĶŽėŠĪ너 ė•ˆė—ė„œ setTimeout()ęģž clearTimeout()ė„ ėīėšĐí•īė•ž 한ë‹Ī.

const hideControls = () => videoControls.classList.remove("showing");

// 1. ë§ˆėš°ėŠĪ ėŧĪė„œëĨž ëđ„ë””ė˜Ī ėœ„ëĄœ ė˜ŽëĶŽëĐī
const handleMouseMove = () => {
  // ėĪ‘ëžĩ
  
  if (mouseMoveTimer) { // 4. ę·ļ럮나 3ėīˆę°€ 되ęļ° ė „ė— ë§ˆėš°ėŠĪëĨž 뛀링ėīëĐī
    clearTimeout(mouseMoveTimer); // 5. showing classëĨž ė‚­ė œí•˜ëŠ” 3ėīˆ íƒ€ėīëĻļ가 ė·Ļė†Œë˜ęģ 
    mouseMoveTimer = null;
  }
  videoControls.classList.add("showing"); // 2. showing class가 ėķ”ę°€ëĻ // 6. ė—Žė „ížˆ showing class가 ëķ€ė—Žëœ ėƒíƒœ
  mouseMoveTimer = setTimeout(hideControls, 3000); // 3. ë§ˆėš°ėŠĪ ėŧĪė„œëĨž 뛀링ėīė§€ ė•Šęģ  3ėīˆę°€ ė§€ë‚˜ëĐī showing class가 ė‚­ė œëĻ
};

ė͉, ëđ„ë””ė˜Ī ė•ˆė—ė„œ ë§ˆėš°ėŠĪëĨž ė›€ė§ėž 때마ë‹Ī ėŧĻíŠļëĄĪ럮ëĨž ė‚­ė œí•˜ëŠ” setTimeout í•Ļ눘ëĨž 만ë“Īęģ  ėžˆė§€ë§Œ, ë§ˆėš°ėŠĪ가 ęģ„ė† 뛀링ėīëĐī 바로 렄뗐 만든 ę·ļ í•Ļ눘ëĨž ęģ„ė† ė‚­ė œí•˜ęļ° ë•ŒëŽļ뗐 ėŧĻíŠļëĄĪ럮가 ėœ ė§€ë˜ëŠ” ęēƒėīë‹Ī.
ë§ˆėš°ėŠĪ가 ęģ„ė† 뛀링ėīëĐī hideControls í•Ļėˆ˜ę°€ ėą„ ė‹Ī행되ęļ° ė „ė— setTimeout í•Ļėˆ˜ę°€ ė‚­ė œëœë‹Ī.
ėŧĻíŠļëĄĪ럮ëĨž ė‚­ė œí•˜ë ĪëĐī 3ėīˆ ë™ė•ˆ ë§ˆėš°ėŠĪ ėŧĪė„œę°€ 뛀링ėīė§€ ė•Šė•„ė•ž 한ë‹Ī.


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

  1. ëģĩėŠĩ
profile
dev log

0ę°œė˜ 댓ęļ€