微信小程序生成海报

微信小程序生成海报的代码如下:

promisify文件:

module.exports = {  
  promisify: api => {  
    return (options, ...params) => {  
      return new Promise((resolve, reject) => {  
        const extras = {  
          success: resolve,  
          fail: reject  
        }  
        api({ ...options, ...extras }, ...params)  
      })  
    }  
  }   
} 

开始:

import {promisify} from './promisify'

const wxGetImageInfo = promisify(wx.getImageInfo)
// 图标路径
const [localtionIconUrl, timeIconUrl, assemblyPointIconUrl] = ['/img/icons/localtion.png', '/img/icons/time.png', '/img/icons/assembly-point .png']
// 是否是大屏幕
const isLargeScreen = wx.getSystemInfoSync().windowHeight > 516
// canvas 宽、高、内边距
const [cvsW, cvsH, cvsPL, cvsPT, cvsPB] = [300, 516, 16, 22, 70]
// 封面图片宽高
const [coverImgW, coverImgH, qrImgH, qrImgW] = [300, isLargeScreen ? 180 : 150, 90, 90]
// 字体内边距、字体大小、字体颜色
const [fontPL, fontPT, fontSize18, fontSize14, colorBlack, colorGray, colorRed] = [55, 45, 18, 14, '#141414', '#666', 'red']
// 字体分割显示缩略
function helpFontSplit (str, lineNum = 1) {
    const maxChar = 12
    const len = str.length
    let res
    if (len <= maxChar) {// 小于一行
      res = [str]
    } else if (len <= maxChar * lineNum) {// 小于指定行数
      res = [str.slice(0, maxChar), str.slice(maxChar, 37)]
    } else {//大于指定行数
      let temp = []
      for (let i = 0; i < lineNum; i++) {
        if (i === lineNum - 1) {
          temp.push(str.slice(maxChar * i, (i + 1) * maxChar - 3) + '...')
        } else {
          temp.push(str.slice(maxChar * i, (i + 1) * maxChar))
        }
      }
      res = temp
    }
    return lineNum > 1 ? res :[res][0]
}
// 日期格式化
function helpFormatDate (dateArr) {
	if (!Array.isArray(dateArr)) {
		return
	}
	return dateArr.map(item => {
		const week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
		let startArr = item.activity_start.split('-')
		let endArr = item.activity_end.split('-')
		let start = new Date(startArr.join('/'))
		let end = new Date(endArr.join('/'))
		return startArr.splice(1, 2).join('.') + week[start.getDay()] + '~' + endArr.splice(1, 2).join('.') + week[end.getDay()]
	})
}
// canvas转换成图片
export class Canvas2Image {
  constructor(param, qrUrl) {
    this.param = param
    this.qrUrl = qrUrl
    this.isSingle = param.price_date.length == '1'
  }


  getImg (callback) {
  	const qrUrl = this.qrUrl
  	const coverUrl = this.param.thumb_img
  	Promise.all([ // url是服务器地址
    	// icon - 1
    	wxGetImageInfo({
    	  src: url+ localtionIconUrl
    	}),
    	// icon - 2
    	wxGetImageInfo({
    	  src: url + timeIconUrl
    	}),
    	// icon - 3
    	wxGetImageInfo({
    	  src: url+ assemblyPointIconUrl
    	}),
    	// 封面图
    	wxGetImageInfo({
    	  src: coverUrl
    	}),
    	// 小程序码图
    	wxGetImageInfo({
    	  src: url+ qrUrl
    	})
  	]).then(res => {
  		callback && callback(res)
  	})
  }

  render (canvasId, callback) {
    this.getImg(res => {
    	console.log('---图片就绪---')
    	console.log(res)
    	// 图片路径
    	const [{path: localtionIconPath}, {path: timeIconPath}, {path: assemblyPointIconPath}, {path: coverImgPath}, {path: qrImgPath}] = res
    	const {activity_name: title, resort: resort, price_list: prices, price_date: times} = this.param
    	const ctx = wx.createCanvasContext(canvasId)
    	console.log('---绘图开始---')
    	this.drawCover(ctx, coverImgPath)
    	this.drawIcon(ctx, localtionIconPath, timeIconPath, assemblyPointIconPath)
    	this.drawTitle(ctx, helpFontSplit(title, 2))
    	this.drawLocaltion(ctx, resort)
    	this.drawTime(ctx, helpFormatDate(times))
    	this.drawResort (ctx, resort)
    	this.drawQrImage (ctx, qrImgPath)
    	this.drawPrices (ctx, prices)
    	ctx.draw(false, function () {
      		console.log('---canvas绘图完成---')
      		callback && callback()
    	})
    })
  }
  // 绘制封面
  drawCover (ctx, coverImgPath) {
  	ctx.drawImage(coverImgPath, 0, 0, coverImgW, coverImgH)
  }
  // 绘制图标
  drawIcon (ctx, localtionIconPath, timeIconPath, assemblyPointIconPath) {
  	ctx.drawImage(localtionIconPath, fontPL - 20, coverImgH + fontPT * 2.28, 15, 15)
    ctx.drawImage(timeIconPath, fontPL - 20, coverImgH + fontPT * 2.88, 15, 15)
    if (this.isSingle) {
    	ctx.drawImage(assemblyPointIconPath, fontPL - 20, coverImgH + fontPT * 3.54, 15, 15)
    } else {
    	ctx.drawImage(assemblyPointIconPath, fontPL - 20, coverImgH + fontPT * 4.45, 15, 15)
    }
  }
  // 绘制标题
  drawTitle (ctx, title) {
    ctx.setTextAlign('left')    // 文字居中
    ctx.setFillStyle(colorBlack)  // 文字颜色
    ctx.setFontSize(fontSize18)       // 文字字号:18px
    ctx.fillText(title[0], fontPL - 20, coverImgH + fontPT)
    title[1] && ctx.fillText(title[1], fontPL - 20, coverImgH + fontPT * 1.6)
  }
  // 绘制地点
  drawLocaltion (ctx, adress) {
  	// 活动时间、地点
    ctx.setFillStyle(colorGray)  // 文字颜色
    ctx.setFontSize(fontSize14)       // 文字字号:14px
    ctx.fillText('集合地点: ' + helpFontSplit(adress), fontPL, coverImgH + fontPT * 2.55)
  }
  // 绘制班期
  drawTime (ctx, times) {
  	ctx.fillText('活动时间 :  ' + times[0], fontPL, coverImgH + fontPT * 3.15)
  	if (!this.isSingle) {
  		times[1] && ctx.fillText(times[1], fontPL + 70, coverImgH + fontPT * 3.6)
      	times[2] && ctx.fillText(times[2], fontPL + 70, coverImgH + fontPT * 4)
  	} 
  }
  // 绘制集合地点
  drawResort (ctx, resort) {
  	if (this.isSingle) {
  		ctx.fillText('集合地点: ' + helpFontSplit(resort), fontPL, coverImgH + fontPT * 3.8)
  	} else {
  		ctx.fillText('集合地点: ' + helpFontSplit(resort), fontPL, coverImgH + fontPT * 4.7)
  	}
  }
  // 绘制小程序二维码
  drawQrImage (ctx, qrImgPath) {
  	if (isLargeScreen) {
      ctx.drawImage(qrImgPath, cvsW - qrImgW - cvsPL - 16, cvsH - qrImgH - cvsPB + 50, qrImgW, qrImgH)
    } else {
      ctx.drawImage(qrImgPath, cvsW - qrImgW - cvsPL + 10, cvsH - qrImgH - cvsPB + 10, qrImgW - 10, qrImgH - 10)
    }
  }
  // 绘制价格
  drawPrices (ctx, prices) {
  	const priceLabel = ['', '成人价: ', '儿童价: ', '老人价: ']
  	const baseNum = 5.3
  	const increment = 0.6
  	if (Array.isArray(prices)) {
  		prices.forEach((item, index) => {
  			ctx.setFillStyle(colorGray) 
  			ctx.fillText(priceLabel[item.type], fontPL - 20, coverImgH + fontPT * (baseNum + index * increment))
  			ctx.setFillStyle(colorRed)
  			ctx.fillText('¥' + item.price, fontPL + 35, coverImgH + fontPT * (baseNum + index * increment))
  		})
  	}
    ctx.stroke()
  }
}
// 保存至本地
export function saveCanvasImage2Local(canvasId, callback) {
  console.log('---准备保存到本地---')
  const wxCanvasToTempFilePath = promisify(wx.canvasToTempFilePath)
  const wxSaveImageToPhotosAlbum = promisify(wx.saveImageToPhotosAlbum)
  wxCanvasToTempFilePath({
     canvasId: canvasId
  }, this).then(res => {
    console.log('---保存到本地就绪---')
      callback && callback()
      return wxSaveImageToPhotosAlbum({
          filePath: res.tempFilePath
      })
  }).then(res => {
    wx.showModal({...{
        title: '',
        content: '这是一个模态弹窗',
        cancelText: '取消',
        cancelColor: '#505050',
        confirmText: '确定',
        confirmColor: '#ff4558',
        showCancel: true,
        success: function(res) {
          if (res.confirm) {
            console.log('用户点击确定')
          } else if (res.cancel) {
            console.log('用户点击取消')
          }
        }
      }, ...config})
      // wx.showToast({
      //     title: '已保存到相册'
      // })
  })
}

猜你喜欢

转载自blog.csdn.net/wh13267207590/article/details/80761632
今日推荐