<think>我们参考了用户提供的引用内容,特别是引用[1]和引用[2]中关于海康插件在Vue中的使用经验。用户要求一个完整的JavaScript实现方案,因此我们将提供一个不依赖框架的纯JavaScript实现示例,同时考虑海康插件3.3版本的事件处理特性。
根据引用[1]的信息,海康插件3.3版本可能没有直接隐藏画面的接口,因此我们的事件处理方案将避免频繁停止和重新播放,而是利用坐标计算来确定点击的窗口。
### 纯JavaScript实现海康视频插件窗口选择事件
```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>海康威视视频插件窗口选择事件示例</title>
<style>
#video-container {
width: 800px;
height: 600px;
background-color: #000;
margin: 20px auto;
position: relative;
border: 1px solid #ccc;
}
.layout-selector {
text-align: center;
margin: 15px 0;
}
.layout-selector button {
margin: 0 5px;
padding: 5px 10px;
}
.selected-info {
text-align: center;
padding: 10px;
background: #f0f0f0;
font-weight: bold;
}
</style>
</head>
<body>
<div id="video-container"></div>
<div class="layout-selector">
<button onclick="changeLayout('1x1')">1分屏</button>
<button onclick="changeLayout('2x2')">4分屏</button>
<button onclick="changeLayout('3x3')">9分屏</button>
<button onclick="changeLayout('4x4')">16分屏</button>
</div>
<div class="selected-info">
当前选中窗口: <span id="selected-window">-1</span> |
坐标: (<span id="click-x">0</span>, <span id="click-y">0</span>)
</div>
<!-- 引入海康插件 -->
<script type="text/javascript" src="webVideoCtrl.js"></script>
<script>
// 全局变量
let webControl = null; // 插件实例
let currentLayout = "1x1"; // 当前布局
let selectedWindow = -1; // 当前选中窗口索引
let lastClick = { x: 0, y: 0 }; // 最后点击坐标
// 页面加载完成后初始化
window.onload = function() {
initPlugin();
};
// 初始化插件
function initPlugin() {
// 确保插件已加载
if (typeof WebVideoCtrl === 'undefined') {
console.error('未找到海康插件');
return;
}
// 创建插件实例
webControl = new WebVideoCtrl();
// 创建播放容器
const container = document.getElementById('video-container');
webControl.create({
id: "video-container",
width: "100%",
height: "100%",
});
// 初始化插件(示例参数)
const initResult = webControl.initPlugin(
"127.0.0.1", // 设备IP
8000, // 端口
true // 使用HTTPS
);
if (!initResult) {
console.error("插件初始化失败");
return;
}
// 设置事件监听
setupEventListeners();
// 启动预览
startPreview();
}
// 设置事件监听
function setupEventListeners() {
// 启动窗口事件监听
webControl.JS_StartWindowEvent("video-container");
// 设置窗口事件回调
webControl.JS_SetWindowEventCallback({
cbWindowEvent: function(eventType, x, y) {
handleWindowEvent(eventType, x, y);
}
});
}
// 处理窗口事件
function handleWindowEvent(eventType, x, y) {
// 更新最后点击坐标
lastClick = { x, y };
document.getElementById('click-x').innerText = x;
document.getElementById('click-y').innerText = y;
switch (eventType) {
case "EVENT_CLICK":
handleWindowClick(x, y);
break;
case "EVENT_DBLCLICK":
handleWindowDoubleClick(x, y);
break;
case "EVENT_RBUTTONDOWN":
handleRightClick(x, y);
break;
default:
console.log('未处理事件类型:', eventType);
}
}
// 处理窗口点击
function handleWindowClick(x, y) {
const index = calcWindowIndex(x, y);
selectedWindow = index;
document.getElementById('selected-window').innerText = index;
console.log(`窗口${index}被选中`, { x, y });
// 执行聚焦操作(示例)
focusWindow(index);
}
// 处理双击事件(全屏)
function handleWindowDoubleClick(x, y) {
const index = calcWindowIndex(x, y);
console.log(`窗口${index}被双击`);
// 执行全屏操作
fullscreenWindow(index);
}
// 处理右键点击(示例:弹出菜单)
function handleRightClick(x, y) {
const index = calcWindowIndex(x, y);
console.log(`窗口${index}右键点击`);
// 这里可以显示自定义右键菜单
}
// 计算窗口索引
function calcWindowIndex(x, y) {
const container = document.getElementById('video-container');
const rect = container.getBoundingClientRect();
// 计算相对坐标(考虑滚动位置)
const relX = x - rect.left;
const relY = y - rect.top;
// 解析布局 (如"2x2")
const [cols, rows] = currentLayout.split('x').map(Number);
// 计算单元格尺寸
const cellWidth = rect.width / cols;
const cellHeight = rect.height / rows;
// 计算行列索引
const colIndex = Math.min(cols - 1, Math.floor(relX / cellWidth));
const rowIndex = Math.min(rows - 1, Math.floor(relY / cellHeight));
// 返回窗口索引(从0开始)
return rowIndex * cols + colIndex;
}
// 聚焦窗口(停止其他窗口播放,只播放选中的窗口)
function focusWindow(index) {
// 停止所有窗口播放
webControl.JS_StopAllPlay();
// 在选定窗口重新播放(示例摄像头ID)
webControl.JS_StartPlay({
iWndIndex: index,
cameraIndexCode: "YOUR_CAMERA_ID", // 实际摄像头ID
streamType: 0, // 主码流
});
}
// 全屏窗口
function fullscreenWindow(index) {
// 将指定窗口全屏
webControl.JS_WindowFullScreen(index);
}
// 切换布局
function changeLayout(layout) {
currentLayout = layout;
// 停止当前播放
webControl.JS_StopAllPlay();
// 重新设置窗口数量
const windowCount = parseInt(layout.split('x')[0]) *
parseInt(layout.split('x')[1]);
webControl.JS_ChangeWndNum(windowCount);
// 重新开始预览
startPreview();
}
// 启动预览(示例)
function startPreview() {
// 根据布局创建窗口
const [cols, rows] = currentLayout.split('x').map(Number);
const windowCount = cols * rows;
for (let i = 0; i < windowCount; i++) {
// 实际项目中应使用真实的摄像头ID数组
webControl.JS_StartPlay({
iWndIndex: i,
cameraIndexCode: `CAM_${i}`, // 示例摄像头ID
streamType: 0, // 主码流
});
}
}
// 窗口大小变化时调整插件尺寸(参考引用[2])
window.addEventListener('resize', function() {
const container = document.getElementById('video-container');
if (webControl) {
webControl.JS_Resize(container.clientWidth, container.clientHeight);
}
});
</script>
</body>
</html>
```
### 关键实现说明
1. **事件监听设置**
```javascript
// 启动窗口事件监听
webControl.JS_StartWindowEvent("video-container");
// 设置事件回调
webControl.JS_SetWindowEventCallback({
cbWindowEvent: function(eventType, x, y) {
// 事件处理逻辑
}
});
```
2. **坐标计算核心**
```javascript
function calcWindowIndex(x, y) {
const container = document.getElementById('video-container');
const rect = container.getBoundingClientRect();
// 计算相对坐标(考虑滚动和偏移)
const relX = x - rect.left;
const relY = y - rect.top;
// 解析布局
const [cols, rows] = currentLayout.split('x').map(Number);
// 计算单元格尺寸
const cellWidth = rect.width / cols;
const cellHeight = rect.height / rows;
// 计算行列索引
const colIndex = Math.floor(relX / cellWidth);
const rowIndex = Math.floor(relY / cellHeight);
// 返回索引(0开始)
return rowIndex * cols + colIndex;
}
```
3. **布局切换处理**
```javascript
function changeLayout(layout) {
currentLayout = layout;
// 停止所有播放
webControl.JS_StopAllPlay();
// 改变窗口数量
const [cols, rows] = layout.split('x').map(Number);
webControl.JS_ChangeWndNum(cols * rows);
// 重新开始预览
startPreview();
}
```
### 注意事项
1. **插件引入**
- 必须提前加载`webVideoCtrl.js`[^3]
- 确保插件安装正确(通常需要安装ActiveX控件或NPAPI插件)
2. **布局适应**
- 使用`getBoundingClientRect()`获取实时容器尺寸
- 监听`resize`事件动态调整插件尺寸(参考引用[2])
3. **事件类型**
- `EVENT_CLICK`:左键单击
- `EVENT_DBLCLICK`:左键双击
- `EVENT_RBUTTONDOWN`:右键点击
- 其他事件请参考海康官方文档
4. **兼容性处理**
- 海康插件3.3版本可能没有直接隐藏画面的接口(引用[1]),避免频繁停止/启动播放
- 全屏操作使用`JS_WindowFullScreen`方法
5. **实际部署**
- 替换示例中的摄像头ID为实际设备ID
- 处理设备登录和权限问题
- 考虑跨域安全策略
> **重要提示**:在真实环境中,需要确保设备网络可达,并且已经正确配置了视频流参数(如主/子码流、协议等)。多画面分屏时,每个窗口播放不同的摄像头,需要维护摄像头和窗口的映射关系。
§§相关问题§§
1. 海康插件窗口事件回调中`eventType`参数有哪些可能的值?
2. 如何解决海康插件在分屏布局下的坐标计算偏差问题?
3. 在没有海康插件隐藏接口的情况下,如何实现窗口的隐藏和显示?
4. 海康视频插件在页面滚动时如何保持正确尺寸?</think>### JavaScript 海康威视视频插件窗口选择事件完整实现方案
以下是基于海康威视 WebVideoCtrl.js 插件的窗口选择事件完整实现方案(纯JavaScript版):
```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>海康威视视频插件窗口选择事件</title>
<style>
#video-container {
width: 800px;
height: 600px;
background-color: #000;
margin: 20px auto;
position: relative;
border: 1px solid #ccc;
}
.layout-selector {
text-align: center;
margin: 15px 0;
}
.layout-selector button {
margin: 0 5px;
padding: 5px 10px;
}
.selected-info {
text-align: center;
padding: 10px;
background: #f0f0f0;
font-weight: bold;
}
</style>
</head>
<body>
<div id="video-container"></div>
<div class="layout-selector">
<button onclick="changeLayout('1x1')">1分屏</button>
<button onclick="changeLayout('2x2')">4分屏</button>
<button onclick="changeLayout('3x3')">9分屏</button>
<button onclick="changeLayout('4x4')">16分屏</button>
</div>
<div class="selected-info">
当前选中窗口: <span id="selected-window">-1</span> |
坐标: (<span id="click-x">0</span>, <span id="click-y">0</span>)
</div>
<!-- 引入海康插件 -->
<script type="text/javascript" src="webVideoCtrl.js"></script>
<script>
// 全局变量
let webControl = null; // 插件实例
let currentLayout = "1x1"; // 当前布局
let selectedWindow = -1; // 当前选中窗口索引
let lastClick = { x: 0, y: 0 }; // 最后点击坐标
// 页面加载完成后初始化
window.onload = function() {
initPlugin();
};
// 初始化插件
function initPlugin() {
// 确保插件已加载
if (typeof WebVideoCtrl === 'undefined') {
console.error('未找到海康插件');
return;
}
// 创建插件实例
webControl = new WebVideoCtrl();
// 创建播放容器
const container = document.getElementById('video-container');
webControl.create({
id: "video-container",
width: "100%",
height: "100%",
});
// 初始化插件(示例参数)
const initResult = webControl.initPlugin(
"127.0.0.1", // 设备IP
8000, // 端口
true // 使用HTTPS
);
if (!initResult) {
console.error("插件初始化失败");
return;
}
// 设置事件监听
setupEventListeners();
// 启动预览
startPreview();
}
// 设置事件监听
function setupEventListeners() {
// 启动窗口事件监听
webControl.JS_StartWindowEvent("video-container");
// 设置窗口事件回调
webControl.JS_SetWindowEventCallback({
cbWindowEvent: function(eventType, x, y) {
handleWindowEvent(eventType, x, y);
}
});
}
// 处理窗口事件
function handleWindowEvent(eventType, x, y) {
// 更新最后点击坐标
lastClick = { x, y };
document.getElementById('click-x').innerText = x;
document.getElementById('click-y').innerText = y;
switch (eventType) {
case "EVENT_CLICK":
handleWindowClick(x, y);
break;
case "EVENT_DBLCLICK":
handleWindowDoubleClick(x, y);
break;
case "EVENT_RBUTTONDOWN":
handleRightClick(x, y);
break;
default:
console.log('未处理事件类型:', eventType);
}
}
// 处理窗口点击
function handleWindowClick(x, y) {
const index = calcWindowIndex(x, y);
selectedWindow = index;
document.getElementById('selected-window').innerText = index;
console.log(`窗口${index}被选中`, { x, y });
// 执行聚焦操作(示例)
focusWindow(index);
}
// 处理双击事件(全屏)
function handleWindowDoubleClick(x, y) {
const index = calcWindowIndex(x, y);
console.log(`窗口${index}被双击`);
// 执行全屏操作
fullscreenWindow(index);
}
// 处理右键点击(示例:弹出菜单)
function handleRightClick(x, y) {
const index = calcWindowIndex(x, y);
console.log(`窗口${index}右键点击`);
// 这里可以显示自定义右键菜单
}
// 计算窗口索引
function calcWindowIndex(x, y) {
const container = document.getElementById('video-container');
const rect = container.getBoundingClientRect();
// 计算相对坐标(考虑滚动位置)
const relX = x - rect.left;
const relY = y - rect.top;
// 解析布局 (如"2x2")
const [cols, rows] = currentLayout.split('x').map(Number);
// 计算单元格尺寸
const cellWidth = rect.width / cols;
const cellHeight = rect.height / rows;
// 计算行列索引
const colIndex = Math.min(cols - 1, Math.floor(relX / cellWidth));
const rowIndex = Math.min(rows - 1, Math.floor(relY / cellHeight));
// 返回窗口索引(从0开始)
return rowIndex * cols + colIndex;
}
// 聚焦窗口(停止其他窗口播放,只播放选中的窗口)
function focusWindow(index) {
// 停止所有窗口播放
webControl.JS_StopAllPlay();
// 在选定窗口重新播放(示例摄像头ID)
webControl.JS_StartPlay({
iWndIndex: index,
cameraIndexCode: "YOUR_CAMERA_ID", // 实际摄像头ID
streamType: 0, // 主码流
});
}
// 全屏窗口
function fullscreenWindow(index) {
// 将指定窗口全屏
webControl.JS_WindowFullScreen(index);
}
// 切换布局
function changeLayout(layout) {
currentLayout = layout;
// 停止当前播放
webControl.JS_StopAllPlay();
// 重新设置窗口数量
const windowCount = parseInt(layout.split('x')[0]) *
parseInt(layout.split('x')[1]);
webControl.JS_ChangeWndNum(windowCount);
// 重新开始预览
startPreview();
}
// 启动预览(示例)
function startPreview() {
// 根据布局创建窗口
const [cols, rows] = currentLayout.split('x').map(Number);
const windowCount = cols * rows;
for (let i = 0; i < windowCount; i++) {
// 实际项目中应使用真实的摄像头ID数组
webControl.JS_StartPlay({
iWndIndex: i,
cameraIndexCode: `CAM_${i}`, // 示例摄像头ID
streamType: 0, // 主码流
});
}
}
// 窗口大小变化时调整插件尺寸(参考引用[2])
window.addEventListener('resize', function() {
const container = document.getElementById('video-container');
if (webControl) {
webControl.JS_Resize(container.clientWidth, container.clientHeight);
}
});
</script>
</body>
</html>
```
### 关键实现说明
1. **事件监听设置**
```javascript
// 启动窗口事件监听
webControl.JS_StartWindowEvent("video-container");
// 设置事件回调
webControl.JS_SetWindowEventCallback({
cbWindowEvent: function(eventType, x, y) {
// 事件处理逻辑
}
});
```
2. **坐标计算核心**
```javascript
function calcWindowIndex(x, y) {
const container = document.getElementById('video-container');
const rect = container.getBoundingClientRect();
// 计算相对坐标(考虑滚动和偏移)
const relX = x - rect.left;
const relY = y - rect.top;
// 解析布局
const [cols, rows] = currentLayout.split('x').map(Number);
// 计算单元格尺寸
const cellWidth = rect.width / cols;
const cellHeight = rect.height / rows;
// 计算行列索引
const colIndex = Math.floor(relX / cellWidth);
const rowIndex = Math.floor(relY / cellHeight);
// 返回索引(0开始)
return rowIndex * cols + colIndex;
}
```
3. **布局切换处理**
```javascript
function changeLayout(layout) {
currentLayout = layout;
// 停止所有播放
webControl.JS_StopAllPlay();
// 改变窗口数量
const [cols, rows] = layout.split('x').map(Number);
webControl.JS_ChangeWndNum(cols * rows);
// 重新开始预览
startPreview();
}
```
### 注意事项
1. **插件引入**
- 必须提前加载`webVideoCtrl.js`[^3]
- 确保插件安装正确(通常需要安装ActiveX控件或NPAPI插件)
2. **布局适应**
- 使用`getBoundingClientRect()`获取实时容器尺寸
- 监听`resize`事件动态调整插件尺寸(参考引用[2])
3. **事件类型**
- `EVENT_CLICK`:左键单击
- `EVENT_DBLCLICK`:左键双击
- `EVENT_RBUTTONDOWN`:右键点击
- 其他事件请参考海康官方文档
4. **兼容性处理**
- 海康插件3.3版本可能没有直接隐藏画面的接口(引用[1]),避免频繁停止/启动播放
- 全屏操作使用`JS_WindowFullScreen`方法
5. **实际部署**
- 替换示例中的摄像头ID为实际设备ID
- 处理设备登录和权限问题
- 考虑跨域安全策略
> **重要提示**:在真实环境中,需要确保设备网络可达,并且已经正确配置了视频流参数(如主/子码流、协议等)。多画面分屏时,每个窗口播放不同的摄像头,需要维护摄像头和窗口的映射关系。