赞
踩
微信小程序中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可以解决这个问题
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。