@1076984375 写道:
我们知道creator里的WebView,VideoPlayer等特殊组件有一个非常严重的问题,就是不管你怎么设置层级,这类组件始终处于最上层!其他UI组件会被遮挡。
我们打开浏览器运行,F12检测元素就可以清楚的看到他们的层级关系。
如下图:
通过上图我们可以清楚的看到,video(videoPlayer组件) 和 iframe(webView组件) 在 canvas(GameCanvas) 上层,而我们creator内置UI组件都是在GameCanvas层渲染的,所以不管我们怎么改UI层级都无效。
解决方案可以参考我之前的一篇文章: videoPlayer组件一直处于在最上层的问题
其实除了上述的办法,还有一个解决方案,就是我们可以通过自己写一个简单的html页面来中转!
大致思路:
首先我们自己用 nginx 搭建一个简单的 html 页面,在通过 webView组件加载我们自己的web页面,然后在我们自己的页面加载一些需要的video或者其他网页,一些需要显示在Video组件上层的组件我们就可以通过html标签来实现了(需要一点web知识),然后和creator JS交互就可以了。
如何与 WebView 内部页面进行交互呢?:
可以参考一下
官方文档个人感觉官方文档讲得不够全面。
我的实现如下:
首先我们先来看下官方的:
我们可以看到,Web平台上会出现跨域的问题,所以我们需要分别对web平台和移动平台做处理,
web平台:
在Web上我们可以通过 window.postMessage 实现跨域消息传递:
cocos 发送消息到 web:
this.webView._sgNode._renderCmd._iframe.contentWindow.postMessage(data, "*"); //如果因为版本原因 _sgNode 被舍弃了,可以换成以下 this.webView._impl._iframe.contentWindow.postMessage(data, "*");
这里需要注意的是:我们必须等webView加载完成之后才能发送。
html JS:
//接收来自cocos的消息 window.addEventListener('message', function (e) { var data = e.data;//参数 console.log("-----------message--------------", data) });
web 发送消息到 cocos:
html JS:
//browser 浏览器下,向cocos发送消息 parent.postMessage("------------hello!-----cocos---------", "*")
cocos JS:
if (cc.sys.isBrowser) { //这里是浏览器环境下, 接收web传过来的消息 window.addEventListener('message', function (e) { console.log("----cocos---",e.data); }) }
演示如下:
以上是运行在浏览器环境下的交互
移动平台:
移动平台下就和官网的区别不大了。
首先需要初始化:
//初始化 init() { // 这里是与内部页面约定的关键字,请不要使用大写字符,会导致 location 无法正确识别。 var scheme = "testkey"; //这里是移动端, 接收web传过来的消息 function jsCallback(target, url) { // 这里的返回值是内部页面的 URL 数值,需要自行解析自己需要的数据。 var str = url.replace(scheme + '://', ''); // str === 'a=1&b=2' // webview target console.log("jsCallback-------str-------", str); window.closeWebView(target, url); } this.webView.setJavascriptInterfaceScheme(scheme); this.webView.setOnJSCallback(jsCallback); //web window.closeWebView = this.closeWebView.bind(this); },
cocos 发送消息到 web:
cocos JS:
let data = { id:123456 } data = JSON.stringify(data); //注意这里需要把参数序列化 //调用web页面 定义的全局函数 this.webView.evaluateJS("setBackgroundColor(" + data + ")");
web 发送消息到 cocos :
function onClick() { console.log("-------web--------onClick----->>cocos JS-------------", window.isNative) //android or ios document.location = 'testkey://a=1&b=2' }
demo完整代码:
if (cc.sys.isBrowser) { //这里是浏览器环境下, 接收web传过来的消息 window.addEventListener('message', function (e) { console.log("----cocos---",e.data); window.closeWebView(e); }) } cc.Class({ extends: cc.Component, properties: { webView: cc.WebView, debugText: cc.Label }, start() { this.setDebugText("start.....") this.webView.url = "web ip 地址"; // 如: "http://127.0.0.1:8190/web/" this.init(); }, init() { // 这里是与内部页面约定的关键字,请不要使用大写字符,会导致 location 无法正确识别。 var scheme = "testkey"; //这里是移动端, 接收web传过来的消息 function jsCallback(target, url) { // 这里的返回值是内部页面的 URL 数值,需要自行解析自己需要的数据。 var str = url.replace(scheme + '://', ''); // str === 'a=1&b=2' // webview target console.log("jsCallback-------str-------", str); window.closeWebView(target, url); } this.webView.setJavascriptInterfaceScheme(scheme); this.webView.setOnJSCallback(jsCallback); //web window.closeWebView = this.closeWebView.bind(this); }, setDebugText(str) { this.debugText.string = str }, //绑定按钮 cocosToWeb() { let data = { width: this.webView.node.width, height: this.webView.node.height, isNative: cc.sys.isNative, color:"#FF9800" } let text; console.log("------cocos------data-----------", data) //浏览器 if (cc.sys.isBrowser) { console.log("-----cocos------Browser---------"); text = "-----cocos------Browser---------"; this.webView._sgNode._renderCmd._iframe.contentWindow.postMessage(data, "*"); //如果因为版本原因 _sgNode 被舍弃了,可以换成以下 //this.webView._impl._iframe.contentWindow.postMessage(data, "*"); } //移动端 else if (cc.sys.isNative) { console.log("-----cocos------Native---------"); text = "-----cocos------Native---------"; data = JSON.stringify(data); //setBackgroundColor 是 web 全局函数, data 参数 this.webView.evaluateJS("setBackgroundColor(" + data + ")"); } this.webView.node.active = true; this.setDebugText(text) }, //关闭WebView closeWebView(e, url) { this.webView.node.active = false; this.setDebugText("--------cocos-----close----webView-------" + url); }, //事件 onWebFinishLoad: function (sender, event) { if (event === cc.WebView.EventType.LOADED) { this.setDebugText("----webView---loaded---finish!!----") this.cocosToWeb() } else if (event === cc.WebView.EventType.LOADING) { this.setDebugText("----webView---loading----") } else if (event === cc.WebView.EventType.ERROR) { this.setDebugText("----webView---load---error----") } }, });
Html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>cocos web</title> <style> body { margin: 0; padding: 0; background: rgb(94, 94, 94); } div { width: 100%; height: 50px; position: absolute; margin: auto; left: 0; right: 0; bottom: 0; text-align: center; font-size: 30px; } iframe{ width: 50%; height: 80%; position: absolute; margin: auto; left: 0; right: 0; top: 0; text-align: center; font-size: 30px; } button { position: absolute; width: 200px; height: 30px; background: red; top: 2px; right: 20%; border: 0; } </style> </head> <body> <iframe id="iframeID" src="http://www.baidu.com" frameborder="0"></iframe> <div id="text"></div> <button type="button" onclick="onClick()">触发cocos 关闭webView</button> </body> <script> let iframeWeb = document.getElementById("iframeID"); // ---------------browser-------need-------- window.addEventListener('message', function (e) { var data = e.data; //e.data 里面有自己所传的所有参数 可以根据参数做自己的判断 console.log("--------------this is web message--------------", data) setBackgroundColor(data); }); // ---------------browser--------------- function setBackgroundColor(data) { console.log("-------web--------data-------" + data) window.isNative = data.isNative; document.getElementsByTagName("body")[0].style.background = data.color; document.getElementById("text").innerHTML = "this is cocos send msg color :" + data.color; document.getElementById("iframeID").innerHTML = "this is cocos send msg color :" + data.color; // setIframeSize(data) } function setIframeSize(data){ if (data.isNative) { //----------mobile--------- let cocosIframe = window.parent.document.documentElement; console.log("-----mobile--web-------size------" + cocosIframe.clientWidth + "---" + cocosIframe.clientHeight); iframeWeb.style.width = cocosIframe.clientWidth + "px"; iframeWeb.style.height = cocosIframe.clientHeight + "px"; }else{//----------browser--------- console.log("----browser---web-------size------" + data.width + "---" + data.height); iframeWeb.style.width = data.width + "px"; iframeWeb.style.height = data.height + "px"; } } function onClick(param) { console.log("-------web--------onClick----->>cocos JS-------------", window.isNative) if (window.isNative) { //android or ios document.location = 'testkey://a=1&b=2' } else { //browser 浏览器下,向cocos发送消息 parent.postMessage("------------hello!-----cocos---------", "*") } } </script> </html>
end!
帖子: 1
参与者: 1