Skip to content

THING.UE.UWebView API 文档 进阶

前言

在实际项目应用中会遇到要在场景中创建几百甚至上千个顶牌,且样式不同,如果每一个顶牌都创建一个THING.Webview会造成严重的性能消耗。 这是因为,在ThingUE中,每创建一个Webview就创建一个内置浏览器进程,进程数量多了会出现帧率下降等情况。当进程数达到一定数量时,甚至出现显存溢出而导致程序崩溃。 webview进程 上图是创建了几个webview后,多出来的CEF进程。

这里提供一种创建大量顶牌的优化方案。

优化方案

这里采用类似图集资源(Atlas)的形式,图集(Atlas)也称作 Sprite Sheet,是游戏开发中常见的一种美术资源。图集是通过专门的工具将多张图片合并成一张大图。项目中采用雪碧图即可。

  • 将所有的顶牌元素(图标/图标+文字)都绘制到一个html页面中,即制作一张雪碧图。
  • 在雪碧图的页面创建JavaScript脚本,用来拆分小图
  • 在ThingUE中创建一个THING.UE.WebView,用来渲染这张雪碧图。
  • 在THING.UE.WebView直接调用JavaScript脚本,获取到拆分小图的结果
  • 根据获取到的结果,创建THING.Marker,并设置每个Marker的fixedSize 按上述步骤,雪碧图页面完成对小图的拆分,利用WebView可直接调用页面js特性,直接获取到小图的锚点信息,整个过程做到性能消耗最低。 下图是WebView初始化及调用html页面js方法的流程 流程图

雪碧图拆分效果

雪碧图显示在单个Marker上雪碧图拆分后显示在多个Marker上

创建雪碧图

页面可以是静态或动态页面 webview进程

创建js脚本,用来拆分页面小图

实例代码

javascript
//拆分小图的方法,这里的参数obj是ThingUE的Webview传过来的参数
function getHtmlElements(obj) {
    //window.ue是ThingUE中的Webview对象,只要是用Webview访问页面,window.ue便会存在,且window.ue被创建是在Webview被创建并且打开页面之后。
    if (window.ue && window.ue[obj]) {
        //获取页面小图的大小和位置信息,准备发送给ThingUE使用
        const icons = document.querySelectorAll('div.icon');
        let rects = [];
        icons.forEach(icon => {
            let box = icon.getBoundingClientRect();
            let rect = {
                left: box.left,
                right: box.right,
                top: box.top,
                bottom: box.bottom,
                height: box.height,
                width: box.width
            }
            rects.push(rect);
        });
        //访问到obj对象,并调用response方法将拆分完的数据传给webview,这将触发webView.executeJavascript函数的回调。
        window.ue[obj].response(JSON.stringify(rects));
    }
}

创建Webview

  • 创建一个webview
  • 在创建完成的回调里调用executeJavascript方法,获取到雪碧图中每个小图的位置、大小等数据
  • 遍历小图数据,创建Marker,调用webview.setWindow方法指定每个Marker都显示这个webview。
  • 设置Marker的fixedSize为获取到的小图的size;设置border为小图在大图中的锚点: [left,top,right,bottom]

示例代码如下,这里调用是上文示例代码中的getHtmlElements方法。executeJavascript方法有三个参数

  • 参数一:要调用的页面的js方法,getHtmlElements方法里传的参数要和executeJavascript方法的第三个参数一致,且要小写。
  • 参数二:页面的js方法执行完的回调,由参数三触发
  • 参数三:html中的回调路由器对象,在页面中可通过window.ue访问,该对象提供了response方法,调用该方法,页面可以将json字符串传给webview。具体使用方法参见上文的html页面的js脚本示例。
javascript
    //雪碧图的地址,这里是ThingUE的testcase里的一个示例页面
    let url = path.join(__dirname, '../../Modules/WebView/htmlPage/views/webview/index.html');
    const webView = new THING.UE.UWebView({
        domWidth: 960,
        domHeight: 480,
        url,
        complete: (url) => {
            //executeJavascript方法是Webview调用页面里的js方法,回调里是页面方法返回来的值,该方法要在创建webview完成的回调里执行
            //window.getHmlElements方法是页面端写的,用来获取到小图的rect信息
            webView.executeJavascript(`
                window.getHtmlElements(\'page1\');
            `, (str) => {
                let datas = JSON.parse(str);
                for (let i = 0; i < datas.length; i++) {
                    const divRect = datas[i];
                    //每个小图的大小
                    let size = [divRect.width, divRect.height];
                    //每个小图在大图中的锚点信息,是一个数组,存储的是小图 [left,top,right,bottom]占大图的比例
                    let border2 = [divRect.left / webView.domWidth, divRect.top / webView.domHeight, divRect.right / webView.domWidth, divRect.bottom / webView.domHeight];
                    let marker = new THING.Marker({
                        name: "webviewmarker1",
                        position: [i % 6 * 10 - 50, 20, Math.floor(i / 6) * 10],
                        scale: [10, 10, 10],
                        pivot: [0, 0],
                        alwaysOnTop: true,
                        complete: function ({ object }) {
                            object.node.renderer.renderLayer = THING.UE.URenderLayer.WebView;
                            // 设置当前marker可以作为webview输入窗口
                            webView.setWindow(object);
                            // 设置webview纹理
                            object.node.style.setImage("Map", webView.resource); 
                            // 设置Marker固定尺寸,设置成渲染div的尺寸
                            object.getBodyNode().fixedSize = size;
                            // 设置div在dom中的锚点 [left, top , right, bottom]
                            object.node.style.border = border2;   
                        },
                    });
                }
            }, 'page1');
        }
    });

京ICP备13053130号 京公网安备11010502050947号