Одна из вещей, которые заинтересовало меня, совсем недавно создают полностью индивидуальный видеоплеер. Очевидно, что в наши дни у нас есть услуги, которые предоставляют виджеты, которые будут использоваться на наших сайтах.
Или, с другой стороны, у вас уже есть зависимости, которые вы можете установить и начать использовать. Но эти средства приходят по цене, в которой в этом случае является отсутствие или сложность настройки.
Вот почему у меня была идея создать свой собственный видеоплеер и, видимо, это не так сложно, как я думал, и в конце я нашел это весело.
Именно по этой причине у меня была идея написать эту статью, чтобы объяснить шаг за шагом, как сделать простой видеоплеер, но с той же логикой вы можете пойти намного дальше.
В сегодняшнем примере мы собираемся использовать Это Видео, он имеет звук и совершенно бесплатно.
Сегодня мы не собираемся использовать какие-либо внешние зависимости, поэтому вы будете полностью знакомы со всем.
Что касается стиля, в конце концов я дам код CSS, это потому, что фокус статьи состоит в том, чтобы научить логику за то, как работает видеоплеер.
Первое, что я спрашиваю, это скачать видео, упомянутое выше, а затем переименовать файл на видео.mp4. . Наконец создайте папку в вашем проекте под названием Активы и перетащите файл в эту папку.
Так что у нас нет кода в одном файле, давайте создадим наш собственный крючок, который будет отвечать за контроль всей работы нашего видеоплеер.
// @src/hooks/useVideoPlayer.js
const useVideoPlayer = () => {
// ...
};
export default useVideoPlayer;
В нашем крючке мы собираемся использовать только два реактивных крючка, Usestate () и Useffect () Отказ
// @src/hooks/useVideoPlayer.js
import { useState, useEffect } from "react";
const useVideoPlayer = () => {
// ...
};
export default useVideoPlayer;
Теперь мы можем начать создавать наше состояние, которое мы позвоним Playerstate Отказ Это состояние нашего будет иметь четыре свойства, распечатывая, ослабленные, прогресс и скорость.
// @src/hooks/useVideoPlayer.js
import { useState, useEffect } from "react";
const useVideoPlayer = () => {
const [playerState, setPlayerState] = useState({
isPlaying: false,
progress: 0,
speed: 1,
isMuted: false,
});
// ...
};
export default useVideoPlayer;
Одна вещь, которую я хочу, чтобы вы имели в виду, что наш крючком должен принять один аргумент, который в этом случае будет ссылка на наше видео, которое мы собираемся назвать видеоэлемент.
// @src/hooks/useVideoPlayer.js
import { useState, useEffect } from "react";
const useVideoPlayer = (videoElement) => {
const [playerState, setPlayerState] = useState({
isPlaying: false,
progress: 0,
speed: 1,
isMuted: false,
});
// ...
};
export default useVideoPlayer;
Теперь мы можем создать нашу функцию, которая будет диктовать, если игрок приостановлен или нет. Для этого мы будем держать значения всех других свойств нашего PlayerState И мы просто скажем, что всякий раз, когда функция выполняется, это предоставить обратное значение текущего состояния ISPlaying.
// @src/hooks/useVideoPlayer.js
import { useState, useEffect } from "react";
const useVideoPlayer = (videoElement) => {
const [playerState, setPlayerState] = useState({
isPlaying: false,
progress: 0,
speed: 1,
isMuted: false,
});
const togglePlay = () => {
setPlayerState({
...playerState,
isPlaying: !playerState.isPlaying,
});
};
// ...
};
export default useVideoPlayer;
Теперь нам нужно использовать Useffect () Чтобы приостановить или не видео через значение свойства ISPlaying.
// @src/hooks/useVideoPlayer.js
import { useState, useEffect } from "react";
const useVideoPlayer = (videoElement) => {
const [playerState, setPlayerState] = useState({
isPlaying: false,
progress: 0,
speed: 1,
isMuted: false,
});
const togglePlay = () => {
setPlayerState({
...playerState,
isPlaying: !playerState.isPlaying,
});
};
useEffect(() => {
playerState.isPlaying
? videoElement.current.play()
: videoElement.current.pause();
}, [playerState.isPlaying, videoElement]);
// ...
};
export default useVideoPlayer;
Теперь мы должны создать функцию, чтобы помочь нам знать прогресс видео, т.е., по продолжительности видео, мы хотим, чтобы панель прогресса мы хотим показать, сколько видео, которое мы видели.
Для этого мы создадим функцию под названием HILLOTIMEUPDATE () Так что мы можем рассчитать, насколько мы видели видео с тем, что еще предстоит увидеть. После этого мы будем сохранить значения всех других свойств нашего государства, и мы будем обновлять только значение прогресса.
// @src/hooks/useVideoPlayer.js
import { useState, useEffect } from "react";
const useVideoPlayer = (videoElement) => {
const [playerState, setPlayerState] = useState({
isPlaying: false,
progress: 0,
speed: 1,
isMuted: false,
});
const togglePlay = () => {
setPlayerState({
...playerState,
isPlaying: !playerState.isPlaying,
});
};
useEffect(() => {
playerState.isPlaying
? videoElement.current.play()
: videoElement.current.pause();
}, [playerState.isPlaying, videoElement]);
const handleOnTimeUpdate = () => {
const progress = (videoElement.current.currentTime / videoElement.current.duration) * 100;
setPlayerState({
...playerState,
progress,
});
};
// ...
};
export default useVideoPlayer;
Одна из вещей, которые мы собираемся захотеть реализовать, – это возможность, чтобы мы могли перетащить панель прогресса, чтобы мы могли выбрать, где мы хотим просмотреть видео.
Таким образом, мы создадим функцию под названием рулявидеопрогресс () который будет иметь один аргумент, который в этом случае будет событием.
Затем мы преобразуем наше значение события из строки на номер. Это потому, что тогда мы хотим, чтобы тогда мы хотим рассказать наше видеоэлемент, что текущее время просмотра равно стоимости нашего ручного изменения. Наконец, мы просто сохраняем значения всех других свойств нашего государства, и мы обновляем только прогресс.
// @src/hooks/useVideoPlayer.js
import { useState, useEffect } from "react";
const useVideoPlayer = (videoElement) => {
const [playerState, setPlayerState] = useState({
isPlaying: false,
progress: 0,
speed: 1,
isMuted: false,
});
const togglePlay = () => {
setPlayerState({
...playerState,
isPlaying: !playerState.isPlaying,
});
};
useEffect(() => {
playerState.isPlaying
? videoElement.current.play()
: videoElement.current.pause();
}, [playerState.isPlaying, videoElement]);
const handleOnTimeUpdate = () => {
const progress = (videoElement.current.currentTime / videoElement.current.duration) * 100;
setPlayerState({
...playerState,
progress,
});
};
const handleVideoProgress = (event) => {
const manualChange = Number(event.target.value);
videoElement.current.currentTime = (videoElement.current.duration / 100) * manualChange;
setPlayerState({
...playerState,
progress: manualChange,
});
};
// ...
};
export default useVideoPlayer;
Еще одна особенность, которую мы захотят реализовать, – это скорость воспроизведения видео, это, потому что я считаю, что не каждый – это вентиляторы 1.0x, и что есть ребята, которые смотрят видео на 1.25X.
Для этого мы создадим функцию под названием handsideospeed () Это получит событие в качестве единого аргумента, то значение этого события будет преобразовано в число и, наконец, мы расскажем, что скорость воспроизведения равна значению события.
В нашем состоянии мы сохраняем значения всех свойств, кроме скорости.
// @src/hooks/useVideoPlayer.js
import { useState, useEffect } from "react";
const useVideoPlayer = (videoElement) => {
const [playerState, setPlayerState] = useState({
isPlaying: false,
progress: 0,
speed: 1,
isMuted: false,
});
const togglePlay = () => {
setPlayerState({
...playerState,
isPlaying: !playerState.isPlaying,
});
};
useEffect(() => {
playerState.isPlaying
? videoElement.current.play()
: videoElement.current.pause();
}, [playerState.isPlaying, videoElement]);
const handleOnTimeUpdate = () => {
const progress = (videoElement.current.currentTime / videoElement.current.duration) * 100;
setPlayerState({
...playerState,
progress,
});
};
const handleVideoProgress = (event) => {
const manualChange = Number(event.target.value);
videoElement.current.currentTime = (videoElement.current.duration / 100) * manualChange;
setPlayerState({
...playerState,
progress: manualChange,
});
};
const handleVideoSpeed = (event) => {
const speed = Number(event.target.value);
videoElement.current.playbackRate = speed;
setPlayerState({
...playerState,
speed,
});
};
// ...
};
export default useVideoPlayer;
Последняя функция, которую я хочу добавить, – это возможность отключить звук и включить видео. И как вы должны рассчитать логику очень похоже на воспроизведение/паузу.
// @src/hooks/useVideoPlayer.js
import { useState, useEffect } from "react";
const useVideoPlayer = (videoElement) => {
const [playerState, setPlayerState] = useState({
isPlaying: false,
progress: 0,
speed: 1,
isMuted: false,
});
const togglePlay = () => {
setPlayerState({
...playerState,
isPlaying: !playerState.isPlaying,
});
};
useEffect(() => {
playerState.isPlaying
? videoElement.current.play()
: videoElement.current.pause();
}, [playerState.isPlaying, videoElement]);
const handleOnTimeUpdate = () => {
const progress = (videoElement.current.currentTime / videoElement.current.duration) * 100;
setPlayerState({
...playerState,
progress,
});
};
const handleVideoProgress = (event) => {
const manualChange = Number(event.target.value);
videoElement.current.currentTime = (videoElement.current.duration / 100) * manualChange;
setPlayerState({
...playerState,
progress: manualChange,
});
};
const handleVideoSpeed = (event) => {
const speed = Number(event.target.value);
videoElement.current.playbackRate = speed;
setPlayerState({
...playerState,
speed,
});
};
const toggleMute = () => {
setPlayerState({
...playerState,
isMuted: !playerState.isMuted,
});
};
useEffect(() => {
playerState.isMuted
? (videoElement.current.muted = true)
: (videoElement.current.muted = false);
}, [playerState.isMuted, videoElement]);
// ...
};
export default useVideoPlayer;
Наконец, просто верните наше состояние и все функции, которые были созданы.
// @src/hooks/useVideoPlayer.js
import { useState, useEffect } from "react";
const useVideoPlayer = (videoElement) => {
const [playerState, setPlayerState] = useState({
isPlaying: false,
progress: 0,
speed: 1,
isMuted: false,
});
const togglePlay = () => {
setPlayerState({
...playerState,
isPlaying: !playerState.isPlaying,
});
};
useEffect(() => {
playerState.isPlaying
? videoElement.current.play()
: videoElement.current.pause();
}, [playerState.isPlaying, videoElement]);
const handleOnTimeUpdate = () => {
const progress = (videoElement.current.currentTime / videoElement.current.duration) * 100;
setPlayerState({
...playerState,
progress,
});
};
const handleVideoProgress = (event) => {
const manualChange = Number(event.target.value);
videoElement.current.currentTime = (videoElement.current.duration / 100) * manualChange;
setPlayerState({
...playerState,
progress: manualChange,
});
};
const handleVideoSpeed = (event) => {
const speed = Number(event.target.value);
videoElement.current.playbackRate = speed;
setPlayerState({
...playerState,
speed,
});
};
const toggleMute = () => {
setPlayerState({
...playerState,
isMuted: !playerState.isMuted,
});
};
useEffect(() => {
playerState.isMuted
? (videoElement.current.muted = true)
: (videoElement.current.muted = false);
}, [playerState.isMuted, videoElement]);
return {
playerState,
togglePlay,
handleOnTimeUpdate,
handleVideoProgress,
handleVideoSpeed,
toggleMute,
};
};
export default useVideoPlayer;
Теперь мы можем начать работать над нашим App.jsx Компонент и для записи используемая библиотека значка была Boxicons И типография была DM SANS Отказ
Сначала я дам код CSS нашего App.csss Отказ
body {
background: #EEEEEE;
}
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
h1 {
color: white;
}
video {
width: 100%;
}
.video-wrapper {
width: 100%;
max-width: 700px;
position: relative;
display: flex;
justify-content: center;
overflow: hidden;
border-radius: 10px;
}
.video-wrapper:hover .controls {
transform: translateY(0%);
}
.controls {
display: flex;
align-items: center;
justify-content: space-evenly;
position: absolute;
bottom: 30px;
padding: 14px;
width: 100%;
max-width: 500px;
flex-wrap: wrap;
background: rgba(255, 255, 255, 0.25);
box-shadow: 0 8px 32px 0 rgba(255, 255, 255, 0.1);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.18);
transform: translateY(150%);
transition: all 0.3s ease-in-out;
}
.actions button {
background: none;
border: none;
outline: none;
cursor: pointer;
}
.actions button i {
background-color: none;
color: white;
font-size: 30px;
}
input[type="range"] {
-webkit-appearance: none !important;
background: rgba(255, 255, 255, 0.2);
border-radius: 20px;
height: 4px;
width: 350px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none !important;
cursor: pointer;
height: 6px;
}
input[type="range"]::-moz-range-progress {
background: white;
}
.velocity {
appearance: none;
background: none;
color: white;
outline: none;
border: none;
text-align: center;
font-size: 16px;
}
.mute-btn {
background: none;
border: none;
outline: none;
cursor: pointer;
}
.mute-btn i {
background-color: none;
color: white;
font-size: 20px;
}
Теперь мы можем начать работать над нашим компонентом, и для этого мы импортируем все, что нам нужно, в этом случае это наш стиль, наше видео и наш крючком.
// @src/App.jsx
import React from "react";
import "./App.css";
import video from "./assets/video.mp4";
import useVideoPlayer from "./hooks/useVideoPlayer";
const App = () => {
// ...
};
export default App;
Тогда мы импортируем УСЭРЕФ () Крюк для создания ссылки на нашем лицементе. Так:
// @src/App.jsx
import React, { useRef } from "react";
import "./App.css";
import video from "./assets/video.mp4";
import useVideoPlayer from "./hooks/useVideoPlayer";
const App = () => {
const videoElement = useRef(null);
// ...
};
export default App;
Тогда мы можем получить нашу Playerstate и каждый из наших функций из нашего крючка. Так:
// @src/App.jsx
import React, { useRef } from "react";
import "./App.css";
import video from "./assets/video.mp4";
import useVideoPlayer from "./hooks/useVideoPlayer";
const App = () => {
const videoElement = useRef(null);
const {
playerState,
togglePlay,
handleOnTimeUpdate,
handleVideoProgress,
handleVideoSpeed,
toggleMute,
} = useVideoPlayer(videoElement);
// ...
};
export default App;
Теперь мы можем наконец начать работать над нашим шаблоном, таким образом мы начнем работать наш видеоэлемент, который будет иметь три реквизита, источник будет нашим видео, и мы все еще будем пройти нашу ссылку и нашу HILLOTIMEUPDATE () функция.
// @src/App.jsx
import React, { useRef } from "react";
import "./App.css";
import video from "./assets/video.mp4";
import useVideoPlayer from "./hooks/useVideoPlayer";
const App = () => {
const videoElement = useRef(null);
const {
playerState,
togglePlay,
handleOnTimeUpdate,
handleVideoProgress,
handleVideoSpeed,
toggleMute,
} = useVideoPlayer(videoElement);
return (
// ...
);
};
export default App;
Теперь мы можем начать работать над нашим видео управления, давайте начнем с кнопки PLAY и PAUSE. На что мы пройдем TOGGLEPLAY () Функция, и мы сделаем условный рендеринг, так что он показывает указанные значки в соответствии со значением ISPlaying свойству.
// @src/App.jsx
import React, { useRef } from "react";
import "./App.css";
import video from "./assets/video.mp4";
import useVideoPlayer from "./hooks/useVideoPlayer";
const App = () => {
const videoElement = useRef(null);
const {
playerState,
togglePlay,
handleOnTimeUpdate,
handleVideoProgress,
handleVideoSpeed,
toggleMute,
} = useVideoPlayer(videoElement);
return (
// ...
);
};
export default App;
Теперь мы можем начать с работы на нашем входе, который будет иметь тип диапазона, который будет иметь минимальное значение ноль и максимальное значение сто. Таким же образом мы передам рулявидеопрогресс () Функция и значение свойства прогресса.
// @src/App.jsx
import React, { useRef } from "react";
import "./App.css";
import video from "./assets/video.mp4";
import useVideoPlayer from "./hooks/useVideoPlayer";
const App = () => {
const videoElement = useRef(null);
const {
playerState,
togglePlay,
handleOnTimeUpdate,
handleVideoProgress,
handleVideoSpeed,
toggleMute,
} = useVideoPlayer(videoElement);
return (
handleVideoProgress(e)}
/>
// ...
);
};
export default App;
Теперь мы собираемся работать над элементом, чтобы выбрать нашу скорость воспроизведения видео. Для чего мы пройдем стоимость недвижимости скорости и handsideospeed () функция.
// @src/App.jsx
import React, { useRef } from "react";
import "./App.css";
import video from "./assets/video.mp4";
import useVideoPlayer from "./hooks/useVideoPlayer";
const App = () => {
const videoElement = useRef(null);
const {
playerState,
togglePlay,
handleOnTimeUpdate,
handleVideoProgress,
handleVideoSpeed,
toggleMute,
} = useVideoPlayer(videoElement);
return (
handleVideoProgress(e)}
/>
// ...
);
};
export default App;
Последнее, но не менее важное, у нас будет кнопка, которая будет нести ответственность за нему и включить видео. На что мы пройдем TOGGLEMUTE () Функция, и мы будем делать условный рендеринг, чтобы показать указанные значки в соответствии с ISMED имуществом.
// @src/App.jsx
import React, { useRef } from "react";
import "./App.css";
import video from "./assets/video.mp4";
import useVideoPlayer from "./hooks/useVideoPlayer";
const App = () => {
const videoElement = useRef(null);
const {
playerState,
togglePlay,
handleOnTimeUpdate,
handleVideoProgress,
handleVideoSpeed,
toggleMute,
} = useVideoPlayer(videoElement);
return (
handleVideoProgress(e)}
/>
);
};
export default App;
Конечный результат должен выглядеть так:
Заключение
Как всегда, я надеюсь, что вы нашли это интересно. Если вы заметили какие-либо ошибки в этой статье, пожалуйста, укажите их в комментариях. 🥳.
Надеюсь у тебя будет отличный день! 🙌.
Оригинал: “https://dev.to/franciscomendes10866/how-to-create-a-video-player-in-react-40jj”