uniapp开发小程序,使用canvas保存海报中自定义字体不生效的解决方案

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可以保存,所以决定使用uniappwebview嵌套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页面,并引入自定义字体、jqueryuni.webviewhtml2canvas;页面样式需要自行排版,此不赘述

<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页面

经过测试,发现保存海报字体已设置为自定义字体,但是多了一个跳转又返回的效果
这是我的解决方案,欢迎大家一起讨论

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值