微信小程序(以及THREE.js)场景导出成图片

微信小程序中type=webgl的canvas导出成base64图片

<canvas id="webgl" canvas-id="webgl" type="webgl" disable-scroll="{{true}}" bindtouchstart="touchstart"></canvas>
<image src='{{photoUrl}}'></image>
function createImg(){
    photoUrl = renderer.domElement._ctx.canvas.toDataURL('image/png');// jpg形式在真机上不支持透明背景
    self.setData({
    	photoUrl
	})
}

微信小程序base64图片和拍照的照片合成为一张图片

.webgl {
  position: absolute;
  z-index: 5;
  height: 100%;
  width: 100%;
}
.camera {
  position: absolute;
  z-index: 0;
  height: 100%;
  width: 100%;
}
<canvas id="webgl" canvas-id="webgl" type="webgl" disable-scroll="{{true}}" bindtouchstart="touchstart"></canvas>
<camera device-position="back" flash="off" frame-size="large" binderror="error" class="camera"></camera>
<canvas canvas-id="photo" style="width: {{photoSize.width}}rpx;height:{{photoSize.height}}rpx;left:-10000px;"></canvas>
<image class="photo" src='{{photoUrl}}'  style="width: {{photoSize.width}}rpx;height:{{photoSize.height}}rpx;"></image>
<view class="takephoto-btn" bindtap="takePhoto">拍照分享</view>
takePhoto(){
        let self = this;
        this.data.cameraContext.takePhoto({
            quality: "high",
            success: (res) => {   
                self.webglToPhoto(res.tempImagePath);
            },
        });
    },
   webglToPhoto(photo) {
        let self = this;
        const webglBase64 = this.createImg();
        const fs = wx.getFileSystemManager();
        const times = new Date().getTime();
        const codeimg = wx.env.USER_DATA_PATH + "/" + times + ".png";
        fs.writeFile({
            filePath: codeimg,
            data: webglBase64.slice(22),
            encoding: "base64",
            success: () => {
                      const ctx = wx.createCanvasContext("photo");
                      const {width, height} = self.data.sysInfo
                      ctx.drawImage(photo, 0, 0, width, height);

                      // 绘制codeimg时旋转180度
                      // ctx.translate(width, height);
                      // ctx.rotate((180 * Math.PI) / 180);
                      // 绘制codeimg的水平镜像
                      // ctx.translate(width,0);
                      // ctx.scale(-1,1);
                      // 绘制codeimg的垂直镜像(webgl生成的base64图片在canvas中绘制时会垂直颠倒)
                      ctx.translate(0,height);
                      ctx.scale(1,-1);
                      
                      ctx.drawImage(codeimg, 0, 0, width, height);
                      ctx.draw(true);// 已将照片和base64图片合成绘制到canvas中,但是canvas不支持缩放,故而显示成image,不显示canvas
                      self.canvasToImg(ctx, width, height);
            },
        });
    },
     canvasToImg(ctx, width, height) {
        let self = this;
        ctx.draw(
            true,
            setTimeout(() => {
                wx.canvasToTempFilePath({
                    quality: 1,
                    x: 0,
                    y: 0,
                    width: width,
                    height: height,
                    destWidth: width * wx.getSystemInfoSync().pixelRatio,
                    destHeight: height * wx.getSystemInfoSync().pixelRatio,
                    canvasId: "photo",
                    fileType: "png",
                    success(res) {
                        console.log("photo绘制成功");
                        wx.hideLoading({
                            success: (res) => {},
                        });
                        self.setData({
                            photoUrl: res.tempFilePath,
                        });
                    },
                    fail(err) {
                        wx.hideLoading({
                            success: (res) => {},
                        });
                    },
                    complete() {
                        wx.hideLoading({
                            success: (res) => {},
                        });
                    }, // end complete
                });
            }, 500)
        );
    },
    savePhoto() {
        let self = this;
        wx.saveImageToPhotosAlbum({
            filePath: this.data.photoUrl,
            success() {
                wx.showToast({
                    title: "图片已为您保存到本地",
                    icon: "none",
                });
            },
        });
    },

以上方法在安卓中好用,在IOS中toDataUrl得到的结果是data:;,故而不起作用。

IOS解决办法如下:

 <canvas id="webgl" canvas-id="webgl" class="webgl" type="webgl" disable-scroll="{{true}}">
    <canvas class="helper-canvas" type="2d" id="canvas"></canvas>
  </canvas>
  <view class="takephoto-btn" bindtap="takePhoto">拍照分享</view>
.helper-canvas {
  opacity: 0;
  display: block;
  position: absolute;
  top: 0;
  left: -100vw;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}
// 拍照相关
    takePhoto() {
        let self = this;
        wx.showLoading({
            title: "图片处理中...",
        });
        this.data.cameraContext.takePhoto({
            quality: "high",
            success: (res) => {
                // self.webglToPhoto(res.tempImagePath);
                self.webglToPhoto2(res.tempImagePath);
            },
        });
    },
    webglToPhoto2(photo){
        let self = this;
        const query = wx.createSelectorQuery();
        query.select('#canvas').fields({node: true,size: true}).exec((res)=>{
            self.clipWebgl(res[0].node, photo)
            .then(webglImg => {
                    const ctx = wx.createCanvasContext("photo");
   
               		 const {width, height} = self.data.sysInfo
                    ctx.drawImage(photo, 0, 0, width, height);
                    ctx.drawImage(webglImg.path, 0, 0, width, height);
                    ctx.draw(true);
                    self.canvasToImg(ctx, width, height);
                    .....
            });
        })
        return;
    },


 //  处理IOS的新增部分
function clipWebgl(helperCanvas,photo){
    return new Promise((resolve,reject) => {
        const [data, w, h] = screenshot(renderer, scene, camera, THREE.WebGLRenderTarget);
        const ctx = helperCanvas.getContext('2d')
        const imgData = helperCanvas.createImageData(data, w, h);
        helperCanvas.height = imgData.height;
        helperCanvas.width = imgData.width;

       // var data_len = w * h * 4;
        // var srcPixels = imgData.data;
        // for (var i = 0; i < data_len; i += 4) {
        //     if (srcPixels[i] > 0 || srcPixels[i + 1] > 0 || srcPixels[i + 2] > 0)
        //         srcPixels[i + 3] = 255;
        // }

        ctx.putImageData(imgData, 0, 0);

        wx.canvasToTempFilePath({
            canvas: helperCanvas,
            success(res) {
                resolve({path: res.tempFilePath, width: imgData.width, height: imgData.height})
            },
            fail(err){
                reject(err);
            }
        })
    })
}
function screenshot(renderer, scene, camera, WebGLRenderTarget) {
  const { width, height } = renderer.domElement;
  // const { x: width, y: height } = renderer.getDrawingBufferSize();
  const renderTarget = new WebGLRenderTarget(width, height);
  const buffer = new Uint8Array(width * height * 4);

  renderTarget.texture.encoding = renderer.outputEncoding;
  renderer.setRenderTarget(renderTarget);
  renderer.render(scene, camera);
  renderer.readRenderTargetPixels(renderTarget, 0, 0, width, height, buffer);
  renderer.setRenderTarget(null);
  renderTarget.dispose();

  flip(buffer, width, height, 4);
  return [buffer, width, height];
}
function flip(pixels, w, h, c) {
  // handle Arrays
  if (Array.isArray(pixels)) {
    var result = flip(new Float64Array(pixels), w, h, c);
    for (var i = 0; i < pixels.length; i++) {
      pixels[i] = result[i];
    }
    return pixels;
  }

  if (!w || !h) throw Error('Bad dimensions');
  if (!c) c = pixels.length / (w * h);

  var h2 = h >> 1;
  var row = w * c;
  var Ctor = pixels.constructor;

  // make a temp buffer to hold one row
  var temp = new Ctor(w * c);
  for (var y = 0; y < h2; ++y) {
    var topOffset = y * row;
    var bottomOffset = (h - y - 1) * row;

    // make copy of a row on the top half
    temp.set(pixels.subarray(topOffset, topOffset + row));

    // copy a row from the bottom half to the top
    pixels.copyWithin(topOffset, bottomOffset, bottomOffset + row);

    // copy the copy of the top half row to the bottom half
    pixels.set(temp, bottomOffset);
  }

  return pixels;
};

THREE.js场景导出成图片

 function downloadImage(imgUrl){
            var a = document.getElementById('img');
            a.href = imgUrl;
            a.click();
        }
    setTimeout(()=>{
        var url = renderer.domElement.toDataURL('image/jpeg')
        downloadImage(url)
    },2000);

代码片段:
https://developers.weixin.qq.com/s/tkXh0Ams7FvD

这里有时候会出现一个问题:安卓端生成的图片是清晰的,IOS端生成的图片很模糊,像马赛克,在css里对helper-canvas设置width,height可以解决这个问题

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值