<!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: 0px 0 0 0px; width: 1px; height: 1px; border: 1px solid white; z-index: -1; } .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; } .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"></div> <div id="operate" class="operate" style="display: none"> <!--初始化、反初始化、设置认证信息接口调用入口。 1.插件所有接口都需要在调用初始化并返回成功后才能调用 2.设置认证信息仅适用于对接多平台时的情况,具体参照开发指南 3.反初始化后,插件资源销毁--> <div class="module" style="left:30px;height:30px;width:280px;padding:10px;margin:10px;"> <div class="item"> <label >初始化相关参数:</label> <textarea id="initParam" type="text" style="width:260px;height:200px;"> { "argument": { "appkey": "25766251", "ip": "192.168.1.22", "port": 443, "secret": "h2o6zXtzCmt8eaOaMkXb", "enableHTTPS": 1, "layout": "1x1", "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:30px;width:280px;padding:10px;margin:10px;"> <div class="item"> <label >播放相关参数:</label> <textarea id="playParam" type="text" style="width:260px;height:200px;"> { "argument": { "cameraIndexCode": "2a617f752fbe4c68989e8d3975cf58f9", "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:50px;width:300px;padding:10px;margin:10px;"> <legend>返回值信息</legend> <div id="cbInfo" class="cbInfo"></div> <button style="width:80px;height:24px;padding:30px;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 const winHeight = document.documentElement.clientHeight; const winWidth = document.documentElement.clientWidth - 50; // 标签关闭 $(window).unload(function () { if (oWebControl != null){ oWebControl.JS_HideWnd(); // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题 oWebControl.JS_Disconnect().then(function(){}, function() {}); } }); function hide(){ oWebControl.JS_HideWnd(); }; function show(){ oWebControl.JS_ShowWnd(); }; // 步骤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(parseInt(winWidth), parseInt(winHeight)); 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(parseInt(winWidth), parseInt(winHeight)); 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, parseInt(winWidth) + 1, parseInt(winHeight) + 1); // 多1个像素点防止还原后边界缺失一个像素条 // if(iframeClientPos){ // 判断剪切矩形的上边距 if (iframeClientPos.top < 0 && Math.abs(iframeClientPos.top) > divTop){ var deltaTop = Math.abs(iframeClientPos.top) - divTop; oWebControl.JS_CuttingPartWindow(0, 0, parseInt(winWidth) + 1, 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, parseInt(winHeight) + 1); // 多剪掉一个像素条,防止出现剪掉一部分窗口后出现一个像素条 } // 判断剪切矩形的右边距 var W1 = iframeWndWidth - divRight; var W2 = iframeParentShowSize.width - iframeClientPos.left; if (W2 < divWidth){ var deltaRight = iframeWndWidth - W2 - W1; if (deltaRight > 0) { oWebControl.JS_CuttingPartWindow(parseInt(winWidth) - deltaRight, 0, deltaRight + 1, parseInt(winHeight) + 1); } } // 判断剪切矩形的下边距 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, parseInt(winHeight) - deltaBottom, parseInt(winWidth) + 1, deltaBottom + 1); } } // } } // 创建插件实例,并启动本地服务建立websocket连接,创建插件窗口 function initPlugin (type,num,top) { 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", parseInt(winWidth), parseInt(winHeight), { 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(type); }); }, 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(type); }, 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; } }); if(oWebControl!=null) { var height if(type==="real"){ height = 200 }else if(type === "back"){ height = 280 }else{ height = top } oWebControl.JS_SetDocOffset({ left: num, top: height }); setWndCover(); } } // 回访 function search(cameraIndexCode, startTimeStamp, endTimeStamp){ var startTimeStamp = Date.parse(new Date(startTimeStamp)); var endTimeStamp = Date.parse(new Date(endTimeStamp)); console.log(startTimeStamp,endTimeStamp) var recordLocation = 1; //录像存储位置:0-中心存储,1-设备存储 var transMode = 1; //传输协议:0-UDP,1-TCP var gpuMode = 0; //是否启用GPU硬解,0-不启用,1-启用 var wndId = -1; //播放窗口序号(在2x2以上布局下可指定播放窗口) oWebControl.JS_RequestInterface({ funcName: "startPlayback", argument: JSON.stringify({ cameraIndexCode: cameraIndexCode, //监控点编号 startTimeStamp: Math.floor(startTimeStamp / 1000).toString(), //录像查询开始时间戳,单位:秒 endTimeStamp: Math.floor(endTimeStamp / 1000).toString(), //录像结束开始时间戳,单位:秒 recordLocation: recordLocation, //录像存储类型:0-中心存储,1-设备存储 transMode: transMode, //传输协议:0-UDP,1-TCP gpuMode: gpuMode, //是否启用GPU硬解,0-不启用,1-启用 wndId:wndId //可指定播放窗口 }) }) } function requestInterface(value) { oWebControl.JS_RequestInterface(JSON.parse(value)).then(function (oData) { console.log(oData) showCBInfo(JSON.stringify(oData ? oData.responseMsg : '')); }); } $("#initBtn").click(function() { initBtnClicked(); }) function initBtnClicked(type){ // var param = $("#initParam").val(); var mode = type === "real"?0:1 var param = '{\n' + ' "argument": {\n' + ' "appkey": "25766251",\n' + ' "ip": "192.168.1.22",\n' + ' "port": 443,\n' + ' "secret": "h2o6zXtzCmt8eaOaMkXb",\n' + ' "enableHTTPS": 1,\n' + ' "layout": "1x1",\n' + ' "playMode": ' + mode + '},\n' + ' "funcName": "init"\n' + '}' //删除字符串中的回车换行 param = param.replace(/(\s*)/g, ""); // 执行初始化 requestInterface(param); } $("#playBtn").click(function() { play() }) function play(cameraIndexCode) { // var param = $("#playParam").val(); // console.log("控件读取:" + param); var param = '{"argument": ' + '{"cameraIndexCode": "'+cameraIndexCode+'","ezvizDirect": 0,"gpuMode": 0,"streamMode": 0,"transMode": 1,"wndId": -1},"funcName": "startPreview"}'; console.log("非控件读取:" + param); //删除字符串中的回车换行 param = param.replace(/(\s*)/g, ""); // 执行预览 requestInterface(param); }; // 获取公钥 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 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()); } // 清空 $("#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>