解决uniapp微信小程序canvas不能引入字体的问题

在使用前要先把调试基础库调整为2.25.1,我调到这个版本就好其他的版本我也没试 下面是我画布导出的大概效果姓名这里使用了字体,白色的轮廓是字体轮廓填充

首先要了解一个api名称: 这里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都可以直接用,就小程序事情多

base64ToTemp(base64){
          
   
	return new Promise((r) => {
          
   
		let qrcode = base64.replace(/. +/g, ).replace(/[
]/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)
			})

		},
经验分享 程序员 微信小程序 职场和发展