Пользовательский индикатор выполнения для YouTube Iframe с пользовательским временем начала и окончания - PullRequest
1 голос
/ 25 января 2020

Я пытаюсь создать пользовательскую строку прогресса YouTube с другим временем начала и окончания (отличным от начального и продолжительности по умолчанию), из-за того, что я хочу показать только часть видео, а также пользователь не может просмотреть весь оригинал видео. Веб-сайт для справки: https://tutorialzine.com/2015/08/how-to-control-youtubes-video-player-with-javascript

Я использую этот код с интервалом в 1 секунду для обновления индикатора выполнения, который является вводом диапазона.

<input type="range" id="progress-bar" value="0" />

function updateProgressBar(){
    // Update the value of our progress bar accordingly.
    $('#progress-bar').val((player.getCurrentTime() / Session.get('customEndTime') * 100);
}

Однако, это не служит цели, так как отнимает текущее время от player.getCurrentTime () Когда я на самом деле хочу, чтобы он начинался с 0 или крайнего левого угла, так как я хочу, чтобы он выглядел так, как будто он играет с самого начала.

Предположим, что моя начальная длительность равна 10, а конечная длительность равна 60. Как я могу отобразить индикатор выполнения, чтобы он давал процент и увеличивался по мере прогресса моего игрока.

1 Ответ

1 голос
/ 25 января 2020

Я пытался прокомментировать код, как мог, но что-то вроде этого должно работать .. Трюк на самом деле просто установить min и max на input с type='range' ..

Я также параметризовал каждую функцию - я считаю, что параметризованные функции масштабируются лучше ..

~ ~ ~ ВАЖНО отметить, что переполнение стека не появляется чтобы разрешить использование iframe во фрагменте ~ ~ ~, вы можете:

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Custom YouTube Controls</title>
</head>

<body>
  <div id="video-placeholder"></div>
  <div>
    <button id="play">Play</button>
    <button id="pause">Pause</button>
    <input id="progress-bar" type="range" style="width: 300px;">
    <span id="current-time"></span>
    <span id="duration"></span>
  </div>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
  <script src="https://www.youtube.com/iframe_api"></script>
  <script>
    /** 
     * CONFIGURATION
     */

    var YOUTUBE_PLAYER,
      YOUTUBE_PLAYER_EL = "video-placeholder", // Don't have to specify "#" here
      START_TIME = "1:00",
      END_TIME = "1:20",
      PLAY_EL = "#play",
      PAUSE_EL = "#pause",
      PROGRESS_BAR_EL = "#progress-bar",
      CURRENT_TIME_EL = "#current-time",
      DURATION_EL = "#duration";

    /**
     * FUNCTIONS
     */

    function onYouTubeIframeAPIReady() {
      /**
       * Builds main YouTube API object
       */

      YOUTUBE_PLAYER = new YT.Player(YOUTUBE_PLAYER_EL, {
        width: 600,
        height: 400,
        videoId: 'Xa0Q0J5tOP0',
        playerVars: {
          // Supported player params can be found at https://developers.google.com/youtube/player_parameters#Parameters
          controls: 0, // disable video controls on mouse over
          disablekb: 1, // disable keyboard controls
          start: minutesToSeconds(START_TIME),
          end: minutesToSeconds(END_TIME),
        },
        events: {
          onReady: () => initialize(START_TIME, END_TIME, YOUTUBE_PLAYER, PLAY_EL, PAUSE_EL, PROGRESS_BAR_EL, CURRENT_TIME_EL, DURATION_EL)
        }
      });
    }

    function initialize(videoStartTime, videoEndTime, playerObj, playElId, pauseElId, progressBarElId, currentTimeElId, durationElId) {
      /**
       * Initializes all functions for player.
       * The reason we check for PlayerState is because if the video ends, and a user clicks play
       * it will start from the very beginning instead of our desired start time.
       *
       * More can be found https://developers.google.com/youtube/iframe_api_reference#Playback_status
       */

      $(playElId).on('click', () => { // Set play button click handler
        playerObj.getPlayerState() === 0 // a state of 0 means 'ended'
          ? playerObj.seekTo(minutesToSeconds(videoStartTime)) 
          : null;
        playerObj.playVideo();
      });

      $(pauseElId).on('click', () => playerObj.pauseVideo()); // Set pause button click handler

      $(progressBarElId) // Set min/max values for progress bar & set mouseup and touchend handlers
        .attr('min', minutesToSeconds(videoStartTime))
        .attr('max', minutesToSeconds(videoEndTime))
        .on('mouseup touchend', e => playerObj.seekTo(e.target.value));

      playerObj.seekTo(minutesToSeconds(videoStartTime)); // Sets the progress bar to correct start time
      doUpdate(currentTimeElId, durationElId, progressBarElId, playerObj, videoEndTime); // Updates progress bar and timestamp

      let time_update_interval = setInterval(() => { // Creates interval for updating progress bar and timestamp
        doUpdate(currentTimeElId, durationElId, progressBarElId, playerObj, videoEndTime);
      }, 1000);
    }


    function doUpdate(currentTimeElId, durationElId, progressBarElId, playerObj, videoEndTime) {
      /**
       * Updates current_time / duration
       * Updates progress_bar
       */

      updateTimerDisplay(currentTimeElId, durationElId, playerObj, videoEndTime);
      updateProgressBar(progressBarElId, playerObj);
    }


    function updateTimerDisplay(currentTimeElId, durationElId, playerObj, videoEndTime) {
      /**
       * Updates current_time / duration
       */

      $(currentTimeElId).text(formatTime(playerObj.getCurrentTime()));
      $(durationElId).text(formatTime(minutesToSeconds(videoEndTime)));
    }


    function formatTime(time) {
      /**
       * Formats time in xx:xx format
       */

      time = Math.round(time);
      let minutes = Math.floor(time / 60),
        seconds = time - minutes * 60;
      seconds = seconds < 10 ? '0' + seconds : seconds;
      return minutes + ":" + seconds;
    }


    function updateProgressBar(progressBarElId, playerObj) {
      /**
       * Updates progress bar
       */

      $(progressBarElId).val(playerObj.getCurrentTime());
    }
    

    function minutesToSeconds(mins) {
      /**
       * ~~ mins param must be a str in "1:00" format ~~
       * Converts time in xx:xx format to seconds
       */

      let p = mins.split(":");
      return Number((Number(p[0]) * 60 + Number(p[1])).toFixed(3));
    }
  </script>
</body>

</html>

ОБНОВЛЕНИЕ:

Вы спрашивали о том, чтобы начать с 0 и показать время окончания "итога" раздел "вы будете sh играть ...

Это Зеркало CodePen показывает, как вы можете выполнить sh, вместе с кодом ниже:

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Custom YouTube Controls</title>
</head>

<body>
  <div id="video-placeholder"></div>
  <div>
    <button id="play">Play</button>
    <button id="pause">Pause</button>
    <input id="progress-bar" type="range" style="width: 300px;">
    <span id="current-time"></span>
    <span id="duration"></span>
  </div>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
  <script src="https://www.youtube.com/iframe_api"></script>
  <script>
    /** 
     * CONFIGURATION
     */

    var YOUTUBE_PLAYER,
      YOUTUBE_PLAYER_EL = "video-placeholder", // Don't have to specify "#" here
      YOUTUBE_VIDEO_ID = "Xa0Q0J5tOP0",
      START_TIME = "1:00",
      END_TIME = "1:20",
      PLAY_EL = "#play",
      PAUSE_EL = "#pause",
      PROGRESS_BAR_EL = "#progress-bar",
      CURRENT_TIME_EL = "#current-time",
      DURATION_EL = "#duration";

    /**
     * FUNCTIONS
     */

    function onYouTubeIframeAPIReady() {
      /**
       * Builds main YouTube API object
       */

      YOUTUBE_PLAYER = new YT.Player(YOUTUBE_PLAYER_EL, {
        width: 600,
        height: 400,
        videoId: YOUTUBE_VIDEO_ID,
        playerVars: {
          // Supported player params can be found at https://developers.google.com/youtube/player_parameters#Parameters
          controls: 0, // disable video controls on mouse over
          disablekb: 1, // disable keyboard controls
          start: minutesToSeconds(START_TIME),
          end: minutesToSeconds(END_TIME),
        },
        events: {
          onReady: () => initialize(START_TIME, END_TIME, YOUTUBE_PLAYER, PLAY_EL, PAUSE_EL, PROGRESS_BAR_EL, CURRENT_TIME_EL, DURATION_EL)
        }
      });
    }

    function initialize(videoStartTime, videoEndTime, playerObj, playElId, pauseElId, progressBarElId, currentTimeElId, durationElId) {
      /**
       * Initializes all functions for player.
       * The reason we check for PlayerState is because if the video ends, and a user clicks play
       * it will start from the very beginning instead of our desired start time.
       *
       * More can be found https://developers.google.com/youtube/iframe_api_reference#Playback_status
       */

      const START_SECONDS = minutesToSeconds(videoStartTime),
        END_SECONDS = minutesToSeconds(videoEndTime),
        TOTAL_SECONDS = END_SECONDS - START_SECONDS;

      // Make sure the end time is greater than the start time, the total play time is greater 
      // than 0 and we didnt specify an end time greater than the videos length
      if (END_SECONDS > START_SECONDS && TOTAL_SECONDS > 0 && playerObj.getDuration() > END_SECONDS) {

        $(playElId).on('click', () => { // Set play button click handler
          playerObj.getPlayerState() === 0 // a state of 0 means 'ended'
            ? playerObj.seekTo(minutesToSeconds(videoStartTime)) 
            : null;
          playerObj.playVideo();
        });

        $(pauseElId).on('click', () => playerObj.pauseVideo()); // Set pause button click handler

        $(progressBarElId) // Set min/max values for progress bar & set mouseup and touchend handlers
          //.attr('min', minutesToSeconds(videoStartTime))
          //.attr('max', minutesToSeconds(videoEndTime))
          .attr('min', 0)
          .attr('max', TOTAL_SECONDS)       
          .on('mouseup touchend', e => playerObj.seekTo(Number(e.target.value) + Number(START_SECONDS)));

        playerObj.seekTo(minutesToSeconds(videoStartTime)); // Sets the progress bar to correct start time
        doUpdate(currentTimeElId, durationElId, progressBarElId, playerObj, START_SECONDS, TOTAL_SECONDS); // Updates progress bar and timestamp

        let time_update_interval = setInterval(() => { // Creates interval for updating progress bar and timestamp
          doUpdate(currentTimeElId, durationElId, progressBarElId, playerObj, START_SECONDS, TOTAL_SECONDS);
        }, 1000);
      
      } else {
        playerObj.destroy();
        alert("Unable to play video, please verify supplied parameters!")
      }
    }


    function doUpdate(currentTimeElId, durationElId, progressBarElId, playerObj, startSeconds, totalSeconds) {
      /**
       * Updates current_time / duration
       * Updates progress_bar
       */

      updateTimerDisplay(currentTimeElId, durationElId, playerObj, startSeconds, totalSeconds);
      updateProgressBar(progressBarElId, playerObj, startSeconds);
    }


    function updateTimerDisplay(currentTimeElId, durationElId, playerObj, startSeconds, totalSeconds) {
      /**
       * Updates current_time / duration
       */

      $(currentTimeElId).text(formatTime(Number(playerObj.getCurrentTime()) - Number(startSeconds)));
      $(durationElId).text(formatTime(totalSeconds));
    }


    function formatTime(time) {
      /**
       * Formats time in xx:xx format
       */

      time = Math.round(time);
      let minutes = Math.floor(time / 60),
        seconds = time - minutes * 60;
      seconds = seconds < 10 ? '0' + seconds : seconds;
      return minutes + ":" + seconds;
    }


    function updateProgressBar(progressBarElId, playerObj, startSeconds) {
      /**
       * Updates progress bar
       */

      //$(progressBarElId).val(playerObj.getCurrentTime());
      $(progressBarElId).val(playerObj.getCurrentTime() - startSeconds);
    }
    

    function minutesToSeconds(mins) {
      /**
       * ~~ mins param must be a str in "1:00" format ~~
       * Converts time in xx:xx format to seconds
       */

      let p = mins.split(":");
      return Number((Number(p[0]) * 60 + Number(p[1])).toFixed(3));
    }
  </script>
</body>

</html>
...