当前位置:网站首页>解决uniapp微信小程序canvas不能引入字体的问题
解决uniapp微信小程序canvas不能引入字体的问题
2022-07-28 13:11:00 【奥吼吼~~】
这是微信小程序最近修复问题,里面有关于loadFontFace的修复
在使用前要先把调试基础库调整为2.25.1,我调到这个版本就好其他的版本我也没试
下面是我画布导出的大概效果姓名这里使用了字体,白色的轮廓是字体轮廓填充
首先要了解一个api名称:uni.loadfontface
这里source里面只能是网络链接,因为我没有服务器,也不想装搭本地服务,所以我使用的是vscode中Live server然后访问字体链接先把效果搞出来,之后再是上服务器配置安全域名
scopes这个属性,native表示可以在canvas2d中使用这个字体
下面是部分必要代码片段
大致逻辑就是等字体加载成功之后获取画布对象然后把文字绘制到画布上面然后导出base64的图片
至于750和176是我代码的逻辑,按照自己的代码逻辑动态修改或者写死都可以
<template>
<canvas type="2d" id="canvasName" :style="{width:750 + 'px',height:176 + 'px'}" />
</template>
<script> let canvas = null let ctx = null let dpr = null uni.loadFontFace({
global: true, family: "DINMedium", source: 'url("http://192.168.108.240:5500/files/iconfont2.ttf")', success: () => {
this.draw() }, scopes: ["webview", "native"], }) methods:{
draw() {
const self = this; let fm = 'DINMedium'; const query = wx.createSelectorQuery() query.select('#canvasName') .fields({
node: true, size: true }) .exec((res) => {
console.log(res) canvas = res[0].node ctx = canvas.getContext('2d') dpr = wx.getSystemInfoSync().pixelRatio canvas.width = res[0].width * dpr canvas.height = res[0].height * dpr ctx.scale(dpr, dpr) let x = 20 let y = 20 let fontSize = 20 this.drawText(ctx, "姓名", 88, "#01A5AE", 750 / 2, 88, 400, true, 'center', true,fm) ctx.lineWidth = 2 ctx.strokeStyle = '#ffffff' // ctx.font = "bold " + fontSize + 'px ' + fm; ctx.strokeText("姓名", 750 / 2, 88) ctx.restore() this.name = canvas.toDataURL() }) }, drawText(ctx, text, fontSize, color, x, y, maxWidth, bold, align, shadow,fontFamily) {
if (bold) {
ctx.font = `bold ${
fontSize}px ${
fontFamily ? fontFamily : 'normal'}`; } else {
ctx.font = `normal ${
fontSize}px ${
fontFamily ? fontFamily : 'normal'}`; } if (align) {
ctx.textAlign = align } else {
ctx.textAlign = 'left' } ctx.fillStyle = color if (ctx.measureText(text).width > maxWidth) {
var count = 1; while (ctx.measureText(text.slice(0, text.length - count)).width > 693) {
count++ } if (shadow) {
ctx.shadowOffsetX = 3; //用来设定阴影在 X轴的延伸距 ctx.shadowOffsetX = 3; //用来设定阴影在 Y轴的延伸距 ctx.shadowBlur = 4; //设定阴影的模糊程度 默认0 ctx.shadowColor = "rgba(0, 0, 0, 0.5)"; } ctx.fillText(text.slice(0, text.length - (count + 1)) + "...", x, y) } else {
ctx.fillText(text, x, y) } }, } </script>
APP和H5字体是正常的不管是用uni.loadFontFace还是用@font-face都可以直接用,就小程序事情多
通过上面代码不难发现,我将这个带字体样式的文字单独绘制成了一张图片,这是因为在绘制它之前我已经把九宫格图片布局以及底板大部分样式已经使用uni.createCanvasContext这个api绘制完了,最后发现微信小程序字体只能通过上面那种方式进行绘制,为了不让之前的努力白费,我选择将名字单独绘制然后将绘制出来的base64转化为一个临时链接绘制到我之前已经写好绘制过程的画布内容上,所以现在的运行逻辑里有两个画布,一个是图片
下面是将base64转成临时链接的逻辑,因为我发现base64在小程序上面不能直接绘制到画布上面,我裂开
base64ToTemp(base64){
return new Promise((r) => {
let qrcode = base64.replace(/\. +/g, '').replace(/[\r\n]/g, '')
const fs = wx.getFileSystemManager();
//随机定义路径名称
var times = new Date().getTime();
var codeimg = wx.env.USER_DATA_PATH + '/' + times + '.png';
//将base64图片写入
var that = this;
fs.writeFile({
filePath: codeimg,
data: qrcode.split('data:image/png;base64,')[1],
encoding: 'base64',
complete(res) {
console.log(res)
},
success: () => {
r(codeimg)
}
})
})
},
// 为了兼容小程序和APP所以这里分开处理了
使用逻辑(){
// #ifdef MP
var temp = await this.base64ToTemp(this.name)
console.log(temp)
this.temp = temp
this.ctx.drawImage(temp, 0, 554 * (this
.canvasWidth / 750) - 230, this.canvasWidth, 176)
// #endif
// #ifndef MP
this.drawText(this.ctx, "姓名", 88, "#01A5AE", this.canvasWidth / 2, 554 * (this
.canvasWidth / 750) - 140, 400, true,
'center', true)
this.ctx.lineWidth = 2
this.ctx.setStrokeStyle('#ffffff')
this.ctx.strokeText("姓名", this.canvasWidth / 2, 554 * (this.canvasWidth / 750) - 140)
this.ctx.restore()
// #endif
}
下面是我绘制九宫格已经底板的所有逻辑
设计到的一些封装方法可以参考我这个文章
部分方法有点改动不过大逻辑都一样
squaredDraw() {
var colCount = 3;
var gap = 5;
var imageWidth = (750 - ((colCount - 1) * gap)) / colCount
var TextB = 60
this.canvasWidth = 750
var bottomTitle = 72;
var bottomQrCode = 200;
var QrCodeWidth = 160;
this.canvasHeight = TextB + bottomQrCode + bottomTitle + (imageWidth + 5) * Math.ceil(this.drawImageList
.length / colCount)
this.$nextTick(async () => {
uni.showLoading({
title: "加载中...",
mask: true
})
this.ctx = uni.createCanvasContext('myCanvas')
this.drawText(this.ctx, "篮球比赛篮球比赛篮球比赛", 32, "#222222", 375, 46, 200, true, 'center')
for (let i = 0; i < this.drawImageList.length; i++) {
uni.hideLoading()
uni.showLoading({
title: `(${
i + 1}/${
this.drawImageList.length})`,
mask: true
})
await this.drawImageWidthFix1(this.ctx, this.drawImageList[i] + '?type=1&size=300', (
i % colCount == 0 ? 0 :
(imageWidth + 5) * (i % colCount)), (bottomTitle + (imageWidth + gap) *
parseInt(i / colCount)), imageWidth, imageWidth)
}
uni.hideLoading()
uni.showLoading({
title: `生成中...`,
mask: true
})
this.ctx.drawImage('../../static/3.png', (750 - 120) / 2, bottomTitle + (
imageWidth + 5) * Math.ceil(this.drawImageList.length / colCount) + (
bottomQrCode - QrCodeWidth) / 2, QrCodeWidth, QrCodeWidth)
this.drawText(this.ctx, "篮球比赛的文字描述篮球比赛的文字描述篮球比赛的文字描述", 32, "#222222", 375, bottomTitle + (
imageWidth + 5) * Math.ceil(this.drawImageList.length / colCount) +
bottomQrCode + 20, 400, true, 'center')
this.ctx.drawImage('../../static/top.png', 0, 0, this.canvasWidth, 554 * (this
.canvasWidth / 750))
// #ifdef MP
var temp = await this.base64ToTemp(this.name)
console.log(temp)
this.temp = temp
this.ctx.drawImage(temp, 0, 554 * (this
.canvasWidth / 750) - 230, this.canvasWidth, 176)
// #endif
// #ifndef MP
this.drawText(this.ctx, "姓名", 88, "#01A5AE", this.canvasWidth / 2, 554 * (this
.canvasWidth / 750) - 140, 400, true,
'center', true)
this.ctx.lineWidth = 2
this.ctx.setStrokeStyle('#ffffff')
this.ctx.strokeText("姓名", this.canvasWidth / 2, 554 * (this.canvasWidth / 750) - 140)
this.ctx.restore()
// #endif
var bottomImageHeight = 404 * (this.canvasWidth / 750)
var bottomImageTop = this.canvasHeight - bottomImageHeight
this.ctx.drawImage('../../static/bottom.png', 0, bottomImageTop, this.canvasWidth,
bottomImageHeight)
this.drawText(this.ctx, "内蒙古包头赛区", 42, "#ffffff", 53, bottomImageTop + 274, 400, true,
'left', true)
this.ctx.restore()
this.drawText(this.ctx, "2020.04.05", 58, "#ffffff", 132, bottomImageTop + 346, 400, true,
'left', true)
this.ctx.restore()
this.ctx.draw()
setTimeout(() => {
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: this.canvasWidth,
height: this.canvasHeight,
destWidth: this.canvasWidth * 2,
destHeight: this.canvasHeight * 2,
// quality: 0.5,
canvasId: 'myCanvas',
complete: () => {
uni.hideLoading()
},
success: (res) => {
this.imageSrc = res
.tempFilePath
}
})
}, 1200)
})
},
边栏推荐
- Jmeter安装教程及登录增加token
- Denial of service DDoS Attacks
- leetcode-深度优先与广度优先遍历
- 30天刷题计划(二)
- 产品经理:岗位职责表
- R language uses LM function to build linear regression model and subset function to specify subset of data set to build regression model (use floor function and length function to select the former pa
- Postgresql14 installation and master-slave configuration
- [security] read rfc6749 and understand the authorization code mode under oauth2.0
- 盘点操作URL中常用的几个高效API
- 创建线程池的四种方式
猜你喜欢

7. Dependency injection

Chapter 6 support vector machine

The strongest distributed locking tool: redisson

算法---不同路径(Kotlin)

Istio四之故障注入和链路追踪

什么是自旋锁 自旋锁是指当一个线程尝试获取某个锁时,如果该锁已被其他线程占用,就一直循环检测锁是否被释放,而不是进入线程挂起或睡眠状态。 /** * 为什么用自旋锁:多个线程对同一个变量
JWT login authentication + token automatic renewal scheme, well written!

在 Kubernetes 中部署应用交付服务(第 1 部分)
![[basic course of flight control development 7] crazy shell · open source formation UAV SPI (barometer data acquisition)](/img/ad/e0bc488c238a260768f7e7faec87d0.png)
[basic course of flight control development 7] crazy shell · open source formation UAV SPI (barometer data acquisition)

阿里、京东、抖音:把云推向产业心脏
随机推荐
Rust from introduction to mastery 01 introduction
Duplicate data in leetcode (442) array
A label_ File download (download attribute)
一文读懂如何部署具有外部数据库的高可用 K3s
Security assurance is based on software life cycle - networkpolicy application
Deploy application delivery services in kubernetes (Part 1)
P1797 heavy transportation problem solution
你真的了解esModule吗
关于栈的理解以及实际应用场景
Socket类关于TCP字符流编程的理解学习
Security assurance is based on software life cycle -istio authentication mechanism
30 day question brushing training (I)
leetcode(442)数组中重复的数据
Qt5 development from introduction to mastery -- the first overview
掌握闭包,夯实基本功
Generation of tables and contingency tables (cross tables) of R language factor data: use the summary function to analyze the list, view the chi square test results, and judge whether the two factor v
Uva11175 digraph D and E from D to e and back
安全保障基于软件全生命周期-Istio的认证机制
SLAM论文合集
How to play a data mining game entry Edition