[TIL] 211211

Lee Syong·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
ëŠĨ동ė ėœžëĄœ ė‚īėž, 행ëģĩ하ęēŒðŸ˜

0개ė˜ 댓ęļ€