经验分享:Creator 原生平台截屏方案

非动态创建的sprite,可以从renderTexture获得sprite
但是动态创建的sprite,调用sprite.node._sgNode.visit()方法,没有从renderTexture获得sprite。不管是否设置Visible属性为true或者false。cocos新人请教。具体的代码再您的demo例子上修改的如下:
cc.Class({
extends: cc.Component,

properties: {
    richText: cc.Component,
    sprite4:cc.Component
},

// use this for initialization
onLoad: function () {

},

captureScreen: function () {
    //注意,EditBox,VideoPlayer,Webview 等控件无法截图

       var self=this;
       var node = new cc.Node();
       node.parent =this.node;
       node.position = cc.v2(0, 0);
       self.sprite = node.addComponent(cc.Sprite);
       self.sprite.setVisible(false);
       cc.loader.loadRes("style/0", cc.SpriteFrame, function (err,spriteFrame ) {
             self.sprite.spriteFrame = spriteFrame;
         })
 
       node = new cc.Node();
       node.parent =this.node;
       node.position = cc.v2(60, 60);
       self.sprite2 = node.addComponent(cc.Sprite);
       self.sprite2.setVisible(false);
       cc.loader.loadRes("style/1", cc.SpriteFrame, function (err,spriteFrame ) {
             self.sprite2.spriteFrame = spriteFrame;
         })
         
         
        //如果待截图的场景中含有 mask,请开启下面注释的语句
        // var renderTexture = cc.RenderTexture.create(1280,640, cc.Texture2D.PIXEL_FORMAT_RGBA8888, gl.DEPTH24_STENCIL8_OES);
        var renderTexture = cc.RenderTexture.create(1280,640);

        //把 renderTexture 添加到场景中去,否则截屏的时候,场景中的元素会移动
        this.richText.node.parent._sgNode.addChild(renderTexture);
        //把 renderTexture 设置为不可见,可以避免截图成功后,移除 renderTexture 造成的闪烁
        renderTexture.setVisible(false);
         
         
        //实际截屏的代码
        renderTexture.begin();
        //this.richText.node 是我们要截图的节点,如果要截整个屏幕,可以把 this.richText 换成 Canvas 切点即可
        this.sprite.node._sgNode.visit();
        this.sprite2.node._sgNode.visit();
        //this.richText.node._sgNode.visit();
      
        renderTexture.end();
        //非动态创建的sprite,可以从renderTexture获得sprite
        //问题,动态创建的sprite,调用sprite.node._sgNode.visit()方法,没有从renderTexture获得sprite。不管是否设置Visible属性为true或者false。
    
  
       node = new cc.Node();
       node.parent = this.node;
       node.position = cc.v2(0, 0);
       var sprite5 = node.addComponent(cc.Sprite);
       sprite5.spriteFrame=renderTexture.getSprite().getSpriteFrame();//这里必须重新创建精灵,否则会报错  
       sprite5.node.setAnchorPoint(cc.p(0.3,0.3));  
    

      renderTexture.saveToFile("demo.png",cc.IMAGE_FORMAT_PNG, true, function () {
            //把 renderTexture 从场景中移除
            renderTexture.removeFromParent();
           cc.log("capture screen successfully!");
        }); 
        //打印截图路径
   
  
}

});

2赞

图片动态加载是异步的,cc.loader.loadRes那段代码的意思是,通知loader系统你想加载一个图片,让系统加载完之后执行回调(self.sprite2.spriteFrame=spriteFrame)。JS会继续直接往下执行截图代码,但此时图片还没加载好,就截不到了。所以应该把截图代码放到回调里,self.sprite2.spriteFrame=spriteFrame后面,因为这时候图片加载完成了。

1赞

分享的图片3M 有点大 这个是什么问题呢

请问 分享的图片过大怎么办 一个图片占了3M

@toddlxt 所说, cc.loader.loadRes 的回调是异步的,你的截图代码要放在回调里面。

下面是我稍微修改了一下你的代码:

        //注意,EditBox,VideoPlayer,Webview 等控件无法截图
        var self=this;
        var node = new cc.Node();
        node.parent =this.node;
        node.position = cc.v2(0, 0);
        self.sprite = node.addComponent(cc.Sprite);
        // self.sprite.setVisible(false);
        cc.loader.loadRes("style/0", cc.SpriteFrame, function (err,spriteFrame ) {
            self.sprite.spriteFrame = spriteFrame;

            node = new cc.Node();
            node.parent =self.node;
            node.position = cc.v2(60, 60);
            self.sprite2 = node.addComponent(cc.Sprite);
            // self.sprite2.setVisible(false);
            cc.loader.loadRes("style/1", cc.SpriteFrame, function (err,spriteFrame ) {
                self.sprite2.spriteFrame = spriteFrame;
                cc.log("sprite2 finished");
                //如果待截图的场景中含有 mask,请开启下面注释的语句
                // var renderTexture = cc.RenderTexture.create(1280,640, cc.Texture2D.PIXEL_FORMAT_RGBA8888, gl.DEPTH24_STENCIL8_OES);
                var renderTexture = cc.RenderTexture.create(1280,640);


                //实际截屏的代码
                renderTexture.begin();
                self.sprite.node._sgNode.visit();
                self.sprite2.node._sgNode.visit();

                renderTexture.end();


                node = new cc.Node();
                node.parent = self.node;
                node.position = cc.v2(0, 0);
                var sprite5 = node.addComponent(cc.Sprite);
                sprite5.spriteFrame=renderTexture.getSprite().getSpriteFrame();//这里必须重新创建精灵,否则会报错
                sprite5.node.setAnchorPoint(cc.p(0.3,0.3));
                node.scaleY = -1;


                renderTexture.saveToFile("demo.png",cc.IMAGE_FORMAT_PNG, true, function () {
                    cc.log("capture screen successfully!");
                });
            });
        });

1赞

另外,在截图的时候,sprite 的 visible 不能为 false,那样不会发送渲染指令的。

感谢,感谢,希望是不在界面上显示的也能通过Rendertexure 获得,这样做的目的是想 将多张图片合并成一张图片,再输出到界面上。看cocos2d-js 可以,如 http://blog.csdn.net/cuijiahao/article/details/49487375。请教下creator里能实现么,或者还有不用RenderTexure的方式么?感谢!

意思是web下无法截屏了?

找到了。
http://forum.cocos.com/t/creator/38461/15

1.4.1 beta 3
cc.IMAGE_FORMAT_PNG
js端 取不到。是改成什么了?
我现在直接赋值的1

腻害了,做成插件以后就直接使用了

还是会出现截图后,图跑到左下角的问题,是否是因为creator的坐标系的问题呐?截的图都是原图的右上角的1/4的部分。请问有没有知道是什么原因的

为什么1.4以后这个截屏方法不能用了

为什么我下载你的demo直接打包测试,不能截图呢?是哪里出错了吗?

1.4以后的不能用?那你知道现在怎么截图吗?

就是上面的代码,web上截图好使,ios上不能用

web上使用楼主的代码运行,CC_JSB一直是false啊!根本不执行操作

上面有个web使用的链接,jsb是用模拟器

应该是 cc.ImageFormat.PNG 不然jsb那边报错

1赞

你好!1.4版本截屏Canvas正常,但截屏Canvas下面的组件节点时,就出现游戏被截屏节点的画面在截屏后显示在屏幕左下角的情况。 CCRenderTexture.cpp 里面的 onEnd 函数的代码也是对的。