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)

完善版封装canvas分享组件的更多相关文章

  1. 自己封装的一个JS分享组件

    因为工作的需求之前也封装过一个JS分享插件,集成了我们公司常用的几个分享平台. 但是总感觉之前的结构上很不理想,样式,行为揉成一起,心里想的做的完美,实际上总是很多的偏差,所以这次我对其进行了改版. ...

  2. 基于Bootstrap的DropDownList的JQuery组件的完善版

    在前文 创建基于Bootstrap的下拉菜单的DropDownList的JQuery插件 中,实现了DropDownList的JQuery组件,但是留有遗憾.就是当下拉菜单出现滚动条的时候,滚动条会覆 ...

  3. WPF 自定义 MessageBox (相对完善版)

    WPF 自定义 MessageBox (相对完善版)     基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当 ...

  4. AngularJS指令封装高德地图组件

    1 概述 公司移动门户原来是基于AngularJS指令封装的百度地图组件,用于签到.签退.定位等功能,在使用过程中发现百度地图频繁的弹出广告,所以打算重新引用其它地图组件,最后决定基于AngularJ ...

  5. WPF 自定义 MessageBox (相对完善版 v1.0.0.6)

    基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当你不得不弹出一个消息框通知用户消息时(虽然很不建议在程序中频繁 ...

  6. 【小程序】---- 封装Echarts公共组件,遍历图表实现多个饼图

    一.问题描述: 在小程序的项目中,封装公共的饼图组件,并在需要的页面引入使用.要求一个页面中有多个饼图,动态渲染不同的数据. 二.效果实现: 1. 查看——小程序使用Echarts的方式 2. 封装饼 ...

  7. vue3 vite2 封装 SVG 图标组件 - 基于 vite 创建 vue3 全家桶项目续篇

    在<基于 vite 创建 vue3 全家桶>一文整合了 Element Plus,并将 Element Plus 中提供的图标进行全局注册,这样可以很方便的延续 Element UI 的风 ...

  8. iOS开发---集成百度地图完善版

    一.成为百度的开发者.创建应用 http://developer.baidu.com/map/index.php?title=首页 (鼠标移向 然后选择你的项目需要的功能 你可以在里面了解到你想要使用 ...

  9. Xamarin.Android 绑定友盟社会化分享组件

    Xamarin.Android 绑定友盟社会化分享组件 最近在开发博客园Android App的时候需要用到友盟社会化分享组件,在github上搜了一下都没有找到最新版本绑定好的项目,就自己动手来绑定 ...

随机推荐

  1. leetcode461

    public class Solution { public int HammingDistance(int x, int y) { ]; ]; ; ; do { aryA[i] = x % ;//将 ...

  2. iphone 开发h5 踩过的坑

    html,body{ -webkit-text-size-adjust: none; }  // 当需要在中文版chrome浏览器中显示小于12px的字体时,而且此时页面放大效果会被阻止 html,b ...

  3. sass的基本使用

    使用sass的前提是安装Ruby,如果是Mac系统,那么免去安装,Windows系统需要自行安装https://www.sass.hk/install/.当安装好以后,直接执行安装sass命令:gem ...

  4. 用命令生成Webservice 对应的代理类

    wsdl /language:C# /namespace:Camstar.WebPortal.WebPortlets.Shopfloor.SAP.GreatWall /out:gwSAPService ...

  5. 将python、pip 加入环境变量

    加python: CMD里输:    path=%path%;C:\Python27 其中   C:\Python27  为python的exe所在的文件夹 加pip: CMD里输:    path= ...

  6. Numpy三维数组的转置与交换轴

    二维数组的转置应该都知道,就是行列交换 而在numpy中也可以对三维数组进行转置,np.T 默认进行的操作是将0轴与2轴交换 本文主要对三位数组轴交换的理解上发表本人的看法. a = np.array ...

  7. WD Elements 与 time machine

    备份是很重要的问题. 之前买了一个 WD Elements,想要格式化成 HFS 的格式. 不然不能被 Time Machine 使用. 但是用磁盘工具不能成功,因为 EFI 分区的问题. 参考下面网 ...

  8. Iris数据集实战

    本次主要围绕Iris数据集进行一个简单的数据分析, 另外在数据的可视化部分进行了重点介绍. 环境 win8, python3.7, jupyter notebook 目录 1. 项目背景 2. 数据概 ...

  9. Math的方法;Date的方法;

    Math的方法: (1)弧度的π  Math.PI() (2)返回平方根 Math.sqrt() (3)返回x的绝对值 Mathabs(x) (4)返回x的上舍入 Math.ceil(x) (5)返回 ...

  10. Thinkphp5 表单提交额外参数和页面跳转参数传递url

    1. 表单提交 <input type="hidden" name="project_name" value="$project_name&qu ...