微信小程序 — 总结

微信小程序 — 总结

第一次接触微信小程序项目 – 小记

  1. 环境: 小程序基于mpvue - 电商类 H5公众号
  2. 授权(注册/自动登录)
  3. 生成分享海报图片(本章使用基础的canvas绘制)

(小程序和公众号通过 unionid 关联,公众号通过 userinfo 进行授权,拿到用户信息及 unionid 在H5上授权之后,小程序可直接静默登录,反之亦然。)

<!-- 事件授权 -->
<button class="get_user_info_button" 
		open-type="getUserInfo" 
		lang="zh_CN" 
		@getuserinfo="bingGetUserInfo"
>授权</button>
bingGetUserInfo(e){
	let params = e.target;
	let userInfo = params.userInfo;
	let getUnion = {
		encryptedData: params.encryptedData,
		iv: params.iv,
		session_key: getStorage('session_key')
	}
	// 通过session_key 、iv 和 encryptedData 调用微信接口解密,获取用户的unionid  (session_key 通过 code 获取)
	getUnionid(getUnion).then(res => {
		// 获取 unionid ->  请求用户信息  
		// if 存在用户
			// if 是否绑定手机号(通过用户id获取是否绑定手机号)
				// 登录
			// else 注册
				// 填写手机号进行注册
		// else 不存在
			// 通过 userInfo 注册用户
	}).cath(err => {...});
}
// 绘制海报图片(生成的海报不同,可改动参数)
function createLocalImg(canvas, url) {
  return new Promise((resolve, reject) => {
    const img = canvas.createImage()
    img.onload = function () {
      resolve(img)
    }
    img.onerror = err => {
      reject({
        message: `图片加载失败${url}`
      })
      console.error('图片加载失败', url)
    }
    img.src = url
  })
}

// 绘制圆角矩形
function drawRoundedRect(ctx, x, y, width, height, r, fill, stroke) {
  ctx.save();
  ctx.beginPath(); // 绘制顶部和右上角
  ctx.moveTo(x + r, y);
  ctx.arcTo(x + width, y, x + width, y + r, r); // 绘制右侧和右下角
  ctx.arcTo(x + width, y + height, x + width - r, y + height, r); // 绘制底部和左下角
  ctx.arcTo(x, y + height, x, y + height - r, r); // 绘制左上角
  ctx.arcTo(x, y, x + r, y, r);
  if (fill) ctx.fill();
  if (stroke) ctx.stroke();
  ctx.restore();
}

function drawShareImg(info) {
  console.log("draw canvas", info)
  return new Promise(async (resolve, reject) => {
    const query = wx.createSelectorQuery()
    query.select('#canvasPoster').fields({
      node: true,
      size: true
    }).exec(async res => {
      try {
        const canvas = res[0].node;
        const ctx = canvas.getContext('2d');
        const sysInfo = wx.getSystemInfoSync();
        let dpr = sysInfo.pixelRatio;
        const width = res[0].width;
        const height = res[0].height;
        // 避免安卓机挂掉 安卓机dpr最大为2
        if (sysInfo.platform === 'android' && dpr > 2) {
          dpr = 2;
        }
        // 产品图偏移量
        let offset = info.offset
        // y轴坐标
        let canvasY = 0
        function scaleSize(size) {
          return width / 750 * size
        }
        canvas.width = width * dpr;
        canvas.height = height * dpr;
        // 避免安卓机挂掉 安卓机dpr最大为2
        if (sysInfo.platform === 'android' && dpr > 2) {
          canvas.height = canvas.height - scaleSize(200);
        }
        ctx.scale(dpr, dpr)
        // 绘制背景色
        ctx.fillStyle = '#FFFFFF'
        ctx.fillRect(0, canvasY, width, height)
        // 绘制背景图
        let prodHeight = width
        const prodImg = await createLocalImg(canvas, info.cover)
        ctx.drawImage(prodImg, 0, canvasY, width, prodHeight)
        // 绘制圆角矩形中的内容
        let qsChildBoxY = prodHeight + scaleSize(10);
        ctx.fillStyle = '#FF6300';
        drawRoundedRect(ctx, scaleSize(36), qsChildBoxY, scaleSize(150), scaleSize(52), scaleSize(6), true, false);
        ctx.strokeStyle = "#FF6300";
        let qsChildTextY = prodHeight + scaleSize(44);
        ctx.font = `${scaleSize(28)}px sans-serif`;
        ctx.fillStyle = '#FFFFFF';
        ctx.fillText('项目名称', scaleSize(54), qsChildTextY);
        canvasY += width + (scaleSize(50))
        ctx.font = `${scaleSize(30)}px sans-serif`
        ctx.fillStyle = '#1a1a1a'
        ctx.textAlign = 'left'
        // 字符分隔为数组  字符长度大于13留两个缩进字符
        if (info.name.length > 13) {
          let textArr = info.name.split('');
          let textHeight = 0;  // 文本最终占据高度
          let textOfLine = '';     // 每行显示的文字
          let indentText = scaleSize(36);    // 首行缩进
          let textWidth = scaleSize(596);     // 标题宽度
          let limitRow = 2;   // 控制行数
          let rowCount = 0;
          // 循环分割的文字数组
          for (let i = 0; i < textArr.length; i++) {
            let singleWord = textArr[i];      // 获取单个文字或字符
            let connectText = textOfLine + singleWord;  // 连接文字
            let isLimitRow = limitRow ? rowCount === (limitRow - 1) : false;   // 计算接下来要写的是否是最后一行
            let measureText = isLimitRow ? (connectText + '...') : connectText;   // 最后一行则显示省略符,否则显示连接文字
            ctx.font = `${scaleSize(40)}px sans-serif`;     // 设置字体并计算宽度,判断是否存在首行缩进
            let width = ctx.measureText(measureText).width + scaleSize(36);
            let conditionIndent = (indentText && rowCount === 0);       // 首行需要缩进满足条件
            let measureWidth = conditionIndent ? (width + indentText) : width;
            let xPos = scaleSize(192);
            // 大于限制宽度且已绘行数不是最后一行,则写文字
            if (measureWidth > textWidth && i > 0 && rowCount !== limitRow) {
              let canvasText = isLimitRow ? measureText : textOfLine;
              let xPos = conditionIndent ? scaleSize(192) : scaleSize(36);    // 如果是最后一行,显示计算文本
              ctx.fillStyle = '#000';  // 写文字
              ctx.fillText(canvasText, xPos, canvasY);
              textOfLine = singleWord;  // 下一行文字
              canvasY += scaleSize(60); // 记录下一行位置
              textHeight += scaleSize(36);   // 计算文本高度
              rowCount++;
              if (isLimitRow) break;
            } else {
              textOfLine = connectText;    // 不大于最大宽度
            }
          }
        } else {
          ctx.font = `${scaleSize(40)}px sans-serif`;
          ctx.fillStyle = '#1a1a1a'
          ctx.textAlign = 'left'
          let ptext = info.name
          let arrText = ptext.split('')
          let prox = scaleSize(192)
          let proy = canvasY
          let lineHeight = scaleSize(44)
          let maxWidth = scaleSize(700)
          let line = ''
          for (var n = 0; n < arrText.length; n++) {
            let testLine = line + arrText[n]
            let metrics = ctx.measureText(testLine)
            let testWidth = metrics.width
            if (testWidth > maxWidth && n > 0) {
              ctx.fillText(line, prox, proy)
              line = arrText[n]
              proy += lineHeight
            } else {
              line = testLine
            }
          }
          ctx.fillText(line, prox, proy)
        }
        let codeImgY = canvasY - scaleSize(150);
        const miniCodeImg = await createLocalImg(canvas, info.codeImg)
        ctx.drawImage(miniCodeImg, scaleSize(536), codeImgY, scaleSize(180), scaleSize(180))
        canvasY += scaleSize(60)
        ctx.font = `${scaleSize(24)}px sans-serif`
        ctx.textAlign = 'center'
        ctx.fillStyle = '#999'
        ctx.fillText(`长按识别`, (width - scaleSize(130)), canvasY)
        resolve(canvas)
      } catch (error) {
        reject(error)
        wx.showToast({
          title: error.message,
          icon: 'none'
        })
      }
    })
  })
}

export default drawShareImg;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值