调查:是否还有玩家的手机浏览器是只能跑 Canvas 的呢?

好像不是没有webgl,有些是有,但是用不了,不知道为什么?,特别奇怪

webgl崩溃也会导致游戏无法使用webgl的

额,不是吧,webgl怎么用toDataURL。有相关资料么

我指的是类似烘培的功能,不是截全屏。

有些是引擎选的自动模式,自动模式下切换到 Canvas 了,其实强制用 WebGL 也问题不大

toDataURL 不就是截全屏幕吗?不然还有哪个 API?

支持今早抛弃过时的技术

1、 WebGL可以使用toDataURL,不过直接使用截出来的是黑屏,要在获取webgl的时候加preserveDrawingBuffer参数(对性能有影响)或者在cc.Director.EVENT_AFTER_DRAW事件中截图。相关链接:

2、 如果要截局部的图,目前可以使用cc.RenderTexture去截某个node及其所有子节点(有点不好用,需要一些hack代码去调整位置,据说2.0会有新的截图组件),然后:

// 以下width, height变量为局部截图的宽高
let rt = cc.RenderTexture.create(width, height, cc.Texture2D.PIXEL_FORMAT_RGBA8888, gl.DEPTH_STENCIL);
...... // 用rt截图
let texture = rt._texture._glID;
let frameBuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
// 每个像素点需要rgba四个值
let data = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);

// RenderTexture截出来的图是反向的,下面这段代码通过把data数组反向,来把图像反过来。
let halfHeight: number = Math.floor(height / 2);
let bytesPerRow: number = width * 4;
let temp = new Uint8Array(width * 4);
for (let y = 0; y < halfHeight; ++y) {
    let topOffset: number = Math.round(y * bytesPerRow);
    let bottomOffset = Math.round((height - y - 1) * bytesPerRow);
    temp.set(data.subarray(topOffset, topOffset + bytesPerRow));
    data.copyWithin(topOffset, bottomOffset, bottomOffset + bytesPerRow);
    data.set(temp, bottomOffset);
}
// RenderTexture截出来的图是反向的,上面这段代码通过把data数组反向,来把图像反过来。

gl.deleteFramebuffer(frameBuffer);

// 创建一个2D Canvas来保存截图结果
let canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
let context = canvas.getContext('2d');
let imageData = context.createImageData(width, height);
imageData.data.set(data);
context.putImageData(imageData, 0, 0);

// str即为截图结果
let str = canvas.toDataURL();
4赞

能提供一下相关代码吗… 谢谢了
我就是截图的时候截的是个黑的 所以用了canvas

这段代码挂在Canvas上,点击Canvas就能看到效果。

this.node.on(cc.Node.EventType.TOUCH_END, () => {
    cc.director.once(cc.Director.EVENT_AFTER_DRAW, () => {
        let canvas = document.getElementById('GameCanvas') as HTMLCanvasElement;
        let str = canvas.toDataURL();
        let img = new Image();
        img.onload = () => {
            let texture = new cc.Texture2D();
            texture.initWithElement(img);
            texture.handleLoadedTexture();
            let spriteFrame = new cc.SpriteFrame(texture);
            let spriteNode = new cc.Node();
            let sprite = spriteNode.addComponent(cc.Sprite);
            sprite.spriteFrame = spriteFrame;
            this.node.addChild(spriteNode);
            spriteNode.scale = 0.4;
        };
        img.src = str;
    });
});

多谢:kissing_heart:

我觉得可以忽略掉canvas了。就算支持了canvas又能怎么样呢?性能太差了,完全没法满足正常的需求。

支持去掉 Canvas :clap:

国产好多浏览器不支持webgl或者支持不太好,他们心里没有点逼数吗

1赞

在opp浏览器上 首次进来的时候 用webGL会启动报错 退出页面再重新进来就可以

可以根据5.0以下的占比来看。 不过,这是googleplay的。 要是能拿到微信的就更好了。

1赞

找到了 ·· 是deleteframebuffer的问题 去掉就可以了

cc.director.once(cc.Director.EVENT_AFTER_DRAW, () => {
var target = tar._sgNode;
//设置节点位置否则会在左下角
tar.opos = tar.getPosition();
tar.setPosition(tar.width/2,tar.height/2);

        // 以下width, height变量为局部截图的宽高
        var width = tar.width;
        var height = tar.height;
        // 用rt截图
        var rt = cc.RenderTexture.create(width,height,cc.Texture2D.PIXEL_FORMAT_RGBA8888, gl.DEPTH_STENCIL);
        rt.begin();
        rt.beginWithClear(0,0,0,0)
        target.visit();
        rt.end();
        tar.setPosition(tar.opos);

        let texture = rt._texture._glID;
        let frameBuffer = gl.createFramebuffer();
        gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
        // 每个像素点需要rgba四个值
        let data = new Uint8Array(width * height * 4);
        gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data);

        // RenderTexture截出来的图是反向的,下面这段代码通过把data数组反向,来把图像反过来。
        let halfHeight = Math.floor(height / 2);
        let bytesPerRow = width * 4;
        let temp = new Uint8Array(width * 4);
        for (let y = 0; y < halfHeight; ++y) {
            let topOffset = Math.round(y * bytesPerRow);
            let bottomOffset = Math.round((height - y - 1) * bytesPerRow);
            temp.set(data.subarray(topOffset, topOffset + bytesPerRow));
            data.copyWithin(topOffset, bottomOffset, bottomOffset + bytesPerRow);
            data.set(temp, bottomOffset);
        }
        // RenderTexture截出来的图是反向的,上面这段代码通过把data数组反向,来把图像反过来。
        //不知道什么原因这行会导致canvas整体被拉伸 但是删除这句话会导致画面固定 = =
        //gl.deleteFramebuffer(frameBuffer);

        // 创建一个2D Canvas来保存截图结果
        let canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        let context = canvas.getContext('2d');
        let imageData = context.createImageData(width, height);
        imageData.data.set(data);
        context.putImageData(imageData, 0, 0);

        // str即为截图结果
        var str = canvas.toDataURL('image/png');

});

1.9.3目前webgl可用的针对任意节点的截图方法(未完善)
deleteframebuffer后的canvas绘制有问题 输出查看canvas大小和缩放是正常的

如果有大佬有时间希望看看能给个方法不···

请单独发贴,不要挖坟