Add react component example

This commit is contained in:
vdalex
2022-06-15 01:46:13 +03:00
parent 5183291661
commit f787db46ae
11 changed files with 249 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
# React Player Component
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm start
```
### Compiles and minifies for production
```
npm run build
```

View File

@@ -0,0 +1,34 @@
{
"name": "rtsp-to-web-react",
"version": "0.1.0",
"private": true,
"dependencies": {
"cra-template": "1.1.3",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-scripts": "^5.0.0",
"rtsptowebplayer": "github:vdalex25/rtsp-to-web-player#51832916615d9e6c72ae2962ebec35a5061eb775"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>RTSPtoWEBPlayerReact</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
import ReactPlayer from "./components/react-player/react-player";
import {useState} from "react";
import InputGroup from "./components/input-group";
const App = () => {
const [url, setUrl] = useState(null);
return (<div className="container mt-3">
<h3 className="text-center">Simple Example RTSPtoWEB player React</h3>
<div className="row">
<div className="col-12">
<InputGroup setUrl={setUrl}/>
</div>
<div className="col-12">
<div className="card">
<div className="card-header">
PLAYER
</div>
<div className="card-body p-0">
<ReactPlayer url={url}/>
</div>
</div>
</div>
</div>
</div>)
}
export default App;

View File

@@ -0,0 +1,15 @@
import {ReactComponent as PlayImg} from '../components/images/play.svg';
import {ReactComponent as PauseImg} from '../components/images/pause.svg';
const ControlButton = ({type, onClick}) => {
switch (type) {
case 'pause':
return (<span className="c-button" onClick={onClick}><PlayImg/></span>)
case 'play':
return (<span className="c-button" onClick={onClick}><PauseImg/></span>)
default:
return null;
}
}
export default ControlButton;

View File

@@ -0,0 +1,15 @@
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 499.233 499.233" style="enable-background:new 0 0 499.233 499.233;" xml:space="preserve">
<g fill="#fff">
<path d="M249.617,0C111.917,0,0,111.917,0,249.617s111.917,249.617,249.617,249.617s249.617-111.917,249.617-249.617
S387.317,0,249.617,0z M249.617,465.233c-119,0-215.617-96.617-215.617-215.617S130.617,34,249.617,34
s215.617,96.617,215.617,215.617S368.617,465.233,249.617,465.233z"/>
<path d="M192.667,139.117c-9.35,0-17,7.65-17,17v178.5c0,9.35,7.65,17,17,17c9.35,0,17-7.65,17-17v-178.5
C209.667,146.767,202.017,139.117,192.667,139.117z"/>
<path d="M308.833,139.117c-9.35,0-17,7.65-17,17v178.5c0,9.35,7.65,17,17,17s17-7.65,17-17v-178.5
C325.833,146.767,318.183,139.117,308.833,139.117z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 839 B

View File

@@ -0,0 +1,11 @@
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 499.233 499.233" style="enable-background:new 0 0 499.233 499.233;" xml:space="preserve">
<g fill="#fff">
<path d="M383.067,234.883l-203.15-117.3c-5.383-3.117-11.617-3.117-17,0c-5.383,3.117-8.5,8.783-8.5,14.733v234.317
c0,5.95,3.117,11.617,8.5,14.733c2.55,1.417,5.667,2.267,8.5,2.267c2.833,0,5.95-0.85,8.5-2.267l202.867-117.3
c5.383-3.117,8.5-8.783,8.5-14.733S388.167,238,383.067,234.883z M188.417,337.45V161.783l151.867,87.833L188.417,337.45z"/>
<path d="M249.617,0C111.917,0,0,111.917,0,249.617s111.917,249.617,249.617,249.617s249.617-111.917,249.617-249.617
S387.317,0,249.617,0z M249.617,465.233c-119,0-215.617-96.617-215.617-215.617S130.617,34,249.617,34
s215.617,96.617,215.617,215.617S368.617,465.233,249.617,465.233z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 866 B

View File

@@ -0,0 +1,28 @@
import {useState} from "react";
const InputGroup = ({setUrl}) => {
const [linkInput, setLinkInput] = useState('');
const onClickHandler = () => {
try {
new URL(linkInput);
} catch (e) {
console.warn("URL is not valid ")
return false;
}
setUrl(linkInput);
}
return (<div className="input-group mb-3">
<input type="text"
className="form-control"
placeholder="Type url link here"
value={linkInput}
onChange={(e) => {
setLinkInput(e.target.value);
}}/>
<button className="btn btn-outline-secondary" type="button" onClick={onClickHandler}>PLAY</button>
</div>)
}
export default InputGroup;

View File

@@ -0,0 +1,33 @@
.player-wrapper {
position: relative;
aspectRatio: '16/9';
}
.player-wrapper video {
margin-bottom: -6px;
}
.player-wrapper .control {
position: absolute;
bottom: 0;
width: 100%;
height: 50px;
padding: 10px;
}
.player-wrapper .control span {
width: 40px;
height: 40px;
cursor: pointer;
opacity: 0.7;
}
.player-wrapper .control span:hover {
opacity: 1;
}
.player-wrapper .control span svg {
width: 100%;
height: 100%;
}

View File

@@ -0,0 +1,48 @@
import {useEffect, useRef, useState} from "react";
import './react-player.css';
import RTSPtoWEBPlayer from "rtsptowebplayer";
import ControlButton from "../control-btn";
const ReactPlayer = ({url}) => {
const playerElement = useRef(null);
const [player, setPlayer] = useState(null);
const [state, setState] = useState('pause');
const stateListener = (e) => {
setState(e.type);
}
const playPause = () => {
if (player.video.src !== '') {
player.video.paused ? player.video.play() : player.video.pause();
}
}
useEffect(() => {
if (player === null) {
setPlayer(new RTSPtoWEBPlayer({
parentElement: playerElement.current, controls: false
}));
} else if (player.video.onpause === null && player.video.onplay === null) {
player.video.onpause = stateListener;
player.video.onplay = stateListener;
}
if (url !== null && player !== null) {
player.load(url);
}
return () => {
if (player !== null) {
player.destroy();
}
}
}, [url, player]);
return (<div className="player-wrapper">
<div ref={playerElement}/>
<div className="control">
<ControlButton type={state} onClick={playPause}/>
</div>
</div>)
}
export default ReactPlayer;

View File

@@ -0,0 +1,7 @@
import {createRoot} from "react-dom/client";
import App from "./App";
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App/>);