Cocos Creator 實現截圖

王隆帥發表於2017-02-07

前言

Cocos Creator 現在還不是很完善,假如截圖截得是部分節點,所截圖物件會跑到左下角,官方提出的將 renderTexture 新增到場景中去,防止截圖時元素移動,親測這樣雖然截圖時物件不會移動但是截得圖有問題。

一、具體步驟

1、更改被截圖物件的錨點

經過測試,RenderTexture 截圖的時候會將被截圖的物件移到整個場景的左下角,然後根絕設定的 size ,以左下角為座標原點擷取,座標系的錨點是(0,0)。

所以,假如被截圖物件的錨點為(0.5,0.5),則只能擷取右上角的1/4。遂將被截圖物件的錨點設定為(0,0)。

2、新增一個虛假被截圖物件

經過測試,我發現被截圖物件被隱藏後,只要不在本次重新整理介面的時機被啟用,比如在下次重新整理介面的時候啟用,則會恢復到原位(這個啟用操作是必須做的,否則被移動的被截圖物件也不會恢復到原位!)。

基於這個測試結果,我的思路是:代替原被截圖物件,放置一個虛假精靈,在截圖的時候將擷取的圖顯示在這個虛假精靈中,替換原被截圖物件,同時隱藏被截圖物件。這樣就看不到被移動的被截圖物件了。然後在一個合適的時機,再啟用真實被截圖物件,隱藏虛假被截圖物件。

3、正式截圖

① 設定三個物件如下程式碼:

    properties: {

        // 被截圖物件 
        cocos: cc.Sprite,
        // 顯示截圖的精靈
        show: cc.Sprite,
        // 被截圖物件的虛假替身
        cocosImage: cc.Sprite,
    },複製程式碼

需要的注意的是:本例中虛假替身本身是在被截圖的物件的位置的,所以後續不需要設定位置。

② 截圖核心程式碼:

shot: function () {

        // 注意,EditBox,VideoPlayer,Webview 等控制元件無法被包含在截圖裡面
        // 因為這是 OpenGL 的渲染到紋理的功能,上面提到的控制元件不是由引擎繪製的

        if (CC_JSB) {

            // 建立 renderTexture
            var renderTexture = cc.RenderTexture.create(195, 270);

            //實際截圖的程式碼
            renderTexture.begin();
            this.cocos._sgNode.visit();
            renderTexture.end();

            // 獲取SpriteFrame
            var nowFrame = renderTexture.getSprite().getSpriteFrame();

            // 賦值給需要截圖的精靈
            this.show.spriteFrame = nowFrame;

            // 顯示虛假的代替精靈
            this.cocosImage.node.active = true;
            this.cocosImage.spriteFrame = nowFrame;

            // 翻轉得到的紋理
            var action = cc.flipY(true);
            this.show.node.runAction(action);

            var action1 = cc.flipY(true);
            this.cocosImage.node.runAction(action1);

            // 隱藏被截圖的物件
            this.cocos.node.active = false;
        }
    },複製程式碼

需要注意的:

i RenderTexture 得到的紋理是上下翻轉的,所以需要相應翻轉回來!假如不坐旋轉就會如下圖:

Cocos Creator 實現截圖

ii 想要截全屏,只要使用 Canvas 的節點即可,全屏的情況下不需要考慮虛假節點直接擷取即可,記得將初始化 RenderTexture 時,傳入的 size 為全屏的大小。

正常截圖完後的圖如下:

Cocos Creator 實現截圖

4、顯示原圖

之前也說了,需要在合適時機,啟用被截圖物件,並隱藏虛假被截圖物件,程式碼如下:

this.cocos.node.active = true;
this.cocosImage.node.active = false複製程式碼

二、其他事項

1、如果待截圖的場景中含有 mask,請使用下面註釋的語句來建立 renderTexture

var renderTexture = cc.RenderTexture.create(640,960, cc.Texture2D.PIXEL_FORMAT_RGBA8888, gl.DEPTH24_STENCIL8_OES);複製程式碼

2、把 renderTexture 新增到場景中去,否則截圖的時候,場景中的元素會移動。(確實不移動了,但是截部分節點得圖時有問題,假如哪位童鞋測試沒問題,希望能聯絡我...)

this.node.parent._sgNode.addChild(renderTexture);複製程式碼

3、把 renderTexture 設定為不可見,可以避免截圖成功後,移除 renderTexture 造成的閃爍

renderTexture.setVisible(false);複製程式碼

4、儲存所截的圖,並且列印其地址

// 儲存截圖到本地
renderTexture.saveToFile("demo.png", cc.IMAGE_FORMAT_PNG, true, function () {

            });

// 列印本地的地址   
cc.log(jsb.fileUtils.getWritablePath());複製程式碼

三、Demo

點選進入Demo

四、嘿嘿!你懂得!

本文首發於我的個人部落格,希望大家多多支援!

相關文章