一谅年、cocos2dx視圖層級介紹
? ? ? ? 不管在Android茧痒、IOS、還是h5平臺踢故,videoview與webview永遠都是壓在游戲視圖之上的文黎,所以當(dāng)我們在項目內(nèi)添加組件webView或者videoPlayer的時候,你會發(fā)現(xiàn)殿较,這兩個view會無視當(dāng)前canvas節(jié)點的層級永遠顯示在最上面耸峭,以Android舉例,為什么會是這樣子
首先查看文件Cocos2dxActivity.java淋纲,發(fā)現(xiàn)如下代碼
其中init添加了游戲視圖
Cocos2dxWebViewHelper.java在如下函數(shù)中添加了webview圖層
????而Cocos2dxVideoViewHelper.java在如下函數(shù)中添加了視頻圖層劳闹,并且設(shè)置為最上層
????按照視圖繪制順序,越先繪制的圖層再越下面洽瞬,而且本涕,視頻圖層VideoView將之層級設(shè)置為Top,所以伙窃,正常情況下菩颖,游戲圖層是被壓在視頻圖層與網(wǎng)頁圖層之下的。
二为障、在視頻上添加按鈕或其他內(nèi)容
? ? 這是個很普遍的需求晦闰,即使你現(xiàn)在正常做的項目沒有這樣的需求,但是只要你一直從事這一行鳍怨,就一定會遇到呻右。
? ??首先思考一下,我們想在視頻上添加其他UI鞋喇,并且能夠與這些UI進行交互宁否,那么必然需要能夠接收到用戶的觸控事件徙鱼,假如游戲圖層上方有其他圖層A怠李,那么必然是A接收并阻攔掉觸控事件弥奸,所以,我們先將游戲視圖的層級放到視頻視圖之上鄙皇。
? ? 然后游戲視圖默認(rèn)是黑色的芜赌,如果蓋在視頻之上,那么視頻也就看不到了伴逸,所以我們還需要將游戲視圖默認(rèn)背景設(shè)置透明缠沈。
? ? 1、h5的實現(xiàn)
? ? ? ? ? ? video0.style.zIndex = -1 說明視頻層級放在最下層
? ? ? ? ? ? c.Camera.main.backgroundColor 設(shè)置游戲視圖背景透明,
? ? ? ? ? ? setClearColor說明刷新的背景板顏色也為透明
? ? 2洲愤、Android的實現(xiàn)
? ? Cocos2dxVideoHelper._createVideoView 內(nèi)颓芭,將設(shè)置視頻層級最高的代碼刪除
? ? Cocos2dxActivity.onCreateView 內(nèi),設(shè)置游戲視圖層級最高
? ? AppActivity.onCreateView 內(nèi)柬赐,將游戲視圖背景設(shè)置為透明
? ? 3亡问、IOS實現(xiàn)
? ? CCApplication-ios.onCreateView中,將視圖背景設(shè)置為透明
? ? AppController中肛宋,修改代碼州藕,先繪制視頻圖層、再繪制游戲圖層
? ? 4酝陈、IOS兼容處理
? ? ? ?在creator 2.1.2之前的版本床玻,ios用戶展示視圖的控件為MediaPlayer,該控件在IOS往上的設(shè)備已經(jīng)棄用了沉帮,需要手動升級到AVPlayerViewController锈死, 更高版本的creator已經(jīng)替換了,不需要處理穆壕。
? ? 5待牵、引擎底層c++處理
? ? 如果做過渲染這塊的同學(xué)應(yīng)該知道,我們的游戲場景之所以會在屏幕上展示出連續(xù)的畫面喇勋,是因為有類似這樣的代碼
? ? while (true){
? ? ? ? draw()
????}
? ? draw里面一般是刷新我們的視圖內(nèi)容缨该,因為是一個循環(huán)的過程所以我們會不停刷新形成動態(tài)畫面。
? ? 而一般在刷新之前川背,我們需要刪除上一幀的殘留畫面压彭,cocos在代碼上表現(xiàn)在這里
? ? ? ? clearColor函數(shù)在每次繪制一開始,將上一幀的畫面擦干凈渗常,引擎之前是1,1,1,1,也就是純黑色汗盘,我們把刷新的alpha值改為 0皱碘,這樣就能通過glsurfaceView 透視到下面的視頻圖層了
至此 項目中的視頻會作為背景存在于游戲視圖之下,你可以在上面添加UI了隐孽。
三癌椿、在WebView上面加按鈕
? ? 如果你沒有經(jīng)驗,那么你首先想到的可能是調(diào)整WebView層級菱阵,當(dāng)然踢俄,最終可以順利的實現(xiàn)這個效果,但是這種方案最終會帶來一個致命的問題:
? ? 一般webview承載的內(nèi)容為有許多交互內(nèi)容晴及,例如按鈕都办。webview放置于glView之下,那么glView將完全攔截點擊事件,我們只能觀看它琳钉。
? ? 1势木、在webView上面添加webView
? ? ? ? 看到這,你應(yīng)該知道我想說什么歌懒。沒錯啦桌,webview與webview是同一層級的圖層,后面添加的webview當(dāng)然會覆蓋在之前的上面及皂。
? ? ? ? 2甫男、將后添加的webview當(dāng)作按鈕來用
? ? ? ? 以上圖為例,webviewBtn1加載的是一個網(wǎng)頁 http://xxx.html验烧,而這個網(wǎng)頁的內(nèi)容板驳,就是一張全屏幕的按鈕圖片。
? ? ? ? 上圖是兩個webview噪窘。
? ? ? ? 3笋庄、相應(yīng)webview的點擊事件
? ? ? ? 首先,在webview的node節(jié)點上倔监,添加button是不行的直砂,因為button屬于游戲?qū)蛹墸趙ebview層級之下浩习,我們是無法通過button接收到的静暂,我們只能通過接收webviewBtn內(nèi)網(wǎng)頁的內(nèi)容來達到我們的目的。
? ? ? ? h5平臺谱秽,這個webviewBtn該這么響應(yīng)洽蛀,當(dāng)然這種方式不用遇到跨域的問題,請放心:
// webviewBtn.html?點擊后疟赊,觸發(fā)動作
document.location = 'close://hahaha=1';
// 在h5客戶端郊供,得到響應(yīng)
window.addEventListener("message", (e) =>{
? ??if (e.data == "close") {
? ??????// do something
? ? }
}
? ? ????再來看看原生平臺該如何響應(yīng)
//?webviewBtn.html?點擊后,觸發(fā)動作
parent.postMessage("close", '*');
// 在原生客戶端近哟,得到響應(yīng)
var jsCallback = function (sender, str) {
? ??// do something
}
// this.btn驮审,為webViewBtn的cc.WebView組件
this.btn.setJavascriptInterfaceScheme("close")
this.btn.setOnJSCallback(jsCallback)
? ? ????至此,你可以在webview上自由添加按鈕了
????4吉执、與videoView的兼容處理
? ? ? ? 如果你不需要在自己的項目處理videoView的話疯淫,那么在第3步的時候,你已經(jīng)完成了webview部分的功能戳玫。但是如果你在自己的項目內(nèi)同時使用兩套方案熙掺,那么請繼續(xù)往下看。
? ? ? ? 首先為了能夠在視頻上添加ui等內(nèi)容咕宿,我們在Android平臺上币绩,將游戲圖層設(shè)置為最上了蜡秽,所以,它一定是覆蓋在webview之上的类浪,我是這么解決Android平臺的問題的:
// 進入webview時
glSurfaceView.setZOrderOnTop(false);
// 離開webview時
glSurfaceView.setZOrderOnTop(true);
四载城、webview加載部分網(wǎng)頁的兼容處理
????cocoscreator2.1.2以下的webview,在原生設(shè)備上加載某些網(wǎng)頁會崩潰费就,需要升級使用webkit诉瓦,具體的升級方式請參考creator最新版本的源碼,或者在開發(fā)的時候使用最新版本的引擎力细。
????PS:筆者截稿時睬澡,creator最新版本為2.3.1,由于剛發(fā)布眠蚂,穩(wěn)定性未知煞聪。而據(jù)筆者了解2.3.0的版本又有許多bug待解決。所以最穩(wěn)定版本為哪個也不好說逝慧,但是不管用哪個版本昔脯,通過合并fix保證自己的creator最穩(wěn)定總是沒錯的。
筆者的方案不是demo笛臣,有正在線上運營的項目為保證云稚,請放心食用。文章可能比較粗糙沈堡,有問題或者建議可以留言或私信静陈。