Оформление геткурс
November 14, 2022

Делаем плеер с таймкодами на getcourse с помощью плагина Plyr и скриптов

Плеер с таймкодами делаем используя "Визуальный конструктор" геткурса т.е. можно разместить видео в уроках или на страницах.

Что мы будем использовать:

  1. Визуальный конструктор геткурса(можно вставлять плеер на страницы и в уроки)
  2. Plyr плеер (Ссылка на документацию: https://github.com/sampotts/plyr )
  3. HTML(для вставки видео), CSS и JS(в геткурсе по умолчанию подключен JQuery)

Шаг 1. Подключаем Plyr

HTML:

<!-- plyr 3.7.2 -->
<link rel="stylesheet" href="https://cdn.plyr.io/3.7.2/plyr.css" />
<script src="https://cdn.plyr.io/3.7.2/plyr.polyfilled.js"></script>

Подключение Plyr на Getcourse страницу, варианты:

1. В поле страницы Теги в разделе HEAD

Пример вставки кода для подключиения Plyr в "Теги в разделе HEAD"

ИЛИ

2. В HTML блок наверху страницы

Пример вставки кода для подключиения Plyr в "HTML блок"

Шаг 2. Вставляем видео в HTML

<video id="player" playsinline controls>
  <source src="https://fs.getcourse.ru/fileservice/file/download/a/581768/sc/356/h/ed8c52d4e70d8cc5da72ac875e88b65f.mp4" type="video/mp4" />
</video>

*где src="ССЫЛКА_НА_ВИДЕО_ИЗ_ГЕТКУРС_ХРАНИЛИЩА"

id="player" - player это идентификатор, по которому мы скриптом обращаемся к видео

Шаг 3. Вставляем JS-код

Для того, чтобы на данном этапе убедиться что мы все делаем правильно, вставляем в JS-блок код

const player = new Plyr('#player');

*Javascript-блок должен находиться ниже чем блок с видео

Сохраняем -> Проверяем

Если в нашем видео интерфейс плеера Plyr, значит мы подключили и инициализировали его правильно.

Очищаем JS поле, вместо него ставим

JS-код:

/*  
@name timecodesForPlyrOnGetcourse  
@author Maksim Kalmykov  
@version 1.0
*/

$(function () {


  const timecodesArr = [
    {
      time: "00:06",
      label: "Чебурашка начинает петь"
    },

    {
      time: "00:25",
      label: "Чебурашка летит в пузыре"
    },
    {
      time: "00:40",
      label: "Чебурашка крутит юлу"
    },
    {
      time: "01:21",
      label: "Чебурашка и Гена играют в шахматы"
    }

  ];


  initPlyr("#player", timecodesArr, ".timecodes-title");


});


function initPlyr(plyrVideoSelector, timecodesArr = [], timecodeTitleSelector = null) {

  const videoPlayer = document.querySelector(plyrVideoSelector);

  if (!videoPlayer) return;

  const timecodesTitle = document.querySelector(timecodeTitleSelector);

  const timecodesContent = document.createElement("div");
  timecodesContent.className = "timecodes-ac-content";


  timecodesArr.forEach(item => {
    timecodesContent.innerHTML += `
<p class="timecode_item">
<span class="item_time">${item.time}</span>
<span class="item_desc">${item.label}</span>
</p>
`;
  });


  const timecodesArrForPlyr = timecodesArr.reduce((acc, curr) => {
    curr.time = parseTimeInSeconds(curr.time);
    acc.push(curr);
    return acc;
  }, []);


  const player = new Plyr(videoPlayer, {
    markers: {
      enabled: true,
      points: timecodesArrForPlyr
    }
  });

  timecodesContent.querySelectorAll(".timecode_item").forEach((timecode, i) => {

    timecode.addEventListener("click", function () {
      player.currentTime = timecodesArrForPlyr[i].time;
    });

  });


  if (timecodesTitle && timecodesArr.length) {
    timecodesTitle.append(timecodesContent);
  }

  if ($(timecodesTitle).hasClass("timecodes-ac-trigger")) {
    $(timecodesTitle).find(".f-header").on("click", function () {
      $(this).toggleClass("active");
      $(this).next().slideToggle();
    });
  }
}


function parseTimeInSeconds(timeStr) {

  let s = 0;

  if (typeof timeStr !== "string") return s;

  const arrTime = timeStr.split(':');

  if (arrTime.length === 2) {
    s = parseInt(arrTime[0]) * 60 + parseInt(arrTime[1]);
  } else if (arrTime.length === 3) {
    s = parseInt(arrTime[0]) * 60 * 60 + parseInt(arrTime[1]) * 60 + parseInt(arrTime[2]);
  }

  return s;

}

P.S. Уже просматривая видео решил что лучше будет если порядок аргументов в функции будет такой:

initPlyr("#player", timecodesArr, ".timecodes-title");

(массив объектов таймкодов стал вторым а селектор заголовка 3-м)

timecodesArr - массив объектов, в котором через запятую прописаны свойства конкретного таймкода. В этом массиве мы ставим свои значения. Эти значения подтянутся скриптом в метки на видео и в html код внутри контейнера указанного заголовка таймкодов.

  const timecodesArr = [
    {
    
      time: "00:06", // Время таймкода
      label: "Чебурашка начинает петь" // Описаине таймкода
    }

  ];

  initPlyr("#player", timecodesArr, ".timecodes-title");

initPlyr("*CЕЛЕКТОР_ЭЛЕМЕНТА_ВИДЕО*", *МАССИВ_ОБЪЕКТОВ_ТАЙМКОДОВ*, "*CЕЛЕКТОР_ЗАГОЛОВКА_ТАЙМКОДОВ*");

Шаг 4. Заголовок-контейнер для таймкодов на геткурс

В данном решении мы прописываем таймкоды в объекте timecodesArr, эти данные пойдут в настройки плеера, а также под них подготовится html-разметка.

Для того, чтобы вставить html-разметку таймкодов, нам нужно привязаться к какому либо контейнеру на странице. Этим контейнером будет блок геткурс с заголовком, скрипт найдет его по определенному классу(например timecodes-title)

Создаем заголовок на геткурс стандартным способом

Ставим блоку с заголовком класс - timecodes-title

Сохраняем

Возле заголовка автоматически появилась разметка с таймкодами, и они даже работают при клике, но не хватает стилизации

Шаг 5. Добавляем стилизацию

CSS-стили

/* Подключение шрифта Montserrat 400;700 */
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap');


:root {

  /* Основной цвет плеера */
  --plyr-color-main: #C96BFF;

  --fontTimecodes: "Montserrat", "proxima-nova", sans-serif;
}


.plyr__progress .plyr__tooltip {
  
/* Ширина тултипов */
  width: 160px;
}


.timecodes-title p,
.timecode_item {
  font-family: var(--fontTimecodes);
}

.timecodes-title .f-header {
  font-size: 24px;
  padding-bottom: 15px;
}

.timecode_item {
  padding: 4px 0;
  font-size: 16px;
  display: flex;
  cursor: pointer;
}

.timecode_item span {
  display: inline-block;
  line-height: 1.2;
}


.timecode_item .item_time {
  margin-right: 8px;
  flex:0 0 50px;
  font-weight: 700;

  /* Цвет времени в таймкоде*/
  color: #4848ee;
  transition: color .4s ease;
}


.timecode_item:hover .item_time {
  /* Цвет времени в таймкоде при наведении*/
  color: var(--plyr-color-main);
}

@media (max-width: 375px) {
  .timecode_item {
    font-size: 14px;
  }
}



/* СТИЛИ АККОРДЕОНА */
.timecodes-ac-trigger {
  cursor: pointer;
  box-shadow: 0 4px 12px rgb(0 0 0 / 20%);
  border-radius: 4px;
}


.timecodes-ac-trigger .f-header {
  padding: 20px 16px 20px 70px;
  position: relative;
  user-select: none;
}


.timecodes-ac-trigger .f-header::before {
  content: "";
  width: 40px;
  height: 40px;
  display: inline-block;
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  border-radius: 50px;
/* Изображение стрелки */
  background-image: url("https://fs.getcourse.ru/fileservice/file/download/a/581768/sc/243/h/5d184da29d96d2785c216cca452febb3.svg");
/* Цвет круглого фона стрелки */
  background-color: #ffdda7;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 20px;
  transition:filter .4s ease, transform .4s ease ;
}

.timecodes-ac-trigger .f-header.active::before {
  transform: translateY(-50%) rotate(180deg);
}

.timecodes-ac-trigger .f-header:hover::before {
  filter: brightness(105%);
}


.timecodes-ac-trigger .timecodes-ac-content {
  display: none;
  padding: 8px 16px 16px 16px;
}


@media (max-width: 375px) {
  .timecodes-ac-trigger .f-header {
    font-size: 18px;
  }

  .timecodes-ac-trigger .f-header::before {
    width: 32px;
    height: 32px;
    background-size: 16px;
  }

  .timecodes-ac-trigger .f-header {
    padding: 15px 15px 15px 60px;
  }

}
/* </ СТИЛИ АККОРДЕОНА */


Можно добавить в CSS-блок либо вставить и подключить через тему

На данный момент таймкоды и видео выглядят так

Простой вариант:

В скрипте и стилях предусмотрен вариант таймкодов в виде выпадающего списка

Чтобы инициализировать аккордеон добавляем класс timecodes-ac-trigger в классы заголовка

Результат:

Как сделать несколько видео с таймкодами?

Самый простой способ - вызывать несколько функций инициализации плеера с уникальными параметрами

Пример

$(function () {


    const timecodesArr1 = [
        {
            time: "00:06",
            label: "Чебурашка начинает петь"
        },

        {
            time: "00:26",
            label: "Чебурашка летит в пузыре"
        },
        {
            time: "00:40",
            label: "Чебурашка крутит юлу"
        },
        {
            time: "01:22",
            label: "Чебурашка и Гена играют в шахматы"
        }

    ];

    const timecodesArr2 = [
        {
            time: "00:06",
            label: "2 Чебурашка начинает петь"
        },

        {
            time: "00:26",
            label: "2 Чебурашка летит в пузыре"
        },
        {
            time: "00:40",
            label: "2 Чебурашка крутит юлу"
        },
        {
            time: "01:22",
            label: "2 Чебурашка и Гена играют в шахматы"
        }

    ];


    initPlyr("#player", timecodesArr1, ".timecodes-title_1");

    
    // player2 - id видео в html
    // timecodesArr2 - еще один массив с таймкодами
    // timecodes-title_2 - класс заголовка
    initPlyr("#player2", timecodesArr2, ".timecodes-title_2");

});

id видео ставится в html атрибуте - id

Уникальный класс для заголовка можно поставить в настройках заголовка

initPlyr("#player", timecodesArr1, ".timecodes-title_1");

Передавая параметры в функцию мы решаем, какая сущность к чему относится

т.е. #player - инициализируем тот плеер, которого id="player"

timecodesArr1 - берем именно этот массив таймкодов

".timecodes-title_1" - контейнером таймкодов будет заголовок с классом timecodes-title_1

Телеграм-канал: https://t.me/getcomponent

Youtube: https://www.youtube.com/channel/UCAVwlN_NSAEFR4mJRpzyvCg

VK: https://vk.com/getcomponent

Нельзяграм: @maximilia_n