• 欢迎关注我的微信公众号“ Falost ” 右边扫描关注 --->>

uniapp云开发头像边框小程序和红包封面小程序

JavaScript 神棍 375℃ 0评论

在 2021 年的国庆前两天,群里有人说,想弄一个给微信头像增加国旗渐变和国庆节气氛边框的小程序,并发出了一个案例。

我打开看了看,这感觉挺简单的。然后脑海中大概的形成了一个实现思路,然后说干就干,花了两个晚上的时间,就把代码给撸了出来,赶在放国庆假期之前完成了上线。

先体验一下吧,微信搜索小程序 Falost

下面就来说说实现思路吧~

这个小程序没有什么太多花里胡哨的东西,实现思路很简单

1、首先利用 canvas 将需要添加边框的头像给绘制出来;

2、然后将边框头像进行重叠绘制,保存绘制完成后的图片进行保存即可。

这思路是不是超级简单,对于一个前端开发来说,完全没有压力呀。

正所谓万事开头难,我得先确定技术方案,虽然功能不难,但是技术方案还需要选择一下。原生、taro、uniapp,就从这三个开发方案中选择了,因为考虑到使用后台管理边框数据,最终选择了 uniapp 云开发,至于你问我为什么选择 uniapp 云开发而不是原生云开发,因为 uniapp 免费啊!

好了,技术方案选择完成,那么接下来就把我之前开发的,一个uniapp云开发的小程序框架拿了出来进行了一番修改,很完美的就运行了起来。

但是,另外一个问题来了,没有素材怎么办,只能去网上找,结果很不错,在开源社区找了不少,让这个小程序开发起来更简单了。

接下来就是码代码的过程了。

设计数据表,说到设计数据库,uniapp 是真的很简单。先在项目根目录创建 uniCloud-aliyun/database 目录用来存放 schema 数据结构。schema 的具体使用可以看看官方文档。

// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
    "bsonType": "object",
    "required": ["image"],
    "permission": {
        "read": true,
        "create": false,
        "update": false,
        "delete": false
    },
    "properties": {
        "_id": {
            "description": "ID,系统自动生成"
        },
        "title": {
            "title": "边框名称",
            "bsonType": "string",
            "description": "边框名称",
            "trim": "both"
        },
        "origin": {
            "bsonType": "file",
            "title": "图片",
            "description": "边框图片",
            "fileMediaType": "image",
            "fileExtName": "jpg,png",
            "componentForShow": {
                "name": "image"
            }
        },
        "type": {
            "bsonType": "int",
            "title": "分类",
            "description": "分类",
            "foreignKey": "wz_border_image_category.type",
            "enum": {
                "collection": "wz_border_image_category",
                "field": "name as text, type as value",
                "where": "status == 1 && type > 0",
                "orderby": "sort asc"
            }
        },
        "hot": {
            "title": "热门推荐",
            "bsonType": "int",
            "description": "是否热门推荐",
            "enum": [{
                    "value": 1,
                    "text": "推荐"
                },
                {
                    "value": 0,
                    "text": "不推荐"
                }
            ]
        },
        "sort": {
            "bsonType": "int",
            "description": "值越大越靠后",
            "title": "排序"
        },
        "status": {
            "title": "状态",
            "bsonType": "int",
            "description": "状态",
            "enum": [{
                    "value": 1,
                    "text": "启用"
                },
                {
                    "value": 0,
                    "text": "不启用"
                },
                {
                    "value": -1,
                    "text": "删除"
                }
            ]
        },
        "create_at": {
            "title": "创建时间",
            "bsonType": "timestamp",
            "description": "创建时间",
            "componentForShow": {
                "name": "uni-dateformat"
            },
            "permission": {
                "read": true,
                "write": false
            },
            "forceDefaultValue": {
                "env": "now"
            }
        },
        "update_at": {
            "title": "更新时间",
            "bsonType": "timestamp",
            "description": "更新时间",
            "permission": {
                "read": true,
                "write": false
            },
            "componentForShow": {
                "name": "uni-dateformat"
            },
            "forceDefaultValue": {
                "env": "now"
            }
        }
    }
}

数据表创建完成之后,就是将获取到边框素材进行一个整理,然后通过脚本将素材文件上传到 uniapp 的云储存中,并保存数据记录。

let result = await uniCloud.uploadFile({
  cloudPath: item.image.replace('../', ''),
  fileContent: path.join('../data/json/', item.image)
});
const data = {
  type: item.type || 0,
  image: result.fileID,
  title: item.title ||'',
  sort: item.sort || 0,
  status: 1
}
const res = await db.collection('wz_border_image_urls').add(data)
// item 是整理的素材文件 json

然后,就可以开始前端代码的完成了。

先构建基本页面的框架,然后让我们的小程序,看起来好看一点吧(设计感一般般,将就看吧)

前端页面代码就不贴了,没啥亮点。直接看 js 内容吧

1、获取云端边框数据,直接调用云函数即可。

async getBorderImage(on = 1) {
  if (this.data.borderList[this.data.borderType]) return
  // 点击切换菜单 回复初始状态
  const type = this.data.borderType || 0
  if (on === 1) {
    // this.data.borderList[this.data.borderType] = []
    this.data.pageIndex = 0
  }
  this.data.pageIndex = this.data.pageIndex + 1
  const filter = {
    status: 1
  }
  if (type === 0) {
    filter.hot = 1
  } else {
    filter.type = type
  }
  const {
    result
  } = await uniCloud.callFunction({
    name: 'query_list',
    data: {
      dbName: "wz_border_image_urls",
      filter,
      order: {
        "name": "sort",
        "type": "asc"
      },
      pageIndex: this.data.pageIndex,
      pageSize: 100
    },
  })
  if (result.code === 0) {
    if (result.data.hasMore) {
      this.data.loadStatus = 'loadmore'
    } else {
      this.data.loadStatus = 'nomore'
    }    this.data.hasMore = result.data.hasMore
    let list = [...(this.data.borderList[this.data.borderType] || []), ...(result.data.list || [])]
    this.set(this.data.borderList, `{this.data.borderType}`, list)
    if (this.data.selectBorder) {
      let item = list.find(item => String(item._id) === String(this.data.selectBorder))
      this.changeBorder(item)
    }
  }
}

2、获取云端边框分类数据,同上调用

async getBorderCategory() {
  const {
    result
  } = await uniCloud.callFunction({
    name: 'query_list',
    data: {
      dbName: "wz_border_image_category",
      filter: {
        status: 1,
      },
      order: {
        "name": "sort",
        "type": "asc"
      },
      pageIndex: 1,
      pageSize: 50
    },
  })
  if (result.code === 0) {
    this.$data.borderCategory = result.data.list

  }
}

3、绘制边框,首先初始化 canvas 画布,我们需要将边框素材图片和头像下载到本地,才能进行后面的 canvas 绘制

initCanvas() {
  this.data.ctx = uni.createCanvasContext(this.data.canvasId)
  this.data.ctx.setFillStyle(this.data.canvas.background)
  this.data.ctx.fillRect(0, 0, this.data.canvas.width,  this.$data.canvas.height)
  // 画用户头像
  this.drawAvatarUrlImage()
}

4、绘制用户用户头像,需要先将微信头像下载下来

drawAvatarUrlImage() {
  let avatarSrc = this.data.avatarSrc || ''
  uni.downloadFile({
    url: avatarSrc,
    success: (res) => {
      console.log('result', res)
      this.data.ctx.drawImage(res.tempFilePath, this.changeSize(0), this.changeSize(0), this.data.screenWidth, this.data.screenWidth)
      // 画头像框
      this.drawAvatarBorderImage()
    },
    fail: function() {
      uni.hideLoading()
      uni.showModal({
        title: '提示',
        content: '无法下载头像',
      })
    }
  })
}

5、然后绘制头像边框,同意需要下载到本地

drawAvatarBorderImage() {
  let borderImg = this.data.borderImage
  // 没有头像框
  if (!borderImg) {
    // 开始生成
    return this.draw()
  }
  // // 开始生成
  // return this.draw()
  // 有头像框则继续执行
  uni.downloadFile({
    url: borderImg,
    success: (result) => {
      this.data.ctx.drawImage(result.tempFilePath, this.changeSize(0), this.changeSize(0), this.data.screenWidth, this.data.screenWidth)
      // 开始生成
      this.draw()
    },
    fail: function() {
      uni.hideLoading()
      uni.showModal({
        title: '提示',
        content: '无法下载头像框',
      })
    }
  })
}

6、最后一步就是绘制头像,并保存到相册就好

draw() {
  this.data.ctx.draw(false, () => {
    setTimeout(() => {
      this.canvasToImage()
    }, 130)
  })
}
// 生成图片
canvasToImage() {
  uni.canvasToTempFilePath({
    canvasId: this.data.canvasId,
    success: (res) => {
      uni.hideLoading()
      this.data.ctx = null
      console.log(res)
      this.toast('生成成功,正在保存', 'center', 'success', 2000)
      this.data.imageBill = res.tempFilePath
      uni.setStorageSync('imageBill', this.data.imageBill)
      uni.saveImageToPhotosAlbum({
        filePath: res.tempFilePath,
        success: () => {
          // this.tips('保存成功\n不妨分享一下~', '', 3500)
          wx.showToast({
            title: '保存成功\n不妨分享一下~',
            icon: 'none',
            duration: 3000
          })
          uni.navigateTo({
            url: `/pages/avatar/result?url={this.data.imageBill}`
          })
          // // 生成以后直接预览图片
          // uni.previewImage({
          //    current: res.tempFilePath,
          //    urls: [ res.tempFilePath ],
          // })
        },
        fail: () => {
          this.toast('保存失败\n请授权相册权限~',  'error', 3000)
        }
      });
    },
    fail() {
      uni.hideLoading()
      uni.showModal({
        title: '提示',
        content: '头像保存失败',
      })
    }
  })
}

到这里,我们的小程序想要功能基本已经完成了,但是我们为了更友好的使用,我加上了本地图片上传还有拍照头像进行编辑的功能。这里我们就需要一个裁剪功能,将拍照图片和本地上传的图片,进行一个裁剪,以便我们头像的使用,这里我们之间使用了一个开源组件 image-cropper 很方便使用,当然这里为了更好的使用,我做了一个定制化,具体可以看代码。

为了配合微信运营规范,小程序上传的图片进行了内容安全的检测,禁止色情、暴力和政治相关的内容等。

国庆上线版本就完成了,但是后来,为了有更多的花样,我添加了头像自定义功能,可以多个元素一起编辑和单个边框进行编辑。提供了更多的可玩性,并且,加入了流量主,获取一点小小的收益也是很不错的哦。

为了回馈开源社区,我在半个月前,将代码进行了开源。方便大家一起学习交流。

今天,我上线了一个红包封面领取的功能,群里有朋友想要代码。然后,我就一起放了上来,如果有需要的话,自己拿便可。

如果有兴趣,可以添加我微信(falost_cc)备注小程序,拉你进小程序交流群一起交流哦~

源码地址在公众号后台,关注 Falost 并回复 “头像边框源码” 即可获取。

转载请注明:Falost的小窝 » uniapp云开发头像边框小程序和红包封面小程序

如果你觉得这篇文章不错或者对你有帮助,想请我喝一杯咖啡,可以打赏
喜欢 (2)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址