从零搭建一个生成国庆头像微信小程序

861 阅读2分钟

前言:在朋友圈看到国庆头像,突发奇想自己能不能做个工具来生成头像,然后想到了小程序

1. -创建小程序

QQ截图20220307174049.png

然后我们得到一个初始化的小程序

QQ截图20220307174113.png

2. -整理文件夹逻辑

这里我们把这些原始文件都清空,得到如下文件夹

QQ截图20220307175823.png

3. -编写页面样式

开始写页面,得到如下主页面

image.png

配色参考的这个网站:webgradients.com/

接下来是内部样式

image.png

由于小程序对代码包的大小有限制,所以我们把头像样式图片放在云存储里面,优化包体积

image.png

然后再进入此页面时先从云存储空间存储到本地缓存

/* 图片下载到本地 */
  downloadImg () {
    wx.showLoading({
      title: "加载中",
    })
    // 云存储图片地址数组
    const imgUrls = [
      'cloud://xxx/image/cn-1.png',
      'cloud://xxx/image/cn-11.png',
      'cloud://xxx/image/cn-9.png',
      'cloud://xxx/image/cn-3.png',
      'cloud://xxx/image/cn-4.png',
      'cloud://xxx/image/cn-5.png',
      'cloud://xxx/image/cn-6.png',
      'cloud://xxx/image/cn-7.png',
    ]

    wx.cloud.getTempFileURL({
      fileList: imgUrls
    })
      .then(({ fileList }) => {
        const imgList = []
        fileList.forEach((item, index) => {
          const obj = {
            url: item.tempFileURL,
            name: 'cn' + index
          }
          imgList.push(obj)
        })
        // 赋值,初始化
        this.setData({
          tagList: imgList,
        })
        wx.hideLoading()
      }).catch(err => {
        wx.hideLoading()
        console.log(err)
      })
   },
   
   onLoad () {
    this.downloadImg()
   }

4. -编写上传图片和canvas绘制头像逻辑

/* 上传图片 */
  uploadHandle () {
    const _this = this
    wx.chooseMedia({
      count: 1, // 选择的最大数量
      mediaType: ['image'], // 选择的文件类型
      sourceType: ['album', 'camera'], // 可从相册选择或拍摄
      camera: 'back', // 默认后置摄像头
      success (res) { // 选择成功回调
        _this.setData({
          backUrl: res.tempFiles[0].tempFilePath // 所选文件的临时路径
        })
      }
    })
  }
/* 绘制头像 */
    draw () {
      function getImageInfo (url) {
        return new Promise((resolve, reject) => {
          wx.getImageInfo({
            src: url,
            success: resolve,
            fail: reject,
          })
        })
      }

      const { backUrl, tagUrl } = this.properties
      // 获取背景(头像)图片信息
      const backgroundPromise = getImageInfo(backUrl)
      // 获取合成元素图片信息 (tag)
      const tagPromise = getImageInfo(tagUrl)

      Promise.all([tagPromise, backgroundPromise])
        .then(([tag, background]) => {
          // 获取canvas上下文
          // createSelectorQuery默认初始时,选择器仅选取页面范围的节点,不会选取任何自定义组件中的节点
          // 需用in(this)将选择器的选取范围更改为自定义组件 component 内
          const query = wx.createSelectorQuery().in(this)
          query.select('#canvas')
            .fields({ node: true, size: true })
            .exec((res) => {
              const canvas = res[0].node
              this.setData({
                canvasObj: canvas
              })
              // 设备的缩放比
              const pixelRatio = this.data.pixelRatio
              // 设置canvas宽高
              const canvasWidth = res[0].width * pixelRatio
              const canvasHeight = res[0].height * pixelRatio
              canvas.width = canvasWidth
              canvas.height = canvasHeight

              const ctx = canvas.getContext('2d')
              // 绘制背景,填充满整个canvas画布
              const backImg = canvas.createImage()
              backImg.src = background.path
              backImg.onload = () => {
                console.log('背景')
                ctx.drawImage(
                  backImg,
                  0,
                  0,
                  canvasWidth,
                  canvasHeight
                )

                // 头像图片绘制完成后再绘制tag
                // 否则会出现tag被头像覆盖的情况
                const tagImg = canvas.createImage()
                tagImg.src = tag.path
                tagImg.onload = function () {
                  console.log('tag')
                  ctx.drawImage(
                    tagImg,
                    0,
                    0,
                    canvasWidth,
                    canvasWidth
                  )
                }
                tagImg.onerror = function () {
                  wx.showToast({
                    title: '图片加载失败,请重试',
                    icon: 'error',
                    duration: 2000
                  })
                }
              }
            })
        })
    }

5. -保存头像逻辑

/* 保存到相册 */
saveToPhone () {
      const _this = this
      wx.showLoading({
        title: '保存中...',
      })
      wx.canvasToTempFilePath({
        x: 0,
        y: 0,
        canvas: _this.data.canvasObj,
        success: function (res) {
          wx.saveImageToPhotosAlbum({
            filePath: res.tempFilePath,
            success (res) {
              wx.hideLoading()
              wx.showToast({
                title: '已保存到相册',
                icon: 'success',
                duration: 2000
              })
              // 保存成功之后关闭弹窗
              _this.closeDialog()
            }
          })
        },
        fail: function (res) {
          wx.showToast({
            title: '保存失败请重试',
            icon: 'error',
            duration: 2000
          })
        }
      });
    }

6. -最后看下成品

demo演示.gif

成品如下:

AsOiYNlmIeoH096b73c2f840fe69b790b76bed6578f8(1).png

感兴趣的同学可以体验下Toolkit Pro

gh_0381e673c579_430.jpg