赞
请问为什么不直接就用这一句呢,不管有没有cc.Mask?
这个比较消耗内存一些,所以没有 mask 节点的截图,为了省内存,还是不要这样做。
好的,谢谢!
那个,我的需求比较多一点。之前我测试过截取某个node的图像。我想问问。
第一: 这个只是截屏,就是完整的一个屏幕。即position在0 0点。
但是如果我只想接截取某个其他位置的node的contensize区域呢?
比如我有一个node放在屏幕中央,大小只有100x100。然后我就想截取这个node和它上面所有子节点的图像,只需要node那100x100的范围。
我测试过,如果position不在 0 0点,大小不是全屏,那还挺麻烦的。
用这个老方法:render.setVirtualViewport(origin, fullRect, virtualViewPort)。我试了好久都没搞出来。
伪代码如下:
var render = new cc.RenderTexture(size.width, size.height, cc.Texture2D.PIXEL_FORMAT_RGBA8888, gl.DEPTH24_STENCIL8_OES);
var origin = cc.p(0, 0);
var fullRect = cc.rect(x,y, size.width, size.height);
var virtualViewPort = cc.rect(x, y, size.width * 2, size.height * 2);
render.setVirtualViewport(origin, fullRect, virtualViewPort);
render.begin();
this.backgroundLayer_.visit();
render.end();
setVirtualViewport我以为可以调整截取的区域,结果怎么都达不到效果。
第二,截取生成的renderTexture,我没找到方法来生成sprite使用。图像已经在内存中,但是没办法取出来吗?
第三,renderTexture和 texture2D是什么关系,如果能转换,就能生成spriteFrame,设定截取的rect。可以任意切割,自定义性就强很多。能做很多事情。
我用了这个代码截屏
screenShoot(func){
if (!cc.sys.isNative) return;
let dirpath = jsb.fileUtils.getWritablePath() + 'ScreenShoot/';
if( !jsb.fileUtils.isDirectoryExist(dirpath)){
jsb.fileUtils.createDirectory(dirpath);
}
let name = 'ScreenShoot-' + (new Date()).valueOf() + '.png';
let filepath = dirpath + name;
let size = cc.winSize;
let rt = cc.RenderTexture.create(size.width, size.height);
cc.director.getScene()._sgNode.addChild(rt);
rt.setVisible(false);
rt.begin();
cc.director.getScene()._sgNode.visit();
rt.end();
rt.saveToFile('ScreenShoot/' + name, cc.IMAGE_FORMAT_PNG, true, function() {
cc.log('save succ');
rt.removeFromParent();
if (func) {
func(filepath);
}
});
return filepath;
},
截出来的图片是正确的,但是android平台,游戏界面往左下角缩小了,上面的按钮的响应区域没变。有人遇见过吗?
你把 let size=cc.winSize
改成 let size = cc.director.getVisibleSize()
修改后无效。
目前 native 的截屏可能有些 bug,Android 平台和 mac 模拟器截屏完后,viewport 的大小有问题,会导致游戏画面在截屏后显示在左下角:
可以通过修改 CCRenderTexture.cpp 里面的 onEnd 函数来 hack 一下:
void RenderTexture::onEnd()
{
Director *director = Director::getInstance();
glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO);
// restore viewport
director->setViewport();
//
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, _oldProjMatrix);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _oldTransMatrix);
}
建议做成插件哈
正在考虑做成插件中。
子龙大大。我这边也一样也遇到这个问题了 版本1.3.1 查看RenderTexture::onEnd源码 director->setViewport();这句是已经有加的。但是还是截图后整个画面缩小到左下角。。请问还有什么方法可以解决这个问题。
复制我上面的代码就好了呀
你的代码跟我的不一样啊,去掉 glViewport 的调用。
ok了。谢谢。。我以为是要加上那句glViewport。。
厉害了 我的子龙大神~
请问第二问题解决了吗
我参照上面的方法 (截图的场景中含有 mask ) 也是用注释的部分来创建 renderTexture ;但是在大多手机上好的 在opp有的型号的手机上截屏 还是缺少元素,很多地方都是白色的 什么原因啊 求解决@子龙山人
非动态创建的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!");
});
//打印截图路径
}
});