当前位置: 首页 > Web前端 > 正文
流量卡

小程序canvas生成海报图片压缩和失真问题解决

游魂 发表于2022年4月13日 17:36

微信小程序实现canvas按照原图等比例不失真绘制海报图,防止模糊

我这里的场景是收款二维码+收款背景图。

绘制二维码

我这里绘制二维码使用的 wxapp-qrcode ,也可以使用weapp-qrcode,基本都一样,详细代码不过多累赘,这里主要说下适配不同屏幕大小的canvas。

onLoad: function (options) {
  const size = this.setCanvasSize() // 动态设置画布大小
  this.createQrCode('www.iyouhun.com', "mycanvas", size.w, size.h)
},
// 适配不同屏幕大小的canvas
setCanvasSize: function () {
  const size = {}
  try {
    const res = wx.getSystemInfoSync()
    let scale = 750 / 686; // 不同屏幕下canvas的适配比例;设计稿是750宽,686是因为wxss样式文件中设置的canvas大小
    let width = res.windowWidth / scale
    let height = width; // canvas画布为正方形
    size.w = width
    size.h = height
  } catch (e) {
    console.log("获取设备信息失败" + e)
  }
  return size
},

绘制背景图

动态设置图片的高度和宽度

在小程序布局中,如果图片不是固定高度和高度,但image设置的是固定的高度和宽度,这时候原始图片相对image设置的固定高度和宽度不是等比例大小,那么这张图片就会变形,变的不清晰。这时就可以使用下面的等比例缩放的方式缩放图片,让图片不变形。或者通过imagebindload方法动态的获取图片的高度和宽度,动态的设置图片的高度和宽度,是图片布局的高度和宽度和原始图片的高度和宽度相等。

图片等比例缩放工具

//Util.js 

class Util{ 
  /*** 
   * 按照显示图片的宽等比例缩放得到显示图片的高 
   * @params originalWidth 原始图片的宽 
   * @params originalHeight 原始图片的高 
   * @params imageWidth   显示图片的宽,如果不传就使用屏幕的宽 
   * 返回图片的宽高对象 
  ***/ 
  static imageZoomHeightUtil(originalWidth,originalHeight,imageWidth){ 
    let imageSize = {}; 
    if(imageWidth){ 
      imageSize.imageWidth = imageWidth; 
      imageSize.imageHeight = (imageWidth * originalHeight) / originalWidth; 
    }else{//如果没有传imageWidth,使用屏幕的宽 
      wx.getSystemInfo({  
        success: function (res) {  
          imageWidth = res.windowWidth;  
          imageSize.imageWidth = imageWidth; 
          imageSize.imageHeight = (imageWidth * originalHeight) / originalWidth; 
        }  
      }); 
    } 
    return imageSize; 
  } 

  /*** 
   * 按照显示图片的高等比例缩放得到显示图片的宽 
   * @params originalWidth 原始图片的宽 
   * @params originalHeight 原始图片的高 
   * @params imageHeight  显示图片的高,如果不传就使用屏幕的高 
   * 返回图片的宽高对象 
  ***/ 
  static imageZoomWidthUtil(originalWidth,originalHeight,imageHeight){ 
    let imageSize = {}; 
    if(imageHeight){ 
      imageSize.imageWidth = (imageHeight *originalWidth) / originalHeight; 
      imageSize.imageHeight = imageHeight; 
    }else{//如果没有传imageHeight,使用屏幕的高 
      wx.getSystemInfo({  
        success: function (res) {  
          imageHeight = res.windowHeight; 
          imageSize.imageWidth = (imageHeight *originalWidth) / originalHeight; 
          imageSize.imageHeight = imageHeight; 
        }  
      }); 
    } 
    return imageSize; 
  } 

} 

export default Util;

工具库使用

<image bindload="imageLoad"  src="../test.png"/>
import Util from '../common/Util'

Page({ 
 data:{ 
    imageWidth:0, 
    imageHeight:0 
 }, 
 imageLoad: function (e) {  
    //获取图片的原始宽度和高度 
    let originalWidth = e.detail.width
    let originalHeight = e.detail.height
    let imageSize = Util.imageZoomWidthUtil(originalWidth,originalHeight,145)
    this.setData({imageWidth:imageSize.imageWidth,imageHeight:imageSize.imageHeight})
 } 
})

绘制背景图

用上面的方法动态设置图片宽高,解决失真问题

import Util from '../../libs/Util'
// 背景图
let bgImg = new Promise(function (resolve) {
  wx.getImageInfo({
    src: 'https://www.iyouhun.com/payment/payment_pic.jpg',
    success: function (res) {
      that.setData({
        imgInfo: res
      })
      // 根据屏幕宽度得到图片高
      const imageSize = Util.imageZoomHeightUtil(that.data.imgInfo.width, that.data.imgInfo.height) 
      that.setData({ canvasHeight: imageSize.imageHeight })
      resolve(res.path)
    },
    fail: function (err) {
      console.log(err)
      wx.showToast({
        title: '网络错误请重试',
        icon: 'loading'
      })
    }
  })
})

合成海报/收款码

这里使用Promise分别去绘制二维码和背景图。

// 收款码
let qrcodeImg = new Promise(function (resolve) {
  // ...
})
// 背景图
let bgImg = new Promise(function (resolve) {
  // ...
}
Promise.all([bgImg, qrcodeImg]).then(function(result) {
  wx.showLoading({title: '加载中'})
  // canvas绘制文字和图片,创建画图
  const ctx = wx.createCanvasContext('myCanvas')
  // 绘制背景图
  ctx.drawImage(result[0], 0, 0, that.data.imgInfo.width, that.data.imgInfo.height, 0, 0, that.data.canvasWidth, that.data.canvasHeight)
  ctx.setFillStyle('white')
  // 绘制二维码 二维码宽度300
  const qrX = (that.data.canvasWidth - 300) / 2 // canvas宽度 - 二维码宽度 / 2 (居中)
  ctx.drawImage(result[1], qrX, 120, 300, 300)
  // 绘制文本
  ctx.fillStyle = '#ffffff' // 背景
  ctx.fillRect(Math.floor(qrX),420,300,20)
  ctx.fillStyle = "#333333"
  ctx.font = 25 + 'px Arial' // 文本大小, 字体
  ctx.textAlign = 'center'
  ctx.fillText(
    'No.'+ that.data.serialNum,
    that.data.canvasWidth / 2, // 左上角 X坐标
    430, // 左上角 Y坐标
    300
  )
  //canvasToTempFilePath必须要在draw的回调中执行,否则会生成失败,官方文档有说明
  ctx.draw(false, setTimeout(function () {
    wx.canvasToTempFilePath({
      canvasId: 'myCanvas',
      x: 0,
      y: 0,
      width: that.data.canvasWidth,
      height: that.data.canvasHeight,
      success: function (res) {
        wx.hideLoading()
        that.setData({
          qrcodeStatus: true,
          shareImgSrc: res.tempFilePath
        })
      },
      fail: function (res) {
        wx.hideLoading()
        wx.showToast({
          title: '生成失败',
          icon: "none"
        })
      }
    })
  }, 1000))
})

效果图

全文完
本文标签: 微信小程序微信小程序合成海报canvas海报图片模糊canvas生成图片失真canvas生成图片模糊小程序绘制二维码图片等比例缩放动态设置图片的高度和宽度小程序绘制海报小程序绘制海报失真
本文标题: 小程序canvas生成海报图片压缩和失真问题解决
本文链接: https://www.iyouhun.com/m/?post=218

〓 随机文章推荐

共有3783阅 / 6我要评论
  1. 鸟叔6楼
    鸟叔来贵博客参观学习,期待回访!
  2. Everything composed was actually very logical. But, think about this, what if you
    added a little content? I mean, I don't want to tell you how to run your blog, however what if
    you added a post title to maybe grab people's attention? I
    mean 小程序canvas生成海报图片压缩和失真问题解决 - 游魂博客-分享技术,资源共享 is
    kinda boring. You should glance at Yahoo's front page and watch how
    they write news headlines to grab people interested.
    You might add a video or a pic or two to grab readers excited about what you've got to say.
    Just my opinion, it might bring your posts a little livelier.
  3. I usually ddo not create many comments, buut after reading
    a few of the responses on this page 小程序canvas生成海报图片压缩和失真问题解决 - 游魂博客-分享技术,资源共享.
    I do have 2 questions for you if it's allright. Could iit bee simpoly me
    or does it appear like some of thewse comments appear like they are written by
    brain dead individuals? :-P And, if you are posting on other social sites,
    I'd like to keep up with you. Could you post a list of the complete urls off all your shared pages
    likee your Facebook page, twitter feed, oor linkedin profile?
  4. 鸟叔地板
    鸟叔来访,欢迎回访
  5. Thanks for sharing your thoughts on 微信小程序.
    Regards
  6. Thanks for sharing your thoughts about 微信小程序.
    Regards

发表你的评论吧返回顶部

!评论内容需包含中文

请勾选本项再提交评论