1、需求:在使用uniapp
开发小程序项目中,在手机端保存活动宣传海报,内容包括图片及自定义字体文字
2、设想:
①、在页面增加canvas元素,并隐藏其显示
<canvas id="firstCanvas" style="width: 100vw; height: 100vh; position: fixed; top: 0;"></canvas>
②、使用uni.createCanvasContext(canvasId, this)
,创建 canvas 绘图上下文
this.context = uni.createCanvasContext('firstCanvas', this)
this.context.drawImage(this.bgImg, 0,0, 375, 812) // 设置背景
this.context.font = "24px YRDZSTRegular" // 设置自定义字体
this.context.fillText(this.showName, 140, 255) // 文字
③、使用uni.canvasToTempFilePath
生成图片,使用uni.saveImageToPhotosAlbum
保存到系统相册
this.context.draw(true, () => {
uni.canvasToTempFilePath({
canvasId: 'firstCanvas',
quality: 1,
complete: function(res) {
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: res => {
uni.hideLoading()
uni.showToast({
title: '该海报已保存至本地相册,可分享好友扫码',
icon: "none"
})
}
}
})
})
})
3、遇到问题
在真机保存发现字体设置失败,还是默认字体,查询资料未发现解决方案
4、更改方案
思路:小程序canvas
字体设置失败,但是原生canvas
可以保存,所以决定使用uniapp
中webview
嵌套html
页面进行设置字体的操作,使用html2canvas
插件进行转化图片,通过传值给uniapp
,最后通过uni.saveImageToPhotosAlbum
保存到系统相册
// 小程序端定义webview页面并跳转
<web-view :src="url" @message="getMessage"></web-view>
// 定义接收canvas方法,
methods: {
getMessage(event) {
var imgSrc = (event.detail.data)[0].action; //base64编码
var save = wx.getFileSystemManager();
var number = Math.random();
save.writeFile({
filePath: wx.env.USER_DATA_PATH + '/pic' + number + '.png', //临时路径
data: imgSrc.slice(22), //去除前缀
encoding: 'base64',
success: res => { // 保存图片到系统相册
wx.saveImageToPhotosAlbum({
filePath: wx.env.USER_DATA_PATH + '/pic' + number + '.png',
success: function (res) {
uni.showModal({
content: '保存成功!',
showCancel: false
});
// 请求完成之后自动返回上一页
uni.navigateBack({
delta: 1
});
},
fail: function (err) {
console.log("保存图片到系统相册失败", err)
}
})
}
})
}
}
新建html页面,并引入自定义字体、jquery
、uni.webview
、html2canvas
;页面样式需要自行排版,此不赘述
<style type="text/css">
@font-face {
font-family: 'MyFont'; /*字体名称*/
src: url('./font/YangRenDongZhuShiTi-Regular-2.ttf'); /*字体源文件 */
}
</style>
<script src="js/jquery-1.8.3.min.js"></script>
<script src="./js/uni.webview.1.5.2.js" type="text/javascript" charset="utf-8"></script>
<script src="./js/html2canvas.js" type="text/javascript" charset="utf-8"></script>
定义相关参数和方法
var imgBase64; // 用于存放生成的图片base64
function htmlToImg(){
let Canvas = document.createElement('canvas');
let width = $("#posters").width(); // 画布指定区域的宽
let height = $("#posters").height(); // 画图指定区域的高
let scale = scale(); // 设备的devicePixelRadio
// 将Canvas画布放大scale倍,然后放在小的屏幕里,解决模糊问题
Canvas.width = width * scale;
Canvas.height = height * scale;
Canvas.getContext('2d').scale(scale, scale);
setTimeout(()=>{
html2canvas(document.getElementById('posters'), {
canvas: Canvas,
scale,
useCORS: true, // 允许使用跨域图片
allowTaint: false, // 不允许跨域图片污染画布
width: width + 'px',
height: height + 'px',
}).then(function(canvas) {
let context = canvas.getContext('2d');
// 关闭抗锯齿形
context.mozImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.msImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
// canvas转化为图片
imgBase64 = canvas2Image(canvas, canvas.width, canvas.height);
$("#save").click()
})
},300)
},
// 根据window.devicePixelRatio获取像素比
function scale() {
if (window.devicePixelRatio && window.devicePixelRatio > 1) {
return window.devicePixelRatio;
}
return 1;
}
// 画布转换成图片
function canvas2Image(canvas, width, height) {
let retCanvas = document.createElement('canvas');
let retCtx = retCanvas.getContext('2d');
retCanvas.width = width;
retCanvas.height = height;
retCtx.drawImage(canvas, 0, 0, width, height, 0, 0, width, height);
let img = document.createElement('img');
img.setAttribute("id",'banners');
img.src = retCanvas.toDataURL('image/jpeg');
return img;
},
// 获取uniapp通过url传递的动态参数,需要者调用
function getParams() {
if(!window.location.search) return null;
const url = window.location.search.split ('?')[1];
const arr = url.split("&");
let obj = {};
for (let item of arr) {
const _arr = item.split("=")
obj[_arr[0]] = _arr[1]
}
return obj
}
// 在小程序端需要将图片信息传递给页面
document.addEventListener('UniAppJSBridgeReady', function() {
// 此按钮可设置自定义触发
$("body").on('click','#save',function(){
uni.postMessage({
data: {
action: imgBase64
}
})
})
})
// 调用
$(document).ready(function () {
htmlToImg()
});
将文件放入服务器,获取到路径,在webview
页面中写入url
,并拼接海报中所需要的动态内容,当下载海报操作时,跳转到当前webview
页面
经过测试,发现保存海报字体已设置为自定义字体,但是多了一个跳转又返回的效果
这是我的解决方案,欢迎大家一起讨论