完善版封装canvas分享组件

import regeneratorRuntime from "../../../lib/regenerator-runtime/runtime";
let ctx = false, crown = 0, widFit = 0	// ctx canvas对象, crown生成图的宽高比, widFit当然布局下与需生成图寛比, heiFit高度比
Component({
	/**
	 * 组件的属性列表
	 */
	properties: {
		canvasList: {
			type: Array,
			value: [
        {
					type: 'backImage', 
					url: 'https://portal.lanrenyun.cn/activity/50/activity_50-background-poster.jpg', 
				},
				{
					type: 'text', 
					text: '一二三四五六七八九十十一十二十三十四十五', 
					drawText:{ 
						x: 100, 
						y: 100, 
						maxWidth: 200, 
						fontSize: 14,
						lineHeight:60, 
						color: '#000'
					}
				},
        {
					type: 'image', 
					clip: true, 
					url: 'https://portal.lanrenyun.cn/Fs8toIXayCVeQAfLZDhsdlG-kcWX', 
					drawArguments:{ 
						dwX: 153, 
						dwY: 660, 
						dWidth: 106, 
						dHeight: 106 
					},
					drawArc:{ 
						x: 206, 
						y: 713, 
						radius: 53, 
					}
				},
				{
					type: 'image', 
					clip: true, 
					url: 'https://portal.lanrenyun.cn/Fs8toIXayCVeQAfLZDhsdlG-kcWX', 
					drawArguments:{ 
						dwX: 435, 
						dwY: 1497, 
						dWidth: 210, 
						dHeight: 210 
					},
					drawArc:{ 
						x: 540, 
						y: 1602, 
						radius: 105, 
					}
				},
				
			]
		},
		getShareWidth:{	//想得到的分享图宽度
			type: Number,
			value: 1080
		},

		getShareHeight:{	//想得到的分享图高度
			type: Number,
			value: 1900
		}

	},

	/**
	 * 组件的初始数据
	 */
	data: {
		canvasWidth: 375, //屏幕宽度
		canvasHeight: 375, //屏幕高度
		isShow: true, //canvas组件默认显示
	},

	/**
	 * 组件的方法列表
	 */
	methods: {
		async canvasStart() {
			const canvasList = this.data.canvasList
			await canvasList.map( (v,k)=>{
				if(v.type === 'backImage'){
					this.drawBackImg(v.url)
				}else if(v.type === 'image'){
					this.drawContentImg(v)
				}else{
					this.drawText(v.text,v.drawText)
				}
			})

			ctx.draw()
			this.saveImage()
		},

		// 画背景图
		drawBackImg(url){
			// console.log('drawBackImg',url)
			const { canvasWidth, canvasHeight } = this.data
			ctx.save()
			ctx.drawImage(url, 0, 0, canvasWidth, canvasHeight)
		},

		// 画图不用裁剪(查看小程序canvas api 文档 https://developers.weixin.qq.com/miniprogram/dev/api/CanvasContext.drawImage.html)
		drawImg(url, drawArguments) {
			const arg = Object.keys(drawArguments)
			if (arg.length == 8) {

				const { sx, sy, sWidth, sHeight, dwX, dwY, dWidth, dHeight } = drawArguments
				ctx.drawImage(url, sx * widFit, sy * widFit, sWidth * widFit, sHeight * widFit, dwX * widFit, dwY * widFit, dWidth * widFit, dHeight * widFit)

			} else if (arg.length == 4) {
				
				const { dwX, dwY, dWidth, dHeight } = drawArguments
				ctx.drawImage(url, dwX * widFit, dwY * widFit, dWidth * widFit, dHeight * widFit)

			} else if (arg.length == 2) {

				const { dwX, dwY } = drawArguments
				ctx.drawImage(url, dwX * widFit, dwY * widFit)

			} else {

				wx.showToast({
					title: '背景图传入参数有误,请确认无误后再进行操作',
					icon: 'none'
				})

			}

    	     },
    
		// 画内容图 clip裁剪
		drawContentImg(val){
			const { url, clip, drawArguments, drawArc} = val
			
			if(clip){		//裁剪流图片
				if(!url || !drawArguments || !drawArc){
					wx.showToast({
						title: '请确认drawContentImg参数无误',
						icon: 'none'
					})
					return;
				}

				const { x, y, radius } = drawArc
				if((x || x === 0 ) && (y || y === 0) && (radius || radius === 0)){
					const { x, y, radius, startRadian = 0 , endRadian = 2 * Math.PI  } = drawArc
					ctx.save()
					ctx.beginPath();
					ctx.arc(x * widFit, y * widFit, radius * widFit, startRadian, endRadian)  // arc(x坐标,y坐标,radius半径,startRadian起始弧度/单位弧度(默认在3点钟方向),endRadian终止弧度)
					ctx.clip()
					this.drawImg(url, drawArguments)
					ctx.restore()
				}else{
					wx.showToast({
						title: '画圆参数有误',
						icon: 'none'
					})
				}
			}else{
				ctx.save()
				this.drawImg(url, drawArguments)
				ctx.restore()
			}
			

		},
		
		// 画文字
		drawText(text,drawText){
			debugger
			const { x, y, maxWidth, fontSize, lineHeight = 0, color = 'white' } = drawText  // text文字内容, x画布X坐标, y画布y坐标, max最大宽度, fontSize字体大小, color文字颜色
			if(!text || (!x && x !== 0) || (!y && y !== 0) || !maxWidth || !fontSize){
				wx.showToast({
					title: '文字传入参数有误',
					icon: 'none'
				})
				return
			}
			ctx.save()
			ctx.setFontSize(fontSize)	//设置文字字体

			const measure = ctx.measureText(text).width	//测量文本宽度
			const scale = Math.ceil(measure / maxWidth)	//scale<1则 maxWidth>measure,1 <= scale < 2 则 maxWidth >= measure/2,scale >= 2 则 maxWidth <= measure / 2 
			let arr = []
			 
			if(scale >= 2){
				const fontNum = Math.floor(maxWidth / fontSize) //每行最多字体个数
				let patchVal = 0, patchY = y
				for(var i = 0; i < scale; i++){
					arr[i] = text.substr(patchVal,fontNum)
					if(i < scale - 1){
						ctx.fillText(text.substr(patchVal,fontNum), x * widFit, patchY * widFit)
						patchVal += fontNum
						patchY += (fontSize + lineHeight * widFit)
					}else{
						arr[i] = text.substr(patchVal)
						ctx.fillText(text.substr(patchVal), x * widFit, patchY * widFit)	//画最后剩下的内容
						console.log('arr:',arr)
					}
				}
			}else if(scale == 1 && maxWidth != measure ){
				const fontNum = Math.floor(maxWidth / fontSize) //每行最多字体个数
				ctx.fillText(text.substr(0,fontNum), x * widFit, y * widFit)
				ctx.fillText(text.substr(fontNum), x * widFit, (y+fontSize) * widFit)
				// console.log(text,arr,measure)
			}else{
				ctx.fillText(text, x * widFit, y * widFit);
			}

			ctx.setFillStyle(color)
			ctx.restore()
		},
		
		// 保存图片
		saveImage(){
			const { getShareWidth, getShareHeight } = this.data
			wx.canvasToTempFilePath({
				destWidth: getShareWidth,
				destHeight: getShareHeight,
				canvasId: 'firstCanvas',
				quality: 1,
				complete(fin){
				    console.log('finish',fin)
				    if(fin.tempFilePath){
				        wx.hideLoading();
				        wx.saveImageToPhotosAlbum({
				            filePath: fin.tempFilePath,
				            success: (result)=>{
								wx.hideLoading()
				                wx.showToast({
				                    title: '保存图片成功',
				                    icon: 'none'
				                })
				            }
				        })
				    }else{
							wx.showToast({
									title: '生成图片失败',
									icon: 'none'
							})
						}
						
				}
			},this)
		},

		//转成本地图片
		getImages(url){
			return new Promise( (sovle,reject)=>{
				wx.getImageInfo({
					src: url,
					success: (res)=>{
						sovle(res.path) 
					},
					fail: (err)=>{
						reject(err)
					}
				});
			})
			
		}
	},



	lifetimes: {
	 	async attached() {
			wx.showLoading({
				title: '生成图片中...',
				mask: true
			})
			// 获取屏幕宽高
			const { windowWidth } = wx.getSystemInfoSync();

			let { getShareWidth, getShareHeight, canvasList} = this.data
			crown = getShareWidth / getShareHeight	//分享图的宽高比

			const canvasHeight = windowWidth / crown
			this.setData({
			   canvasWidth: windowWidth,
				 canvasHeight
			})

			ctx = wx.createCanvasContext('firstCanvas',this) //把ctx赋值给全局变量
			widFit = windowWidth / getShareWidth   //宽比  (以px为单位)
			
			
			for(let i = 0; i < canvasList.length; i++){
				if(canvasList[i].url){
					canvasList[i].url = await this.getImages(canvasList[i].url)
					console.log(i,canvasList[i].url)
				}
			}
			
			const self = this
			console.log(4,this.data.canvasList)
			// await this.getImageInfo() //网络图片转成本地图片或临时图片
			this.setData({
				canvasList
			},function(){
				self.canvasStart()
			})
			
		},
	}
})

  最重要的是要注意换算比例以及自定义组件this参数,draw(true,this), 生存图片的时候也要带上this参数

  wx.canvasToTempFilePath(Object object, Object this)

 

转载于:https://www.cnblogs.com/jay-sans/p/10267011.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值