demo_embedded_for_iframe.html
15.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
<!doctype html>
<html>
<head>
<title>预览Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-Control" content="no-cache, must-revalidate" />
<meta http-equiv="Expires" content="0" />
</head>
<style>
html, body {
padding: 0;
margin: 0;
}
.playWnd {
margin: 30px 0 0 50px;
width: 800px;
height: 400px;
border: 1px solid red;
}
.cbInfoDiv {
float: left;
width: 360px;
margin-left: 16px;
border:1px solid #7F9DB9;
}
.cbInfo {
height: 200px;
padding: 5px;
border: 1px solid #7F9DB9;
word-break: break-all;
overflow: scroll/auto;
}
.operate {
margin-top: 24px;
}
.operate::after {
content: '';
display: block;
clear: both;
}
.operate .btns {
height: 32px;
}
.module {
float: left;
width: 120px;
min-height: 290px;
margin-left: 10px;
padding: 16px 8px;
box-sizing: border-box;
border: 1px solid #e5e5e5;
}
.module .item {
margin-bottom: 4px;
}
.module .label {
width: 150px;
display: inline-block;
vertical-align: middle;
margin-right: 8px;
text-align: right;
}
.module input[type="text"],
.module select {
box-sizing: border-box;
display: inline-block;
vertical-align: middle;
margin-left: 0;
width: 150px;
min-height: 20px;
}
.module .btn {
min-width: 80px;
min-height: 24px;
margin-top: 16px;
margin-left: 158px;
}
</style>
<body>
<div id="playWnd" class="playWnd" style="left: 109px; top: 133px;"></div>
<div id="operate" class="operate">
<!--初始化、反初始化、设置认证信息接口调用入口。
1.插件所有接口都需要在调用初始化并返回成功后才能调用
2.设置认证信息仅适用于对接多平台时的情况,具体参照开发指南
3.反初始化后,插件资源销毁-->
<div class="module" style="left:30px;height:30px;width:280px;padding:10;margin:10;">
<div class="item">
<label >初始化相关参数:</label>
<textarea id="initParam" type="text" style="width:260px;height:200px;">
{
"argument": {
"appkey": "",
"ip": "",
"port": 443,
"secret": "",
"enableHTTPS": 1,
"layout": "2x2",
"playMode": 0
},
"funcName": "init"
}
</textarea>
</div>
<div class="item">
<button style="width:10px;padding:0;margin:0;" id="initBtn" class="btn">执行</button>
</div>
</div>
<!--单个点位播放、批量点位播放、批量停止播放、全部停止播放接口调用入口。
1.authUuid为对接多平台时必须的播放字段,对接单平台时,可不指定-->
<div class="module" style="height:30;width:280px;padding:10;margin:10;">
<div class="item">
<label >播放相关参数:</label>
<textarea id="playParam" type="text" style="width:260px;height:200px;">
{
"argument": {
"cameraIndexCode": "",
"ezvizDirect": 0,
"gpuMode": 0,
"streamMode": 0,
"transMode": 1,
"wndId": -1
},
"funcName": "startPreview"
}
</textarea>
</div>
<div class="item">
<button style="width:10px;padding:0;margin:0;" id="playBtn" class="btn">执行</button>
</div>
</div>
<div class="module" style="height:50;width:300px;padding:10;margin:10;">
<legend>返回值信息</legend>
<div id="cbInfo" class="cbInfo"></div>
<button style="width:80px;height:24px;padding:30;margin:0;" id="clear">清空</button>
</div>
</div>
</body>
<script src="jquery-1.12.4.min.js"></script>
<script src="jsencrypt.min.js"></script>
<script src="jsWebControl-1.0.0.min.js"></script>
<script type="text/javascript">
// 插件对象实例,初始化为null,需要创建多个插件窗口时,需要定义多个插件对象实例变量,各个变量唯一标志对应的插件实例
var oWebControl = null;
var bIE = (!!window.ActiveXObject || 'ActiveXObject' in window);// 是否为IE浏览器
var pubKey = ''; // demo中未使用加密,可根据需求参照开发指南自行使用加密功能
var initCount = 0; // 异常重启计数
var iframePos = {}; // iframe相对文档的位置
var parentTitle = ''; // 父页面标题
var iframeClientPos = null; // iframe相对视窗的位置
var iframeParentShowSize = null; // 视窗大小 width height
// 标签关闭
$(window).unload(function () {
if (oWebControl != null){
oWebControl.JS_HideWnd(); // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题
oWebControl.JS_Disconnect().then(function(){}, function() {});
}
});
// 步骤1:监听父页面的消息
window.addEventListener('message', function(e){
if(e && e.data){
switch (e.data.action){
case 'sendTitle': // 父页面将其标题发送过来,子页面保存该标题,以便创建插件窗口成功后将标题设置回给父页面
parentTitle = e.data.info;
break;
case 'updatePos': // 更新插件位置:JS_CreateWnd时需要父页面计算滚动条偏移量,初始偏移量叠加该偏移量作为iframe的偏移量,防止插件窗口与DIV窗口初始不贴合情况
var scrollValue = e.data.scrollValue; // 滚动条滚动偏移量
oWebControl.JS_SetDocOffset({
left: iframePos.left + scrollValue.left,
top: iframePos.top + scrollValue.top
}); // 更新插件窗口位置
oWebControl.JS_Resize(800, 400);
setWndCover();
break;
case 'updateInitParam':
iframePos = e.data.iframeOffset; // iframe与文档的偏移量
iframeClientPos = e.data.iframeClientPos; // iframe相对视窗的位置
iframeParentShowSize = e.data.showSize; // 视窗大小
break;
case 'resize':
iframeParentShowSize = e.data.showSize; // 视窗大小
iframePos = e.data.iframeOffset; // iframe与文档的偏移量
iframeClientPos = e.data.iframeClientPos; // iframe相对视窗的位置
setWndCover();
break;
case 'scroll':
iframeParentShowSize = e.data.showSize; // 视窗大小
iframePos = e.data.iframeOffset; // iframe与文档的偏移量
iframeClientPos = e.data.iframeClientPos; // iframe相对视窗的位置
var scrollValue = e.data.scrollValue; // 滚动条滚动偏移量
if(oWebControl){
oWebControl.JS_SetDocOffset({
left: iframePos.left + scrollValue.left,
top: iframePos.top + scrollValue.top
}); // 更新插件窗口位置
oWebControl.JS_Resize(800, 400);
setWndCover();
}
break;
default:
break;
}
}
});
// 顶部:iframe.getBoundingClientRect().top小于0并且其绝对值超过DIV.get(0).getBoundingClientRect().top部分需要剪切
// 底部:(iframe.getBoundingClientRect().bottom - iframe父窗口可视域高度,为H1)为不可见部分
// ($(window).height() - DIV.get(0).getBoundingClientRect().bottom)
// 为DIV底部与其所在iframe底部之间的距离H2,H1-H2的值大于0则表示DIV有部分在不可见区域
// 左边:iframe.getBoundingClientRect().left小于0并且其绝对值超过DIV.get(0).getBoundingClientRect().left部分需要剪切
// 右边:(iframe宽度 - DIV.get(0).getBoundingClientRect().right表示DIV右边与其父iframe右边之间的距离,为W1)
// (iframe父窗口可视域宽度-iframe.getBoundingClientRect().left表示iframe左边与iframe父窗口可视域右边之间的距离,为W2)
// (iframe宽度 - W2 - W1)如果大于0,则表示DIV右边超出了iframe父窗口可视域,需要剪切超过的部分
function setWndCover() {
if (oWebControl){
// 准备要用到的一些数据
var iframeWndHeight = $(window).height(); // iframe窗口高度
var iframeWndWidth = $(window).width(); // iframe窗口宽度
var divLeft = $("#playWnd").get(0).getBoundingClientRect().left;
var divTop = $("#playWnd").get(0).getBoundingClientRect().top;
var divRight = $("#playWnd").get(0).getBoundingClientRect().right;
var divBottom = $("#playWnd").get(0).getBoundingClientRect().bottom;
var divWidth = $("#playWnd").width();
var divHeight = $("#playWnd").height();
oWebControl.JS_RepairPartWindow(0, 0, 801, 401); // 多1个像素点防止还原后边界缺失一个像素条
// 判断剪切矩形的上边距
if (iframeClientPos.top < 0 && Math.abs(iframeClientPos.top) > divTop){
var deltaTop = Math.abs(iframeClientPos.top) - divTop;
oWebControl.JS_CuttingPartWindow(0, 0, 801, deltaTop + 1);
//console.log({deltaTop: deltaTop});
}
// 判断剪切矩形的左边距
if (iframeClientPos.left < 0 && Math.abs(iframeClientPos.left) > divLeft){
var deltaLeft = Math.abs(iframeClientPos.left) - divLeft;
//console.log({deltaLeft: deltaLeft});
oWebControl.JS_CuttingPartWindow(0, 0, deltaLeft, 401); // 多剪掉一个像素条,防止出现剪掉一部分窗口后出现一个像素条
}
// 判断剪切矩形的右边距
var W1 = iframeWndWidth - divRight;
var W2 = iframeParentShowSize.width - iframeClientPos.left;
if (W2 < divWidth){
var deltaRight = iframeWndWidth - W2 - W1;
if (deltaRight > 0) {
oWebControl.JS_CuttingPartWindow(800 - deltaRight, 0, deltaRight + 1, 401);
}
}
// 判断剪切矩形的下边距
var H1 = iframeClientPos.bottom - iframeParentShowSize.height;
var H2 = iframeWndHeight - divBottom;
var deltaBottom = H1 - H2;
//console.log({deltaBottom: deltaBottom});
if (deltaBottom > 0) {
oWebControl.JS_CuttingPartWindow(0, 400 - deltaBottom, 801, deltaBottom + 1);
}
}
}
// 创建插件实例,并启动本地服务建立websocket连接,创建插件窗口
function initPlugin () {
oWebControl = new WebControl({
szPluginContainer: "playWnd",
iServicePortStart: 15900,
iServicePortEnd: 15909,
szClassId:"23BF3B0A-2C56-4D97-9C03-0CB103AA8F11", // 用于IE10使用ActiveX的clsid
cbConnectSuccess: function () {
initCount = 0;
setCallbacks();
oWebControl.JS_StartService("window", {
dllPath: "./VideoPluginConnect.dll"
}).then(function () {
// 步骤2:JS_CreateWnd时指定cbSetDocTitle回调,并在回调中向父页面发送更新标题消息,标题为回调出来的uuid
oWebControl.JS_CreateWnd("playWnd", 800, 400, {
bEmbed: true,
cbSetDocTitle: function (uuid) {
oWebControl._pendBg = false;
window.parent.postMessage({
action:'updateTitle',
msg:'子页面通知父页面修改title',
info:uuid
}, '\*'); // '\*'表示跨域参数,请结合自身业务合理设置
}
}).then(function () {
// 步骤3:JS_CreateWnd成功后通知父页面将其标题修改回去
console.log("JS_CreateWnd success");
window.parent.postMessage({
action:'updateTitle',
msg:'子页面通知父页面更新title',
info: parentTitle
}, '\*');
// 步骤4:发消息更新插件窗口位置:这里不直接更新的原因是,父页面默认可能就存在滚动条,此时有滚动量
window.parent.postMessage({
action:'updatePos',
msg:'更新Pos'
}, '\*');
initBtnClicked();
});
}, function () {
console.log("JS_CreateWnd fail");
});
},
cbConnectError: function () {
console.log("cbConnectError");
oWebControl = null;
$("#playWnd").html("插件未启动,正在尝试启动,请稍候...");
WebControl.JS_WakeUp("VideoWebPlugin://");
initCount ++;
if (initCount < 3) {
setTimeout(function () {
initPlugin();
}, 3000)
} else {
$("#playWnd").html("插件启动失败,请检查插件是否安装!");
}
},
cbConnectClose: function (bNormalClose) {
// 异常断开:bNormalClose = false
// JS_Disconnect正常断开:bNormalClose = true
if (true == bNormalClose){
console.log("cbConnectClose normal");
}else{
console.log("cbConnectClose exception");
}
oWebControl = null;
}
});
}
initPlugin();
// 获取公钥
function getPubKey (callback) {
oWebControl.JS_RequestInterface({
funcName: "getRSAPubKey",
argument: JSON.stringify({
keyLength: 1024
})
}).then(function (oData) {
console.log(oData)
if (oData.responseMsg.data) {
pubKey = oData.responseMsg.data
callback()
}
})
}
// 设置窗口控制回调
function setCallbacks() {
oWebControl.JS_SetWindowControlCallback({
cbIntegrationCallBack: cbIntegrationCallBack
});
}
// 推送消息
function cbIntegrationCallBack(oData) {
showCBInfo(JSON.stringify(oData.responseMsg));
}
// RSA加密
function setEncrypt (value) {
var encrypt = new JSEncrypt();
encrypt.setPublicKey(pubKey);
return encrypt.encrypt(value);
}
function requestInterface(value)
{
oWebControl.JS_RequestInterface(JSON.parse(value)).then(function (oData) {
console.log(oData)
showCBInfo(JSON.stringify(oData ? oData.responseMsg : ''));
});
}
// 显示接口返回的消息及插件回调信息
function showCBInfo(szInfo, type) {
if (type === 'error') {
szInfo = "<div style='color: red;'>" + dateFormat(new Date(), "yyyy-MM-dd hh:mm:ss") + " " + szInfo + "</div>";
} else {
szInfo = "<div>" + dateFormat(new Date(), "yyyy-MM-dd hh:mm:ss") + " " + szInfo + "</div>";
}
$("#cbInfo").html(szInfo + $("#cbInfo").html());
}
function initBtnClicked(){
var param = $("#initParam").val();
//删除字符串中的回车换行
param = param.replace(/(\s*)/g, "");
// 执行初始化
requestInterface(param);
}
$("#initBtn").click(function() {
initBtnClicked();
})
$("#playBtn").click(function() {
var param = $("#playParam").val();
//删除字符串中的回车换行
param = param.replace(/(\s*)/g, "");
// 执行预览
requestInterface(param);
})
// 清空
$("#clear").click(function() {
$("#cbInfo").html('');
})
// 格式化时间
function dateFormat(oDate, fmt) {
var o = {
"M+": oDate.getMonth() + 1, //月份
"d+": oDate.getDate(), //日
"h+": oDate.getHours(), //小时
"m+": oDate.getMinutes(), //分
"s+": oDate.getSeconds(), //秒
"q+": Math.floor((oDate.getMonth() + 3) / 3), //季度
"S": oDate.getMilliseconds()//毫秒
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (oDate.getFullYear() + "").substr(4 - RegExp.$1.length));
}
for (var k in o) {
if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
}
}
return fmt;
}
</script>
</html>