最近,开始从cocos2d-JS转移到creator开发中,其实之前有学习过Unity的开发,cocos creator的文档也大致看了一下,所以对于这种可视化编辑器,组件化开发方式也不陌生,API与cocos2d-JS的差异也不是很大.总的来说上手也不是很难. 很多人和我一样,遇到问题了会在网上搜一搜,学习一下别人的做法.殊不知新版的文档中早都已经透漏玄机.当然,文档有时候内容太多,有用的没用的一大堆,让人不能很快的定位到文档的位置. 而我这篇文章也是起到一个中转的作用.
好了,开始正题.
备注:代码是经过 cocos creator 2.1版本测试过的(2019.1.10)
首先我要讲的确是creator 新版本的 功能. 新的组件 Camera. 可能许多小伙伴已经看到了更新文档,没有看的小伙伴也赶快去看看吧.虽然,看了我的博客也可以学会,但是作为一个程序员,不看文档,不看API有点说不过去吧,兄弟 ----走--->cocos craetor 摄像机的使用
大家看文档,我就看看类的声明:
首先,继承Component那就是说和一般的组建没什么区别
其次render()函数,手动渲染,其实无非就是跟新了一下页面而已
最后,也是最重要的遍是targetTexture属性,可以让摄像机渲染到这个对象上去
这个页面我没有标注:就一个继承关系, 和两个函数, 都很重要
就这么搭眼一看,我就不屑一笑 哼, 小样,在这等我呢呀 !
你猜,我看到了什么!
继承Texture2D说明什么: 哼,我不知道啥是个Texture2D都可以(当然,还是知道的好),我知道这个能生成Sprite就够了.能生成sprite 还不是就任我拿捏了.各种风骚操作.截图动画就有保证了;
初始化函数initWithSize: 摄像机要拍照片,冲洗到我这个targeTexture上,我是给它多大的尺寸,就由这个函数决定了
readPixels: 什么, 还有这么个函数! 哎呀, 不重要,不重要,不重要. 不重要你说三遍. 唉,主要是返回值牛逼
读取像素数据,数据类型为 RGBA格式 Uint8Array 类型.
这不就是把每个像素的数据都出去来,一个颜色四个值,存到数组中了吗
说了这么多,其实是把截图这个功能 web平台和原生平台 相同点告诉大家了,当我们获取数据后,无非就是保存数据方式的一些差别,我想,接下来说说保存图的那点事.
说的我口干舌燥的,还是用代码说事吧
//统一代码
init(){
let node = new cc.Node();
node.parent = cc.director.getScene();
let camera = node.addComponent(cc.Camera);
// 设置你想要的截图内容的 cullingMask
camera.cullingMask = 0xffffffff;
// 新建一个 RenderTexture,并且设置 camera 的 targetTexture 为新建的 RenderTexture,这样 camera 的内容将会渲染到新建的 RenderTexture 中。
let texture = new cc.RenderTexture();
this.texture =texture ;
let gl = cc.game._renderContext;
// 如果截图内容中不包含 Mask 组件,可以不用传递第三个参数
texture.initWithSize(cc.visibleRect.width, cc.visibleRect.height, gl.STENCIL_INDEX8);
camera.targetTexture = texture;
// 渲染一次摄像机,即更新一次内容到 RenderTexture 中
camera.render();
// 这样我们就能从 RenderTexture 中获取到数据了
let data = texture.readPixels();
}
接下来就是保存图片的那些事了
jsb.fileUtils.getWritablePath() 获取路径
jsb.saveImageData 接口保存 简直就是为做截图而生的,
让人难以理解的是,读到的数据尽然还要自己去翻转, 这个,我觉得把,让我们自己翻转也不是不行, 但是何必赖! 程序员之间不是要互相关爱吗.又没有杀父之仇,夺妻之恨. 希望引擎能早点优化这一点把!
start () {
this.init();
this.schedule(() => {
let picData = this.initImage();
this.saveFile(picData);
}, 1, 0);
},
initImage () {
let data = this.texture.readPixels();
this._width = this.texture.width;
this._height = this.texture.height;
let picData = this.filpYImage(data, this._width, this._height);
return picData;
},
saveFile (picData) {
if (CC_JSB) {
let filePath = jsb.fileUtils.getWritablePath() + 'render_to_sprite_image.png';
let success = jsb.saveImageData(picData, this._width, this._height, filePath)
if (success) {
cc.log("save image data success, file: " + filePath);
}
}
},
// 搞不懂啊, 头都磕了,作揖却不愿意,非得自己翻转一下
filpYImage (data, width, height) {
// create the data array
let picData = new Uint8Array(width * height * 4);
let rowBytes = width * 4;
for (let row = 0; row < height; row++) {
let srow = height - 1 - row;
let start = srow * width * 4;
let reStart = row * width * 4;
// save the piexls data
for (let i = 0; i < rowBytes; i++) {
picData[reStart + i] = data[start + i];
}
}
return picData;
}
还是一样的问题,图片要翻转
start () {
this.init();
// create capture
this.schedule(() => {
this.createSprite();
this.saveFile ("图片名")
}, 1, 0);
}
createSprite () {
let width = this.texture.width;
let height = this.texture.height;
if (!this._canvas) {
this._canvas = document.createElement('canvas');
this._canvas.width = width;
this._canvas.height = height;
}
let ctx = this._canvas.getContext('2d');
this.camera.render();
let data = this.texture.readPixels();
// write the render data
let rowBytes = width * 4;
for (let row = 0; row < height; row++) {
let srow = height - 1 - row;
let imageData = ctx.createImageData(width, 1);
let start = srow * width * 4;
for (let i = 0; i < rowBytes; i++) {
imageData.data[i] = data[start + i];
}
ctx.putImageData(imageData, 0, row);
}
return this._canvas;
},
saveFile ( fileName){
//保存的方法前端有很多,这里暂时用这个
let data =this._canvas.toDataURL("image/png");
let save_link = document.createElement('a');
save_link.href = data;
save_link.download = fileName;
let event = document.createEvent('MouseEvents');
event.initEvent("click", true, false);
save_link.dispatchEvent(event);
}
小伙伴们发下什么问题,及时指正,互相学习.
关注弱势群体,关爱程序员!