需求:uniapp移动端需要生成一张当前界面的海报
方案一:类似于手机按钮截图效果。实现代码如下:
doSaveScreen() {
let $this = this;
uni.showLoading({ //加载框
title: '保存中...',
mask: true
})
var pages = getCurrentPages(); //获取当前页面信息
var page = pages[pages.length - 1];
var bitmap = null;
// $this.$nextTick(()=> {
var currentWebview = page.$getAppWebview();
bitmap = new plus.nativeObj.Bitmap('amway_img');
// 将webview内容绘制到Bitmap对象中
currentWebview.draw(bitmap, function() {
// console.log('截屏绘制图片成功');
//这里我将文件名用四位随机数拼接了,不然会出现当前图片替换上一张图片只能保存一张图片的问题
let rand = Math.floor(Math.random() * 10000)
let saveUrl = '_doc/' + rand + 'a.jpg'
bitmap.save(saveUrl, {}, function(i) {
uni.saveImageToPhotosAlbum({
filePath: i.target,
success: function() {
// bitmap.clear(); //销毁Bitmap图片
uni.showToast({
title: '保存到相册成功',
duration: 1500
});
},
complete() {
uni.hideLoading();
}
});
}, function(e) {
console.log('保存图片失败:' + JSON.stringify(e));
});
}, function(e) {
console.log('保存图片失败:' + JSON.stringify(e));
});
// })
}
上面的发案有两个缺陷:
1.无法保存长图:遇到内容过长,超出了手机屏幕高度(需要上下滚动屏幕才能浏览完所有内容)
2.截图内容不能去掉手机顶部的导航栏;
方案二:使用html2canvas实现。同时解决上面两个缺陷。(不过此方案生成的海报内容有需要显示图片的情况下,需要把图片转成base64给image标签,详情请查看下面的代码。)
在项目的根目录下安装html2canvas: npm install html2canvas。
封装成插件方便后续使用,以下是插件代码:
<template>
<view>
<view class="html2canvas" :prop="domId" :change:prop="html2canvas.create">
<slot></slot>
</view>
</view>
</template>
<script>
export default {
props: {
domId: {
type: String,
required: true
}
},
methods: {
async renderFinish(base64) {
try{
this.$emit('renderFinish', base64);
}catch(e){
//TODO handle the exception
console.log('html2canvas error', e)
}
},
showLoading() {
// uni.showToast({
// title: "正在生成海报",
// icon: "none",
// mask: true,
// duration: 100000
// })
},
hideLoading() {
//uni.hideToast();
}
}
}
</script>
<script module="html2canvas" lang="renderjs">
import html2canvas from 'html2canvas';
export default {
methods: {
async create(domId) {
if(!domId){
return;
}
try {
this.$ownerInstance.callMethod('showLoading', true);
const timeout = setTimeout(async ()=> {
const shareContent = document.querySelector(domId);
const canvas = await html2canvas(shareContent,{
width: shareContent.offsetWidth,//设置canvas尺寸与所截图尺寸相同,防止白边
height: shareContent.offsetHeight,//防止白边
logging: true,
useCORS: true,
allowTaint: true,
});
const base64 = canvas.toDataURL('image/jpeg', 1);
this.$ownerInstance.callMethod('renderFinish', base64);
this.$ownerInstance.callMethod('hideLoading', true);
clearTimeout(timeout);
}, 1300);
} catch(error){
console.log(error)
}
}
}
}
</script>
<style lang="scss">
</style>
使用代码如下:
urlToBase64Qrcode(url){
if(url){
uni.request({
url:url,
method:'GET',
responseType:'arraybuffer',
success: ( res)=> {
let base64 = wx.arrayBufferToBase64(res.data);
let Base64Url = 'data:image/jpeg;base64,' + base64;
this.base64Qrcode = Base64Url;
}
})
}
},
urlToBase64UserHead(url){
if(url){
uni.request({
url:url,
method:'GET',
responseType:'arraybuffer',
success: ( res)=> {
let base64 = wx.arrayBufferToBase64(res.data);
let Base64Url = 'data:image/jpeg;base64,' + base64;
this.base64Head = Base64Url;
}
})
}
},
renderFinish(base64) {
this.imageData = base64;
},
saveImageToLocal() {
if (!this.imageData) {
uni.showToast({
title: '保存失败',
icon: 'none'
})
return;
}
const bitmap = new plus.nativeObj.Bitmap("test")
bitmap.loadBase64Data(this.imageData, function() {
const url = "_doc/" + new Date().getTime() + ".png"; // url为时间戳命名方式
bitmap.save(url, {
overwrite: true, // 是否覆盖
// quality: 'quality' // 图片清晰度
}, (i) => {
uni.saveImageToPhotosAlbum({
filePath: url,
success: function() {
uni.showToast({
title: '保存成功',
icon: 'none'
})
bitmap.clear()
}
});
}, (e) => {
console.log(e);
uni.showToast({
title: '图片保存失败',
icon: 'none'
})
bitmap.clear()
});
}, (e) => {
uni.showToast({
title: '图片保存失败',
icon: 'none'
})
bitmap.clear()
})
},