Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wisdom-components
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ReactWeb5
wisdom-components
Commits
a0b118cc
Commit
a0b118cc
authored
Jan 03, 2024
by
李纪文
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 增加vms视频回放
parent
d84fc0f8
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
1027 additions
and
1 deletion
+1027
-1
VmsVideo.md
packages/base-components/VmsVideo/src/VmsVideo.md
+6
-0
index.js
packages/base-components/VmsVideo/src/apis/index.js
+25
-0
dmeo2.tsx
packages/base-components/VmsVideo/src/demos/dmeo2.tsx
+135
-0
index.jsx
packages/base-components/VmsVideo/src/index.jsx
+1
-1
get-size.js
...e-components/VmsVideo/src/recVideo/TimeSlider/get-size.js
+33
-0
index.js
...base-components/VmsVideo/src/recVideo/TimeSlider/index.js
+564
-0
responsiveCanvas.js
...ents/VmsVideo/src/recVideo/TimeSlider/responsiveCanvas.js
+69
-0
index.js
packages/base-components/VmsVideo/src/recVideo/index.js
+156
-0
index.less
packages/base-components/VmsVideo/src/recVideo/index.less
+38
-0
No files found.
packages/base-components/VmsVideo/src/VmsVideo.md
View file @
a0b118cc
...
@@ -15,8 +15,14 @@ group:
...
@@ -15,8 +15,14 @@ group:
**需安装的依赖项: ezuikit-js axios (1.npm i ezuikit-js 2.npm i axios)**
**需安装的依赖项: ezuikit-js axios (1.npm i ezuikit-js 2.npm i axios)**
### 视频
<code
src=
"./demos/dmeo1.tsx"
>
<code
src=
"./demos/dmeo1.tsx"
>
### 视频回放
<code
src=
"./demos/dmeo2.tsx"
>
## 参数说明
## 参数说明
| JessibucaObj 常用参数(对萤石 EZOPEN 协议不生效) | 说明 | 类型 | 默认值 |
| JessibucaObj 常用参数(对萤石 EZOPEN 协议不生效) | 说明 | 类型 | 默认值 |
...
...
packages/base-components/VmsVideo/src/apis/index.js
0 → 100644
View file @
a0b118cc
import
{
request
}
from
'@wisdom-utils/utils'
;
const
REQUEST_METHOD_GET
=
'get'
;
const
REQUEST_METHOD_POST
=
'post'
;
// eslint-disable-next-line no-undef
const
baseURI
=
typeof
DUMI_TYPE
!==
'undefined'
&&
DUMI_TYPE
===
'dumi'
?
'/api'
:
''
;
const
CommonPath
=
window
?.
globalConfig
?.
hasGateWay
?
'/PandaCore/GateWay'
:
''
;
// 录像回放
export
function
videoPlayback
(
params
)
{
return
request
({
url
:
`
${
baseURI
}${
CommonPath
}
/pandavms/camera/playback`
,
method
:
REQUEST_METHOD_GET
,
params
,
});
}
// 根据时间轴时间选定 查看历史视频
export
function
newPlayback
(
params
)
{
return
request
({
url
:
`
${
baseURI
}${
CommonPath
}
/pandavms/camera/newpalyback`
,
method
:
REQUEST_METHOD_GET
,
params
,
});
}
packages/base-components/VmsVideo/src/demos/dmeo2.tsx
0 → 100644
View file @
a0b118cc
import
React
,
{
useRef
,
useEffect
,
useState
}
from
'react'
;
import
Video
from
'../recVideo'
;
const
Demo2
=
(
props
)
=>
{
const
jessibuca
=
useRef
(
null
);
let
JessibucaObj
=
{
operateBtns
:
{
// fullscreen: false,
screenshot
:
false
,
},
loadingText
:
'演示视频加载中'
,
decoder
:
'/JessibucaVideo/decoder.js'
,
};
// 若是在子应用中,则需加上子应用名称,且兼容基座
// 如下:
// let _url = '/civ_energy/JessibucaVideo/decoder.js'
// let JessibucaObj = {
// decoder: window.__POWERED_BY_QIANKUN__ ? '/civbase' + _url : _url
// }
// let VideoInfo = {
// key: '123638446', //'1CEB209F-8BC7-44B5-9F6B-3D8FCB855E76',
// dataRate: `/2`,
// fullUrl: 'ws://172.16.19.19:8080/jessica/1CEB209F-8BC7-44B5-9F6B-3D8FCB855E76',
// useFullUrl: true,
// cameraName: `摄像头s8`,
// appKey: '6c44c8e92d1c4d75a9818756025df550',
// appSecret: '78b7dc88f9f4bf19c2b1aabfdd995244',
// protocol: '萤石EZOPEN',
//};
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'
,
};
VideoParam
=
{
channel
:
'2'
,
// dataRate: 'Sub', // Main 主码流 Sub 子码流
name
:
'RTSP银河湾五期_通道_2'
,
id
:
'46D6E990-8049-4A61-B592-8503BDFAA07A'
,
username
:
'admin'
,
password
:
'zls_1234@abcd'
,
address
:
'172.16.19.2'
,
protocol
:
'RTSP'
,
pandavmsHost
:
'ws://192.168.8.30:7000/'
,
// pandavms后端主机地址 eg: ws://172.16.19.19:8080/
hoursRuler
:
48
,
beginTime
:
'2024-01-01 00:00:00'
,
// 回放开始时间
endTime
:
'2024-01-02 23:59:59'
,
// 回放结束时间
};
const
[
VideoInfo
,
setVideoInfo
]
=
useState
(
VideoParam
);
useEffect
(()
=>
{
// 事件 ,返回视频信息
jessibuca
&&
jessibuca
.
current
&&
jessibuca
.
current
.
on
(
'videoInfo'
,
function
(
data
)
{
console
.
log
(
'width:'
,
data
.
width
,
'height:'
,
data
.
width
);
});
// 事件 ,播放视频之后的回调
jessibuca
&&
jessibuca
.
current
&&
jessibuca
.
current
.
on
(
'play'
,
function
(
data
)
{
console
.
log
(
'play:'
,
jessibuca
);
});
// 事件 ,暂停视频之后的回调
jessibuca
&&
jessibuca
.
current
&&
jessibuca
.
current
.
on
(
'pause'
,
function
(
data
)
{
console
.
log
(
'pause:'
,
data
);
});
// ******
// 其他事件需查看在线文档
// ******
return
()
=>
{
console
.
log
(
'销毁。。。。。。。。。。。。。。。。。。。。。。。。。'
);
stopVideo
();
};
},
[]);
const
stopVideo
=
()
=>
{
jessibuca
&&
jessibuca
.
current
&&
jessibuca
.
current
.
pause
&&
jessibuca
.
current
.
pause
();
};
const
startVideo
=
()
=>
{
if
(
jessibuca
&&
jessibuca
.
current
)
{
jessibuca
.
current
.
play
();
// console.log(jessibuca.current.isPlaying());
}
};
const
testVideo
=
()
=>
{
// console.log(jessibuca.current.isPlaying());
setVideoInfo
({
channel
:
'2'
,
// dataRate: 'Sub', // Main 主码流 Sub 子码流
name
:
'RTSP银河湾五期_通道_2'
,
id
:
'46D6E990-8049-4A61-B592-8503BDFAA07A'
,
username
:
'admin'
,
password
:
'zls_1234@abcd'
,
address
:
'172.16.19.2'
,
protocol
:
'RTSP'
,
pandavmsHost
:
'ws://192.168.8.30:7000/'
,
// pandavms后端主机地址 eg: ws://172.16.19.19:8080/
hoursRuler
:
24
,
beginTime
:
'2024-01-01 00:00:00'
,
endTime
:
'2024-01-01 23:59:59'
,
});
};
const
destroyVideo
=
()
=>
{
if
(
VideoParam
.
protocol
!=
'萤石EZOPEN'
)
jessibuca
&&
jessibuca
.
current
&&
jessibuca
.
current
.
destroy
();
};
return
(
<
div
>
<
button
onClick=
{
stopVideo
}
>
暂停
</
button
>
<
button
onClick=
{
startVideo
}
>
开始
</
button
>
<
button
onClick=
{
testVideo
}
>
测试
</
button
>
<
button
onClick=
{
destroyVideo
}
>
销毁
</
button
>
<
div
style=
{
{
height
:
'700px'
}
}
>
<
Video
{
...
{
JessibucaObj
:
JessibucaObj
,
VideoInfo
:
VideoInfo
}}
ref=
{
jessibuca
}
/>
</
div
>
</
div
>
);
};
export
default
Demo2
;
packages/base-components/VmsVideo/src/index.jsx
View file @
a0b118cc
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
*/
// eslint-disable-next-line no-unused-vars
// eslint-disable-next-line no-unused-vars
import
EZUIKit
,
{
log
}
from
'
./ezuikit-js/ezuikit
'
;
import
EZUIKit
,
{
log
}
from
'
ezuikit-js
'
;
import
axios
from
'axios'
;
import
axios
from
'axios'
;
import
React
,
{
import
React
,
{
...
...
packages/base-components/VmsVideo/src/recVideo/TimeSlider/get-size.js
0 → 100644
View file @
a0b118cc
const
parseNumber
=
(
prop
)
=>
parseFloat
(
prop
)
||
0
;
const
getSize
=
(
el
)
=>
{
if
(
el
===
window
||
el
===
document
.
body
)
{
return
[
window
.
innerWidth
,
window
.
innerHeight
];
}
let
temporary
=
false
;
if
(
!
el
.
parentNode
&&
document
.
body
)
{
temporary
=
true
;
document
.
body
.
appendChild
(
el
);
}
const
rect
=
el
.
getBoundingClientRect
();
const
styles
=
getComputedStyle
(
el
);
const
height
=
(
rect
.
height
|
0
)
+
parseNumber
(
styles
.
getPropertyValue
(
'margin-top'
))
+
parseNumber
(
styles
.
getPropertyValue
(
'margin-bottom'
));
const
width
=
(
rect
.
width
|
0
)
+
parseNumber
(
styles
.
getPropertyValue
(
'margin-left'
))
+
parseNumber
(
styles
.
getPropertyValue
(
'margin-right'
));
if
(
temporary
&&
document
.
body
)
{
document
.
body
.
removeChild
(
el
);
}
return
[
width
,
height
];
};
export
default
getSize
;
packages/base-components/VmsVideo/src/recVideo/TimeSlider/index.js
0 → 100644
View file @
a0b118cc
import
React
from
'react'
;
import
moment
from
'moment'
;
import
RvResponsiveCanvas
from
'./responsiveCanvas'
;
export
default
class
TimeSlider
extends
React
.
Component
{
constructor
(
props
)
{
super
(
props
);
//const that = this;
this
.
state
=
{
minTimestamp
:
this
.
props
.
minTimestamp
,
maxTimestamp
:
this
.
props
.
maxTimestamp
,
playTimestamp
:
this
.
props
.
playTimestamp
,
timecell
:
this
.
props
.
timecell
,
hoursPerRuler
:
this
.
props
.
hoursPerRuler
,
};
this
.
redrawFlag
=
false
;
}
componentDidMount
()
{
setTimeout
(()
=>
{
this
.
initCanval
(
false
);
},
100
);
}
componentDidUpdate
()
{
this
.
initCanval
(
true
);
}
static
getDerivedStateFromProps
(
nextProps
,
prevState
)
{
const
{
maxTimestamp
,
minTimestamp
,
playTimestamp
,
timecell
}
=
nextProps
;
// 当传入的type发生变化的时候,更新state
if
(
maxTimestamp
!==
prevState
.
maxTimestamp
||
minTimestamp
!==
prevState
.
minTimestamp
||
playTimestamp
!==
prevState
.
playTimestamp
||
timecell
!==
prevState
.
timecell
)
{
return
{
minTimestamp
,
maxTimestamp
,
playTimestamp
,
timecell
,
};
}
// 否则,对于state不进行任何操作
return
null
;
}
initCanval
=
()
=>
{
if
(
!
this
.
redrawFlag
)
{
this
.
ctx
=
this
.
canvas
.
getContext
(
'2d'
);
this
.
minutesPerStep
=
[
1
,
2
,
5
,
10
,
15
,
20
,
30
,
60
,
120
,
180
,
240
,
360
,
720
,
1440
];
// min/格
this
.
graduationStep
=
20
;
//刻度间最小宽度,单位px
this
.
hoursPerRuler
=
this
.
state
.
hoursPerRuler
||
24
;
//时间轴显示24小时
this
.
startTimestamp
=
moment
().
startOf
(
'day'
).
valueOf
();
this
.
distanceBetweenGtitle
=
80
;
this
.
zoom
=
24
;
this
.
gIsMouseout
=
false
;
//拖动mousedown标记
this
.
gIsMousewheel
=
false
;
//拖动mousedown标记
this
.
gIsMousedown
=
false
;
//拖动mousedown标记
this
.
gIsMousemove
=
false
;
//拖动mousemove标记
this
.
gMousedownCursor
=
null
;
//拖动mousedown的位置
this
.
gIsDragStartTime
=
null
;
this
.
hoverTooltip
=
null
;
}
this
.
canvansW
=
this
.
canvas
.
width
;
this
.
canVansH
=
this
.
canvas
.
height
;
if
(
this
.
gIsMousewheel
||
this
.
gIsMousedown
||
this
.
gIsMousemove
)
return
;
this
.
timecell
=
this
.
state
.
timecell
;
this
.
maxTimestamp
=
this
.
state
.
maxTimestamp
;
this
.
minTimestamp
=
this
.
state
.
minTimestamp
;
this
.
playTimestamp
=
this
.
state
.
playTimestamp
;
this
.
onBeforeClickRulerCallback
=
null
;
if
(
this
.
redrawFlag
)
{
this
.
clearCanvas
();
}
this
.
init
(
this
.
startTimestamp
,
this
.
playTimestamp
,
this
.
hoverTooltip
,
this
.
timecell
,
this
.
redrawFlag
,
);
this
.
redrawFlag
=
true
;
};
/**
* 初始化
*
* @param {any} startTimestamp 最左侧时间
* @param {any} timecell 录像段数组
* @param {any} redrawFlag 是否重绘标记
*/
init
=
(
startTimestamp
,
playTimestamp
,
hoverTooltip
,
timecell
,
redrawFlag
)
=>
{
if
(
startTimestamp
<
this
.
minTimestamp
)
{
// eslint-disable-next-line no-param-reassign
startTimestamp
=
this
.
minTimestamp
;
}
const
startEndX
=
this
.
hoursPerRuler
*
60
*
60
*
1000
;
const
end_timestramp
=
startTimestamp
+
startEndX
;
if
(
end_timestramp
>
this
.
maxTimestamp
)
{
// eslint-disable-next-line no-param-reassign
startTimestamp
=
this
.
maxTimestamp
-
startEndX
;
}
this
.
timecell
=
timecell
;
this
.
startTimestamp
=
startTimestamp
;
this
.
playTimestamp
=
playTimestamp
;
this
.
drawCellBg
();
this
.
addGraduations
(
startTimestamp
);
this
.
addCells
(
timecell
);
this
.
drawLine
(
0
,
this
.
canVansH
,
this
.
canvansW
,
this
.
canVansH
,
'rgb(255, 255, 255)'
,
1
);
//底线
var
px_per_ms
=
this
.
canvansW
/
startEndX
;
var
pos_x
=
(
playTimestamp
-
this
.
startTimestamp
)
*
px_per_ms
;
this
.
drawLine
(
pos_x
,
0
,
pos_x
,
33
,
'#E8B700'
,
2
);
//中间播放点时间线
if
(
!
redrawFlag
)
{
//只有第一次进入才需要添加事件
this
.
addEvents
();
}
var
time
=
startTimestamp
+
(
this
.
hoursPerRuler
*
3600
*
1000
)
/
2
;
this
.
ctx
.
fillStyle
=
'#E8B700'
;
var
_pos_x
=
pos_x
-
60
;
if
(
this
.
canvansW
<
pos_x
+
60
)
{
_pos_x
=
this
.
canvansW
-
110
;
}
else
if
(
pos_x
<
60
)
{
_pos_x
=
0
;
}
this
.
ctx
.
font
=
'15px Arial'
;
this
.
ctx
.
fillText
(
this
.
formatTime
(
playTimestamp
),
_pos_x
,
53
);
if
(
this
.
hoverTooltip
)
{
this
.
drawLine
(
this
.
hoverTooltip
.
linePos
,
0
,
this
.
hoverTooltip
.
linePos
,
50
,
'rgba(232,183,0,0.7)'
,
1
,
);
this
.
ctx
.
fillStyle
=
'rgba(232,183,0,0.7)'
;
var
_pos_x
=
this
.
hoverTooltip
.
linePos
-
50
;
if
(
this
.
canvansW
<
this
.
hoverTooltip
.
linePos
+
50
)
{
_pos_x
=
this
.
canvansW
-
100
;
}
else
if
(
this
.
hoverTooltip
.
linePos
<
50
)
{
_pos_x
=
0
;
}
this
.
ctx
.
font
=
'14px Arial'
;
this
.
ctx
.
fillText
(
this
.
formatTime
(
this
.
hoverTooltip
.
time
),
_pos_x
,
70
);
}
};
/**
* 绘制添加刻度
*
* @param {any} startTimestamp 最左侧时间
*/
addGraduations
=
(
startTimestamp
)
=>
{
var
_this
=
this
;
var
px_per_min
=
_this
.
canvansW
/
(
_this
.
hoursPerRuler
*
60
);
// px/min
var
px_per_ms
=
_this
.
canvansW
/
(
_this
.
hoursPerRuler
*
60
*
60
*
1000
);
// px/ms
var
px_per_step
=
_this
.
graduationStep
;
// px/格 默认最小值20px
var
min_per_step
=
px_per_step
/
px_per_min
;
// min/格
for
(
var
i
=
0
;
i
<
_this
.
minutesPerStep
.
length
;
i
++
)
{
if
(
min_per_step
<=
_this
.
minutesPerStep
[
i
])
{
//让每格时间在minutes_per_step规定的范围内
min_per_step
=
_this
.
minutesPerStep
[
i
];
px_per_step
=
px_per_min
*
min_per_step
;
break
;
}
}
var
medium_step
=
30
;
for
(
var
i
=
0
;
i
<
_this
.
minutesPerStep
.
length
;
i
++
)
{
if
(
_this
.
distanceBetweenGtitle
/
px_per_min
<=
_this
.
minutesPerStep
[
i
])
{
medium_step
=
_this
.
minutesPerStep
[
i
];
break
;
}
}
var
num_steps
=
_this
.
canvansW
/
px_per_step
;
//总格数
var
graduation_left
;
var
graduation_time
;
var
caret_class
;
var
lineH
;
var
ms_offset
=
_this
.
msToNextStep
(
startTimestamp
,
min_per_step
*
60
*
1000
);
//开始的偏移时间 ms
var
px_offset
=
ms_offset
*
px_per_ms
;
//开始的偏移距离 px
var
ms_per_step
=
px_per_step
/
px_per_ms
;
// ms/step
for
(
var
i
=
0
;
i
<
num_steps
;
i
++
)
{
graduation_left
=
px_offset
+
i
*
px_per_step
;
// 距离=开始的偏移距离+格数*px/格
graduation_time
=
startTimestamp
+
ms_offset
+
i
*
ms_per_step
;
//时间=左侧开始时间+偏移时间+格数*ms/格
var
date
=
new
Date
(
graduation_time
);
if
(
date
.
getUTCHours
()
==
0
&&
date
.
getUTCMinutes
()
==
0
)
{
caret_class
=
'big'
;
lineH
=
25
;
var
big_date
=
_this
.
graduationTitle
(
date
);
_this
.
ctx
.
font
=
'12px Arial'
;
_this
.
ctx
.
fillText
(
big_date
,
graduation_left
-
20
,
30
);
_this
.
ctx
.
fillStyle
=
'rgba(255,255,255,0.55)'
;
//不改
}
else
if
((
graduation_time
/
(
60
*
1000
))
%
medium_step
==
0
)
{
caret_class
=
'middle'
;
lineH
=
15
;
var
middle_date
=
_this
.
graduationTitle
(
date
);
_this
.
ctx
.
font
=
'12px Arial'
;
_this
.
ctx
.
fillText
(
middle_date
,
graduation_left
-
20
,
30
);
_this
.
ctx
.
fillStyle
=
'rgba(255,255,255,0.7)'
;
}
else
{
lineH
=
10
;
}
// 不能播放视频的时间刻度--灰色 ok
_this
.
drawLine
(
graduation_left
,
0
,
graduation_left
,
lineH
,
'rgba(151,158,167,1)'
,
1
);
}
};
/**
* 绘制线
*
* @param {any} beginX
* @param {any} beginY
* @param {any} endX
* @param {any} endY
* @param {any} color
* @param {any} width
*/
drawLine
=
(
beginX
,
beginY
,
endX
,
endY
,
color
,
width
)
=>
{
this
.
ctx
.
beginPath
();
this
.
ctx
.
moveTo
(
beginX
,
beginY
);
this
.
ctx
.
lineTo
(
endX
,
endY
);
this
.
ctx
.
strokeStyle
=
color
;
this
.
ctx
.
lineWidth
=
width
;
this
.
ctx
.
stroke
();
};
/**
* 添加录像段
*
* @param {any} cells 录像数组
*/
addCells
=
(
cells
)
=>
{
var
_this
=
this
;
cells
.
forEach
((
cell
)
=>
{
_this
.
drawCell
(
cell
);
});
};
/**
* 绘制录像块
*
* @param {any} cell Cell包括beginTime ms;endTime ms;style
*/
drawCell
=
(
cell
)
=>
{
var
_this
=
this
;
var
px_per_ms
=
_this
.
canvansW
/
(
_this
.
hoursPerRuler
*
60
*
60
*
1000
);
// px/ms
var
beginX
=
(
cell
.
beginTime
-
_this
.
startTimestamp
)
*
px_per_ms
;
var
cell_width
=
(
cell
.
endTime
-
cell
.
beginTime
)
*
px_per_ms
;
_this
.
ctx
.
fillStyle
=
cell
.
style
.
background
;
_this
.
ctx
.
fillRect
(
beginX
,
0
,
cell_width
,
15
);
};
/** 绘制录像块背景 */
drawCellBg
=
()
=>
{
this
.
ctx
.
fillStyle
=
'rgb(255,255,255)'
;
this
.
ctx
.
fillRect
(
0
,
0
,
this
.
canvansW
,
15
);
};
/** 时间轴事件 */
addEvents
=
()
=>
{
var
_this
=
this
;
if
(
_this
.
canvas
.
addEventListener
)
{
_this
.
canvas
.
addEventListener
(
'mousewheel'
,
_this
.
mousewheelFunc
.
bind
(
_this
));
_this
.
canvas
.
addEventListener
(
'mousedown'
,
_this
.
mousedownFunc
.
bind
(
_this
));
_this
.
canvas
.
addEventListener
(
'mousemove'
,
_this
.
mousemoveFunc
.
bind
(
_this
));
_this
.
canvas
.
addEventListener
(
'mouseup'
,
_this
.
mouseupFunc
.
bind
(
_this
));
_this
.
canvas
.
addEventListener
(
'mouseout'
,
_this
.
mouseoutFunc
.
bind
(
_this
));
}
};
/** 拖动/点击 mousedown事件 */
mousedownFunc
=
(
e
)
=>
{
this
.
gIsMousedown
=
true
;
this
.
gMousedownCursor
=
this
.
getCursorXPosition
(
e
);
//记住mousedown的位置
this
.
gIsDragStartTime
=
moment
();
};
/** 拖动/鼠标hover显示 mousemove事件 */
mousemoveFunc
=
(
e
)
=>
{
var
_this
=
this
;
_this
.
hoverTooltip
=
null
;
var
pos_x
=
_this
.
getCursorXPosition
(
e
);
var
px_per_ms
=
_this
.
canvansW
/
(
_this
.
hoursPerRuler
*
60
*
60
*
1000
);
// px/ms
_this
.
clearCanvas
();
if
(
_this
.
gIsMousedown
)
{
var
diff_x
=
pos_x
-
_this
.
gMousedownCursor
;
_this
.
startTimestamp
=
_this
.
startTimestamp
-
Math
.
round
(
diff_x
/
px_per_ms
);
_this
.
init
(
_this
.
startTimestamp
,
_this
.
playTimestamp
,
_this
.
hoverTooltip
,
_this
.
timecell
,
true
,
);
_this
.
gIsMousemove
=
true
;
_this
.
gMousedownCursor
=
pos_x
;
}
else
{
var
time
=
_this
.
startTimestamp
+
pos_x
/
px_per_ms
;
_this
.
hoverTooltip
=
{
linePos
:
pos_x
,
time
:
time
,
};
_this
.
init
(
_this
.
startTimestamp
,
_this
.
playTimestamp
,
_this
.
hoverTooltip
,
_this
.
timecell
,
true
,
);
}
};
/** 拖动/点击 mouseup事件 */
mouseupFunc
=
(
e
)
=>
{
var
_this
=
this
;
//避免点击被误认为拖拽
const
dragTimeLen
=
moment
().
diff
(
this
.
gIsDragStartTime
);
if
(
dragTimeLen
<
100
)
{
_this
.
gIsMousemove
=
false
;
_this
.
gIsMousedown
=
false
;
}
if
(
_this
.
gIsMousemove
)
{
//拖动 事件
_this
.
gIsMousemove
=
false
;
_this
.
gIsMousedown
=
false
;
//_this.playTimestamp = _this.startTimestamp + (_this.hoursPerRuler * 3600 * 1000) / 2;
}
else
{
// click 事件
_this
.
gIsMousedown
=
false
;
var
posx
=
_this
.
getCursorXPosition
(
e
);
//鼠标距离 px
var
ms_per_px
=
(
_this
.
zoom
*
3600
*
1000
)
/
_this
.
canvansW
;
// ms/px
_this
.
playTimestamp
=
_this
.
startTimestamp
+
posx
*
ms_per_px
;
_this
.
setPlaytimestamp
(
_this
.
playTimestamp
);
_this
.
playTimestampChange
();
}
};
/**
* 鼠标移出隐藏时间 mouseout事件
*
* @param {any} e
*/
mouseoutFunc
=
()
=>
{
var
_this
=
this
;
_this
.
gIsMouseout
=
true
;
_this
.
clearCanvas
();
_this
.
hoverTooltip
=
null
;
_this
.
init
(
_this
.
startTimestamp
,
_this
.
playTimestamp
,
_this
.
hoverTooltip
,
_this
.
timecell
,
true
);
_this
.
gIsMouseout
=
false
;
};
/** 滚轮放大缩小,以时间轴中心为准 mousewheel事件 */
mousewheelFunc
=
(
event
)
=>
{
var
_this
=
this
;
_this
.
gIsMousewheel
=
true
;
if
(
event
&&
event
.
preventDefault
)
{
event
.
preventDefault
();
}
else
{
window
.
event
.
returnValue
=
false
;
return
false
;
}
var
e
=
window
.
event
||
event
;
var
delta
=
Math
.
max
(
-
1
,
Math
.
min
(
1
,
e
.
wheelDelta
||
-
e
.
detail
));
var
pos_x
=
_this
.
getCursorXPosition
(
e
);
var
px_per_ms
=
_this
.
canvansW
/
(
_this
.
hoursPerRuler
*
60
*
60
*
1000
);
var
eventPositionTime
=
_this
.
startTimestamp
+
pos_x
/
px_per_ms
;
//m
// s 记住当前中间的时间
//var middle_time = _this.startTimestamp + (_this.hoursPerRuler * 3600 * 1000) / 2; //ms 记住当前中间的时间
if
(
delta
<
0
)
{
_this
.
zoom
=
_this
.
zoom
+
4
;
if
(
_this
.
zoom
>=
24
)
{
_this
.
zoom
=
24
;
//放大最大24小时
}
_this
.
hoursPerRuler
=
_this
.
zoom
;
}
else
if
(
delta
>
0
)
{
// 放大
_this
.
zoom
=
_this
.
zoom
-
4
;
if
(
_this
.
zoom
<=
1
)
{
_this
.
zoom
=
1
;
//缩小最小1小时
}
_this
.
hoursPerRuler
=
_this
.
zoom
;
}
_this
.
clearCanvas
();
var
px_per_ms2
=
_this
.
canvansW
/
(
_this
.
hoursPerRuler
*
60
*
60
*
1000
);
_this
.
startTimestamp
=
eventPositionTime
-
pos_x
/
px_per_ms2
;
//_this.startTimestamp = middle_time - (_this.hoursPerRuler * 3600 * 1000) / 2; //startTimestamp = 当前中间的时间 - zoom/2
_this
.
init
(
_this
.
startTimestamp
,
_this
.
playTimestamp
,
_this
.
hoverTooltip
,
_this
.
timecell
,
true
);
_this
.
gIsMousewheel
=
false
;
};
/**
* 获取鼠标posx
*
* @param {any} e
*/
getCursorXPosition
=
(
e
)
=>
{
var
posx
=
0
;
if
(
!
e
)
{
// eslint-disable-next-line no-param-reassign
e
=
window
.
event
;
}
/*if (e.pageX || e.pageY) {
posx = e.pageX;
}else if (e.clientX || e.clientY) {
posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
}*/
posx
=
e
.
offsetX
;
return
posx
;
};
/**
* 返回时间轴上刻度的时间
*
* @param {any} datetime New Date 格式
*/
graduationTitle
=
(
datetime
)
=>
{
if
(
datetime
.
getHours
()
==
0
&&
datetime
.
getMinutes
()
==
0
&&
datetime
.
getMilliseconds
()
==
0
)
{
/* return ('0' + datetime.getDate().toString()).substr(-2) + '.' +
('0' + (datetime.getMonth() + 1).toString()).substr(-2) + '.' +
datetime.getFullYear();*/
return
(
datetime
.
getFullYear
()
+
'-'
+
(
'0'
+
(
datetime
.
getMonth
()
+
1
).
toString
()).
substr
(
-
2
)
+
'-'
+
(
'0'
+
datetime
.
getDate
().
toString
()).
substr
(
-
2
)
);
}
return
datetime
.
getHours
()
+
':'
+
(
'0'
+
datetime
.
getMinutes
().
toString
()).
substr
(
-
2
);
};
/**
* 返回 2018-01-01 10:00:00 格式时间
*
* @param {any} time
*/
formatTime
=
(
time
)
=>
{
var
newTime
=
new
Date
(
time
);
var
year
=
newTime
.
getFullYear
();
var
month
=
newTime
.
getMonth
()
+
1
;
if
(
month
<
10
)
{
var
month
=
'0'
+
month
;
}
var
date
=
newTime
.
getDate
();
if
(
date
<
10
)
{
var
date
=
'0'
+
date
;
}
var
hour
=
newTime
.
getHours
();
if
(
hour
<
10
)
{
var
hour
=
'0'
+
hour
;
}
var
minute
=
newTime
.
getMinutes
();
if
(
minute
<
10
)
{
var
minute
=
'0'
+
minute
;
}
var
second
=
newTime
.
getSeconds
();
if
(
second
<
10
)
{
var
second
=
'0'
+
second
;
}
return
year
+
'-'
+
month
+
'-'
+
date
+
' '
+
hour
+
':'
+
minute
+
':'
+
second
;
};
/**
* 左侧开始时间的偏移,返回单位ms
*
* @param {any} timestamp
* @param {any} step
*/
msToNextStep
=
(
timestamp
,
step
)
=>
{
var
remainder
=
timestamp
%
step
;
return
remainder
?
step
-
remainder
:
0
;
};
/**
* 设置时间,让这个时间点跳到中间红线处
*
* @param {any} playTimestamp 单位ms
*/
setPlaytimestamp
=
(
playTimestamp
)
=>
{
this
.
clearCanvas
();
// this.startTimestamp = playTimestamp - (this.hoursPerRuler * 60 * 60 * 1000) / 2;
this
.
init
(
this
.
startTimestamp
,
playTimestamp
,
this
.
hoverTooltip
,
this
.
timecell
,
true
);
};
/** 清除canvas 每次重新绘制需要先清除 */
clearCanvas
=
()
=>
{
this
.
ctx
.
clearRect
(
0
,
0
,
1500
,
150
);
};
/** 返回点击或者拖动的时间点 */
playTimestampChange
=
()
=>
{
var
_this
=
this
;
if
(
_this
.
playTimestamp
!=
null
)
{
if
(
this
.
props
.
playTimestampChange
)
{
const
selectedCell
=
this
.
timecell
.
find
(
(
cell
)
=>
cell
.
beginTime
<=
_this
.
playTimestamp
&&
cell
.
endTime
>=
_this
.
playTimestamp
,
);
this
.
props
.
playTimestampChange
(
_this
.
playTimestamp
,
selectedCell
,
selectedCell
&&
_this
.
playTimestamp
-
selectedCell
.
beginTime
,
);
}
}
};
draw
()
{
// Draw whatever
this
.
ctx
.
fillRect
(
0
,
0
,
this
.
canvas
.
width
,
this
.
canvas
.
height
);
}
render
()
{
return
(
<
div
style
=
{{
height
:
72
}}
>
<
RvResponsiveCanvas
canvasRef
=
{(
el
)
=>
(
this
.
canvas
=
el
)}
scale
=
{
1
}
style
=
{{
cursor
:
'pointer'
,
border
:
'1px solid #cccccc'
,
backgroundColor
:
'#000000'
,
}}
onDragStart
=
{()
=>
{
return
false
;
}}
onResize
=
{()
=>
this
.
initCanval
()}
/
>
<
/div
>
);
}
}
packages/base-components/VmsVideo/src/recVideo/TimeSlider/responsiveCanvas.js
0 → 100644
View file @
a0b118cc
import
React
,
{
Component
}
from
'react'
;
import
getSize
from
'./get-size'
;
export
default
class
RvResponsiveCanvas
extends
Component
{
static
defaultProps
=
{
scale
:
typeof
window
!==
'undefined'
?
window
.
devicePixelRatio
:
1
,
};
state
=
{
width
:
0
,
height
:
0
,
};
$canvas
;
componentDidMount
()
{
window
.
addEventListener
(
'resize'
,
this
.
handleResize
,
false
);
this
.
setSize
();
}
componentWillUnmount
()
{
window
.
removeEventListener
(
'resize'
,
this
.
handleResize
,
false
);
}
handleResize
=
()
=>
{
this
.
setSize
();
this
.
props
.
onResize
(
this
.
state
.
width
,
this
.
state
.
height
);
};
setSize
=
()
=>
{
const
parent
=
this
.
$canvas
.
parentElement
;
if
(
!
parent
)
{
return
;
}
const
[
width
,
height
]
=
getSize
(
parent
);
this
.
setState
({
width
,
height
});
};
setRef
=
(
el
)
=>
{
if
(
!
el
)
{
return
;
}
const
{
canvasRef
}
=
this
.
props
;
this
.
$canvas
=
el
;
if
(
typeof
canvasRef
===
'function'
)
{
canvasRef
(
el
);
}
};
render
()
{
const
{
scale
,
onResize
,
canvasRef
,
style
,
...
props
}
=
this
.
props
;
const
{
width
,
height
}
=
this
.
state
;
return
(
<
canvas
{...
props
}
ref
=
{
this
.
setRef
}
width
=
{
width
*
scale
}
height
=
{
height
*
scale
}
style
=
{{
...
style
,
width
,
height
,
minWidth
:
'952px'
}}
/
>
);
}
}
packages/base-components/VmsVideo/src/recVideo/index.js
0 → 100644
View file @
a0b118cc
import
{
Button
,
message
,
Modal
}
from
'antd'
;
import
{
useEffect
,
useState
,
useContext
,
useRef
,
useImperativeHandle
}
from
'react'
;
import
TestVideo
from
'../index'
;
import
classNames
from
'classnames'
;
import
{
DatePicker
,
TimePicker
,
Calendar
,
theme
,
ConfigProvider
}
from
'antd'
;
import
Empty
from
'@wisdom-components/empty'
;
import
{
videoPlayback
,
newPlayback
}
from
'../apis'
;
import
'./index.less'
;
import
moment
from
'moment'
;
import
TimeSlider
from
'./TimeSlider'
;
const
RecVideo
=
(
props
,
ref
)
=>
{
const
{
getPrefixCls
}
=
useContext
(
ConfigProvider
.
ConfigContext
);
const
prefixCls
=
getPrefixCls
(
'rec-video-view'
);
const
{
VideoInfo
,
JessibucaObj
}
=
props
;
const
jessibuca
=
useRef
(
null
);
const
[
hoursRuler
,
setHoursRuler
]
=
useState
(
VideoInfo
.
hoursRuler
||
24
);
const
[
showId
,
setShowId
]
=
useState
(
null
);
//视频ID
const
[
peridos
,
setPeridos
]
=
useState
([]);
//可播放视频时间段
const
[
playTimestamp
,
setPlayTimestamp
]
=
useState
(
null
);
//当前正在播放时间段
const
[
minTimestamp
,
setMinTimestamp
]
=
useState
(
null
);
//时间轴最小时间
const
[
maxTimestamp
,
setMaxTimestamp
]
=
useState
(
null
);
//时间轴最大时间
useEffect
(()
=>
{
changeReplayCfg
();
},
[
props
.
VideoInfo
]);
useImperativeHandle
(
ref
,
()
=>
{
// changeVal 就是暴露给父组件的方法, newVal是父组件传递的参数
return
jessibuca
.
current
;
// _video&& _video.current&&_video.current.jessibuca
});
useEffect
(()
=>
{
const
{
endTime
=
moment
().
format
(
'YYYY-MM-DD 23:59:59'
)
}
=
VideoInfo
;
const
edTimes
=
moment
(
endTime
).
format
(
'YYYY-MM-DD HH:mm:ss'
);
if
(
playTimestamp
)
{
let
momentObj
=
moment
(
playTimestamp
);
let
formattedTime
=
momentObj
.
format
(
'YYYY-MM-DD HH:mm:ss'
);
const
edDates
=
moment
(
edTimes
).
format
(
'YYYY-MM-DD HH:mm:ss'
);
const
params
=
{
id
:
VideoInfo
.
id
,
startTime
:
formattedTime
,
endTime
:
edDates
,
'site-code'
:
window
?.
globalConfig
?.
userInfo
?.
LocalSite
||
''
,
};
rePaly
(
params
);
}
},
[
playTimestamp
]);
const
changeReplayCfg
=
()
=>
{
const
{
beginTime
=
moment
().
format
(
'YYYY-MM-DD 00:00:00'
),
endTime
=
moment
().
format
(
'YYYY-MM-DD 23:59:59'
),
}
=
VideoInfo
;
const
hoursPerRuler
=
calculateHours
(
beginTime
,
endTime
)
||
24
;
const
stTimes
=
moment
(
beginTime
).
format
(
'YYYY-MM-DD HH:mm:ss'
);
const
edTimes
=
moment
(
endTime
).
format
(
'YYYY-MM-DD HH:mm:ss'
);
const
param
=
{
id
:
VideoInfo
.
id
,
startTime
:
stTimes
,
endTime
:
edTimes
,
'site-code'
:
window
?.
globalConfig
?.
userInfo
?.
LocalSite
||
''
,
};
setHoursRuler
(
hoursPerRuler
);
setMinTimestamp
(
moment
(
stTimes
).
valueOf
());
setMaxTimestamp
(
moment
(
edTimes
).
valueOf
());
getVideoPlBack
(
param
);
};
const
getVideoPlBack
=
(
param
)
=>
{
videoPlayback
(
param
).
then
((
res
)
=>
{
if
(
res
.
code
===
200
)
{
setPeridos
(
res
.
data
.
peridos
.
map
((
times
,
i
)
=>
{
let
beginTime
=
moment
(
times
.
StartTime
.
replaceAll
(
'T'
,
' '
).
replaceAll
(
'Z'
,
' '
));
let
endTime
=
moment
(
times
.
EndTime
.
replaceAll
(
'T'
,
' '
).
replaceAll
(
'Z'
,
' '
));
return
{
...
times
,
idx
:
i
,
beginTime
:
beginTime
.
valueOf
(),
endTime
:
endTime
.
valueOf
(),
style
:
{
background
:
'#637DEC'
},
};
}),
);
setShowId
(
res
.
data
.
url
);
}
else
{
message
.
warn
(
res
.
msg
);
setShowId
(
null
);
}
});
};
const
rePaly
=
(
params
)
=>
{
newPlayback
(
params
).
then
((
res
)
=>
{
if
(
res
.
code
===
200
)
{
setShowId
(
res
.
data
);
}
else
{
message
.
warn
(
res
.
msg
);
}
});
};
const
calculateHours
=
(
time1
,
time2
)
=>
{
const
date1
=
new
Date
(
time1
);
const
date2
=
new
Date
(
time2
);
const
diff
=
Math
.
abs
(
date1
.
getTime
()
-
date2
.
getTime
());
return
Math
.
ceil
(
diff
/
(
1000
*
60
*
60
));
};
return
(
<
div
className
=
{
classNames
(
prefixCls
)}
>
{
showId
?
(
<>
<
div
className
=
{
classNames
(
`
${
prefixCls
}
-video`
)}
>
{
showId
&&
(
<
TestVideo
VideoInfo
=
{{
...
VideoInfo
,
id
:
showId
}}
JessibucaObj
=
{{
...
JessibucaObj
}}
key
=
{
showId
}
ref
=
{
jessibuca
}
/
>
)}
<
/div
>
{
/* 时间轴 */
}
<
div
className
=
{
classNames
(
`
${
prefixCls
}
-time`
)}
>
{
peridos
.
length
?
(
<
TimeSlider
minTimestamp
=
{
minTimestamp
}
key
=
{
JSON
.
stringify
(
peridos
)
+
(
hoursRuler
||
24
)}
maxTimestamp
=
{
maxTimestamp
}
hoursPerRuler
=
{
hoursRuler
||
24
}
playTimestamp
=
{
playTimestamp
?
playTimestamp
:
peridos
[
0
].
beginTime
}
playTimestampChange
=
{(
time
,
recordInfo
,
playOffset
)
=>
{
if
(
recordInfo
&&
playOffset
)
{
setPlayTimestamp
(
time
);
}
else
{
message
.
warn
(
'当前时间节点没有视频可以播放哦!'
);
}
}}
timecell
=
{
peridos
}
/
>
)
:
null
}
<
/div
>
<
/
>
)
:
(
<
div
className
=
{
classNames
(
`
${
prefixCls
}
-empty`
)}
>
<
Empty
theme
=
{
'dark'
}
description
=
{
''
}
/
>
<
/div
>
)}
<
/div
>
);
};
export
default
React
.
forwardRef
(
RecVideo
);
packages/base-components/VmsVideo/src/recVideo/index.less
0 → 100644
View file @
a0b118cc
@root-entry-name: 'default';
@import '~antd/es/style/themes/index.less';
@rec-video-view-prefix-cls: ~'@{ant-prefix}-rec-video-view';
.@{rec-video-view-prefix-cls} {
display: flex;
align-items: center;
flex-direction: column;
height: 100%;
width: 100%;
&-video {
flex: 1;
width: 100%;
}
&-time {
flex: none;
width: 100%;
}
&-empty {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
:global {
.timeslider-canvas-wrap-his {
height: 72px;
width: 100%;
}
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment