当前位置:   article > 正文

微信小程序(以及THREE.js)场景导出成图片_微信小程序three.js webgl 保存图片

微信小程序three.js webgl 保存图片

微信小程序中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
	})
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

.webgl {
  position: absolute;
  z-index: 5;
  height: 100%;
  width: 100%;
}
.camera {
  position: absolute;
  z-index: 0;
  height: 100%;
  width: 100%;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
<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",
                });
            },
        });
    },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

以上方法在安卓中好用,在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>
  • 1
  • 2
  • 3
  • 4
.helper-canvas {
  opacity: 0;
  display: block;
  position: absolute;
  top: 0;
  left: -100vw;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
// 拍照相关
    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;
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115

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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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

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

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
  

闽ICP备14008679号