Commit 17ef21f7 authored by 刘梦焕's avatar 刘梦焕

feat: 视频组件新增云台控制

parent 3d110e83
import React from 'react';
import CloudPlate from './components/CloudPlate';
import style from './App.less';
// import pubsub from 'pubsub-js'
......@@ -15,6 +15,7 @@ class App extends React.Component {
this.state = {
isPlaying: false,
isShowControl: false,
};
}
createAll() {
......@@ -97,6 +98,9 @@ class App extends React.Component {
this.setState({
isPlaying: true,
});
this.jessibuca.on("start", () => {
this.appendControl()
})
}
}
......@@ -124,11 +128,36 @@ class App extends React.Component {
this.outTime = null;
}
}
appendControl() {
const parentElement = document.getElementsByClassName("jessibuca-controls-right")[0];
const childElement = document.createElement("div");
childElement.className = 'jessibuca-control';
const childChildElement = document.createElement("i");
childElement.addEventListener("click", () => {
// 点击 childElement 时触发的代码
this.setState({ isShowControl: !this.state.isShowControl });
});
// 将子元素添加到子元素的子元素中
parentElement.insertBefore(childElement, parentElement.firstChild);
childElement.appendChild(childChildElement);
}
closeCloudPlate() {
this.setState({
isShowControl: false,
})
}
renderCheckedArr() {
let { VideoInfo } = this.props;
const { isShowControl } = this.state;
return (
<div className={style.containerOut}>
{<div className={style.container} key={VideoInfo.id} ref={`myVideo` + VideoInfo.id}></div>}
{<div className={style.container} key={VideoInfo.id} ref={`myVideo` + VideoInfo.id}>
{isShowControl && <CloudPlate onClose={() => this.closeCloudPlate()} />}
</div>}
</div>
);
}
......
......@@ -15,5 +15,30 @@
height: 100%;
background: rgba(13, 14, 27, 0.7);
border: 1px solid transparent;
position: relative;
}
}
:global {
.jessibuca-control {
width: 36px;
height: 100%;
padding: 0 4px;
cursor: pointer;
i {
display: inline-block;
width: 100%;
height: 100%;
background: url('./assets/控制.svg') no-repeat;
background-size: 100% 100%;
}
&:hover {
i {
background: url('./assets/控制1.svg') no-repeat;
background-size: 100% 100%;
}
}
}
}
}
\ No newline at end of file
<svg id="VIDEO-438CBCED-9AE5-4BAC-8526-AE6C37F3A130-pantile-icon" class="theme-icon-item-icon" fill="#FFFFFF"
version="1.1" xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="-6 -6 32 32"
style="cursor: default; fill: rgb(191, 191, 192);">
<path
d="M10.2,7.8c1.6,0,2.9,1.3,2.9,2.9s-1.3,2.9-2.9,2.9s-2.9-1.3-2.9-2.9S8.5,7.8,10.2,7.8z M10.2,8.8c-1.1,0-1.9,0.9-1.9,1.9s0.9,1.9,1.9,1.9s1.9-0.9,1.9-1.9S11.2,8.8,10.2,8.8z">
</path>
<path
d="M8.8,3.5c0.7-0.6,1.8-0.6,2.5-0.1l0.1,0.1l1.4,1.1c0.2,0.2,0.3,0.5,0.1,0.7 c-0.2,0.2-0.4,0.2-0.6,0.1l-0.1,0l-1.4-1.1C10.5,3.9,10,3.9,9.6,4.2L9.4,4.3L8,5.4C7.8,5.5,7.5,5.5,7.3,5.3c-0.2-0.2-0.1-0.5,0-0.6 l0.1-0.1L8.8,3.5z">
</path>
<path
d="M2.5,12.3c-0.6-0.7-0.6-1.8-0.1-2.5l0.1-0.1l1.1-1.4c0.2-0.2,0.5-0.3,0.7-0.1 c0.2,0.2,0.2,0.4,0.1,0.6l0,0.1l-1.1,1.4C3,10.6,3,11.1,3.2,11.5l0.1,0.1L4.4,13c0.2,0.2,0.1,0.5-0.1,0.7c-0.2,0.2-0.5,0.1-0.6,0 l-0.1-0.1L2.5,12.3z">
</path>
<path
d="M17.7,12.3c0.6-0.7,0.6-1.8,0.1-2.5l-0.1-0.1l-1.1-1.4c-0.2-0.2-0.5-0.3-0.7-0.1 c-0.2,0.2-0.2,0.4-0.1,0.6l0,0.1l1.1,1.4c0.3,0.4,0.3,0.9,0.1,1.3l-0.1,0.1L15.8,13c-0.2,0.2-0.1,0.5,0.1,0.7c0.2,0.2,0.5,0.1,0.6,0 l0.1-0.1L17.7,12.3z">
</path>
<path
d="M8.8,18.2c0.7,0.6,1.8,0.6,2.5,0.1l0.1-0.1l1.4-1.1c0.2-0.2,0.3-0.5,0.1-0.7 c-0.2-0.2-0.4-0.2-0.6-0.1l-0.1,0l-1.4,1.1c-0.4,0.3-0.9,0.3-1.3,0.1l-0.1-0.1L8,16.3c-0.2-0.2-0.5-0.1-0.7,0.1 c-0.2,0.2-0.1,0.5,0,0.6l0.1,0.1L8.8,18.2z">
</path>
</svg>
\ No newline at end of file
<svg id="VIDEO-438CBCED-9AE5-4BAC-8526-AE6C37F3A130-pantile-icon" class="theme-icon-item-icon" fill="#FFFFFF"
version="1.1" xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="-6 -6 32 32"
style="cursor: default; fill: rgb(232, 232, 232);">
<path
d="M10.2,7.8c1.6,0,2.9,1.3,2.9,2.9s-1.3,2.9-2.9,2.9s-2.9-1.3-2.9-2.9S8.5,7.8,10.2,7.8z M10.2,8.8c-1.1,0-1.9,0.9-1.9,1.9s0.9,1.9,1.9,1.9s1.9-0.9,1.9-1.9S11.2,8.8,10.2,8.8z">
</path>
<path
d="M8.8,3.5c0.7-0.6,1.8-0.6,2.5-0.1l0.1,0.1l1.4,1.1c0.2,0.2,0.3,0.5,0.1,0.7 c-0.2,0.2-0.4,0.2-0.6,0.1l-0.1,0l-1.4-1.1C10.5,3.9,10,3.9,9.6,4.2L9.4,4.3L8,5.4C7.8,5.5,7.5,5.5,7.3,5.3c-0.2-0.2-0.1-0.5,0-0.6 l0.1-0.1L8.8,3.5z">
</path>
<path
d="M2.5,12.3c-0.6-0.7-0.6-1.8-0.1-2.5l0.1-0.1l1.1-1.4c0.2-0.2,0.5-0.3,0.7-0.1 c0.2,0.2,0.2,0.4,0.1,0.6l0,0.1l-1.1,1.4C3,10.6,3,11.1,3.2,11.5l0.1,0.1L4.4,13c0.2,0.2,0.1,0.5-0.1,0.7c-0.2,0.2-0.5,0.1-0.6,0 l-0.1-0.1L2.5,12.3z">
</path>
<path
d="M17.7,12.3c0.6-0.7,0.6-1.8,0.1-2.5l-0.1-0.1l-1.1-1.4c-0.2-0.2-0.5-0.3-0.7-0.1 c-0.2,0.2-0.2,0.4-0.1,0.6l0,0.1l1.1,1.4c0.3,0.4,0.3,0.9,0.1,1.3l-0.1,0.1L15.8,13c-0.2,0.2-0.1,0.5,0.1,0.7c0.2,0.2,0.5,0.1,0.6,0 l0.1-0.1L17.7,12.3z">
</path>
<path
d="M8.8,18.2c0.7,0.6,1.8,0.6,2.5,0.1l0.1-0.1l1.4-1.1c0.2-0.2,0.3-0.5,0.1-0.7 c-0.2-0.2-0.4-0.2-0.6-0.1l-0.1,0l-1.4,1.1c-0.4,0.3-0.9,0.3-1.3,0.1l-0.1-0.1L8,16.3c-0.2-0.2-0.5-0.1-0.7,0.1 c-0.2,0.2-0.1,0.5,0,0.6l0.1,0.1L8.8,18.2z">
</path>
</svg>
\ No newline at end of file
import React from 'react';
import { PlusOutlined, MinusOutlined, CloseOutlined } from '@ant-design/icons';
import classNames from 'classnames';
import styles from './CloudPlate.less';
const CloudPlate = (props) => {
const { onClose } = props;
const dotCount = 8; // 点的数量
const radius = 55; // 圆的半径
// 计算每个点的大致样式
const getDotStyle = (index) => {
const angle = (index * 360) / dotCount; // 计算点所在的角度
const radians = (angle * Math.PI) / 180; // 角度转换为弧度
const top = Math.sin(radians) * radius + radius - 8; // 计算点的垂直位置
const left = Math.cos(radians) * radius + radius - 8; // 计算点的水平位置
return { top, left };
};
// 0-上,1-下,2-左,3-右,4-左上,5-左下,6-右上,7-右下
// 3-右,7-右下,1-下,5-左下,2-左,4-左上,0-上,6-右上
const directionList = [3, 7, 1, 5, 2, 4, 0, 6];
const handleControl = (num) => {
// if(!videoList.length) return false;
// ezvizPtzMove({
// id: videoList[curVideoInd - 1].vmS_DeviceID,
// direction: num,
// siteCode: window.globalConfig.userInfo.LocalSite || window.globalConfig.userInfo.site,
// }).then((data) => {}).catch((err) => {})
};
return (
<div className={styles['cloud-plate']}>
<div className={styles['cloud-right']}>
<div className={styles['circle-container']}>
<div className={styles['block-container']}>
<div className={styles['block-icon-container']}></div>
</div>
<div className={styles.circleWrap}>
<div className={styles.lineWrap}>
<div className={classNames(styles['vertical-line'], styles['line'])} />
<div className={classNames(styles['horizontal-line'], styles['line'])} />
<div className={classNames(styles['diagonal-line-1'], styles['line'])} />
<div className={classNames(styles['diagonal-line-2'], styles['line'])} />
</div>
</div>
<div className={styles['circle']}>
{Array.from({ length: dotCount }).map((_, index) => (
<div
key={index}
className={classNames(styles['dot'], styles[`dot${index + 1}`])}
style={getDotStyle(index)}
onClick={() => {
handleControl(directionList[index]);
}}
/>
))}
</div>
</div>
<div className={styles['info-contianer']}>
<div className={styles['close-wrapper']} onClick={onClose}>
<CloseOutlined />
</div>
<div className={classNames(styles['operation-wrap'])}>
<div>变倍</div>
<div
className={styles['opera-btn']}
onClick={() => {
handleControl(8);
}}
>
<PlusOutlined />
</div>
<div
className={styles['opera-btn']}
onClick={() => {
handleControl(9);
}}
>
<MinusOutlined />
</div>
</div>
<div className={classNames(styles['operation-wrap'])}>
<div>聚焦</div>
<div
className={styles['opera-btn']}
onClick={() => {
handleControl(10);
}}
>
<PlusOutlined />
</div>
<div
className={styles['opera-btn']}
onClick={() => {
handleControl(11);
}}
>
<MinusOutlined />
</div>
</div>
<div className={classNames(styles['operation-wrap'])}>
<div>光圈</div>
<div
className={styles['opera-btn']}
onClick={() => {
handleControl(10);
}}
>
<PlusOutlined />
</div>
<div
className={styles['opera-btn']}
onClick={() => {
handleControl(11);
}}
>
<MinusOutlined />
</div>
</div>
</div>
</div>
</div>
);
};
export default CloudPlate;
.cloud-plate {
position: absolute;
bottom: 38px;
right: 0;
width: 278px;
height: 165px;
border-radius: 5px 0px 0px;
background: rgba(0, 0, 0, 0.75);
display: flex;
.cloud-right {
width: 100%;
height: 100%;
display: flex;
.circle-container {
display: flex;
align-items: center;
justify-content: center;
width: 50%;
height: 100%;
margin-left: 12px;
position: relative;
.block-container {
width: 80px;
height: 80px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #111f36;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
.block-icon-container {
width: 66%;
height: 66%;
border-radius: 50%;
background: #3177e9;
display: flex;
justify-content: center;
align-items: center;
}
}
.circleWrap {
width: 150px;
height: 150px;
border: 0.5px solid #5f5f5f;
position: absolute;
top: 8px;
left: -6px;
border-radius: 50%;
overflow: hidden;
.lineWrap {
width: 100%;
height: 100%;
position: relative;
.line {
position: absolute;
width: 0.5px;
height: 100%;
background-color: #5f5f5f;
transform-origin: center;
top: 0;
left: 50%;
}
.vertical-line {
transform: rotate(22deg);
}
.horizontal-line {
transform: rotate(67deg);
}
.diagonal-line-1 {
transform: rotate(112deg);
}
.diagonal-line-2 {
transform: rotate(157deg);
}
}
}
.circle {
position: relative;
width: 110px;
height: 110px;
// border: 4px solid #f0f0f0;
border-radius: 50%;
margin: 0 auto;
.dot {
position: absolute;
cursor: pointer;
}
.dot:hover {
scale: 1.2;
}
.dot1 {
width: 9px;
height: 17px;
background: url('../assets/右.png') center center no-repeat;
background-size: 100% 100%;
top: 46px !important;
left: 110px !important;
}
.dot2 {
width: 13px;
height: 14px;
top: 87px !important;
left: 89px !important;
background: url('../assets/右下.png') center center no-repeat;
background-size: 100% 100%;
}
.dot3 {
width: 17px;
height: 9px;
background: url('../assets/下.png') center center no-repeat;
background-size: 100% 100%;
top: 106px !important;
}
.dot4 {
width: 13px;
height: 14px;
background: url('../assets/左下.png') center center no-repeat;
background-size: 100% 100%;
}
.dot5 {
width: 9px;
height: 17px;
background: url('../assets/左.png') center center no-repeat;
background-size: 100% 100%;
top: 46.5px !important;
left: -9px !important;
}
.dot6 {
width: 13px;
height: 13px;
background: url('../assets/左上.png') center center no-repeat;
background-size: 100% 100%;
}
.dot7 {
width: 17px;
height: 9px;
background: url('../assets/上.png') center center no-repeat;
background-size: 100% 100%;
top: -11px !important;
}
.dot8 {
width: 13px;
height: 13px;
top: 9px !important;
left: 88px !important;
background: url('../assets/右上.png') center center no-repeat;
background-size: 100% 100%;
}
}
}
.info-contianer {
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
margin-left: 16px;
font-family: PingFang SC;
color: #ffffff;
font-weight: 500;
position: relative;
.close-wrapper {
position: absolute;
right: 10px;
top: 8px;
width: 21px;
height: 21px;
border-radius: 50%;
background: #474a4c;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
:global {
.anticon-close {
font-size: 14px;
color: #000000;
opacity: 0.6;
}
}
&:hover {
:global {
.anticon-close {
color: #ffffff;
}
}
}
}
.operation-wrap {
width: 100%;
height: 32px;
display: flex;
align-items: center;
justify-content: space-around;
cursor: pointer;
.opera-btn {
width: 24px;
height: 24px;
background: rgba(22, 133, 255, 0.3);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
&:hover {
background: #1685ff;
}
:global {
.anticon {
font-size: 15px;
font-weight: bold;
}
}
}
}
}
}
}
\ No newline at end of file
......@@ -38,13 +38,13 @@ const Demo1 = (props) => {
//};
let VideoParam = {
id: '9745259F-76B5-4ECB-BDD7-8B1B2C5C84CD',
name: '3L00AE9PAJ00034',
protocol: '乐橙云HTTP-FLV',
username: 'lc0f4b952c86c34c4b',
password: 'dfdcae9267bf4964ae09998e16f016',
pandavmsHost: 'ws://192.168.12.154:8080/',
address: '3L00AE9PAJ00034',
id: 'B1C0D641-81B2-494C-ADAF-7240B9B69F47',
name: '登科华府_通道_4',
protocol: '萤石云HTTP-FLV',
username: '6c44c8e92d1c4d75a9818756025df550',
password: '8b7dc88f9f4bf19c2b1aabfdd995244',
pandavmsHost: 'ws://192.168.10.182:7000/',
address: 'D36342925',
};
/*{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment