微信小程序云开发快速入门(3/4)

前言

《微信小程序云开发快速入门(2/4)》分享中,我们已经将列表的查询和分页全部搞定了,可以说对于备忘录来说已经非常好用了,此时此刻码仔在脑海中已经开始幻想自己走上了人生的巅峰场景了。

可现实往往是残酷无情的,正在码仔幻想的时候,码妞气冲冲的跑到了码仔的电脑面前,恨不得把码仔的电脑都给砸了!

码妞大声说道:

"哼,快把列表页面背景图,给我换了,别人看我用备忘录都说我暗恋你,天天看你的照片,还把你的照片设置成软件背景!!!"

"我可还是单身呢,你这是存心让我找不到对象吗?"

码仔:"既然选择公开给你使用,那就需要满足下你的需求吧"

听到码仔的回复,码妞很高兴说到"等功能上线了,我以后要把背景换我的美照,天天换一张不带重复!!!"

码仔内心:"哼,事真多!"

接下来那来分析下需求的具体步骤:

图片替换需求

  1. 选择图片
  2. 上传图片
  3. 再次上传
  4. 选择图片
  5. 删除图片

在这里需要对图片的数据管理,同时还需要上传到云存储当中去。

本地图片操作

布局走起

很久没有写布局样式了,是不是有些生疏了?感觉复习一下,温故知新。当我们要调试一个页面的样式的时候,首先需要锁定当前的编译模式:

先在头部使用 image 图片组件区域放上一个拍照的icon,当用户点击icon的时候我们就去选择图片。

 <!-- 头部 -->
  <view class="head-bg">
  <!-- 省略无关布局 -->
    <image class="img-add" src="../../images/img_add.png"></image>
  </view>

然后再给它配置上样式把位置大概放在茶杯上面去,使用 position 定位。

.img-add{
  width: 50rpx;
  height: 50rpx;
  position: absolute;
  right: 65rpx;
  top: 450rpx;
}

最终的效果

然后通过 bindtap 绑定一个点击事件起去选择图片。

<image bindtap="chooseImg" class="img-add" src="../../images/img_add.png" />

选择图片

在这个 chooseImg 方法中,可以通过 wx.chooseImage() 从本地相册选择图片或使用相机拍照。

wx.chooseImage({
      count: 1,
      sizeType: ['original', 'compressed'], 
      sourceType: ['album', 'camera'],
      success (res) {
        // 由于是数组然后只取一张图片,所以默认取下标为0的图片
        console.log(res.tempFilePaths[0])
      }
    })

chooseImage 参数解释:

  • count:可以选择的照片数量,默认为9张

  • sourceType:选择图片的来源,默认可以从手机和相机中都支持。

    • album:可以来自手机相册
    • camera:可以来自手机拍照
    • 支持两个都写
  • sizeType:所选的图片的尺寸,默认是原图和压缩图都支持。

    • original:原图
    • compressed:压缩图
    • 支持两个都写,建议使用压缩图
  • success(res)

    • tempFilePaths:临时文件的路径列表
    • tempFiles:临时文件列表
    • 两个值都为数组

替换图片

选择完成之后,接下里就要把图片来显示出来,先在data中定义一个变量存放已经选择好的图片路径。

data: {
    topImgUrl:''
  }

然后把获取到的值存放在这个变量中

chooseImg(){
    let that = this
    wx.chooseImage({
      count: 1,
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera'],
      success (res) {
        that.data.topImgUrl = res.tempFilePaths[0]
      }
    })
  }

之前背景图片是通过在 css 中使用 background-image 属性设置的。

.head-bg {
  width: 750rpx;
  height: 540rpx;
  background-image: url('https://6465-demo-3gf9i3wu06a03ab1-1306451997.tcb.qcloud.la/head_bg.png');
  background-size: 100% 100%;
}

小程序无法把参数传递到css里面只能在wxml里面,所以我们需要把写成行内样式。

 <!-- 头部 -->
  <view class="head-bg" style="background-image: url('https://6465-demo-3gf9i3wu06a03ab1-1306451997.tcb.qcloud.la/head_bg.png');" >
   <!-- 省略无关布局 -->
  </view>

然后把 topImgUrl 对图片路径进行替换

<!-- 头部 -->
   <view class="head-bg" style="background-image: url('{{topImgUrl}}');" >
    <!-- 省略无关布局 -->
  </view>

然后运行一下看效果:

这个时候我们会发现一开始进来用户没有图片,所以需要给 topImgUrl 设置一个默认值。

 data: {
    topImgUrl:'https://6465-demo-3gf9i3wu06a03ab1-1306451997.tcb.qcloud.la/head_bg.png'
  }

然后我们再选择相片试试看效果,我们会发现还是没有效果,因为不支持本地图片。那么这个时候我们就需要上传到云存储。

图片上传云存储

云端文件存储,自带 CDN 加速,支持在前端直接上传/下载,可在云开发控制台可视化管理。

云存储可视化

这张默认图片其实就是我们之前手动上传到云存储上面的,打开云开发控制面板选择「存储」可以看到之前上传的背景图和气泡图。

除了可以直接对文件进行管理之外,它还支持像云数据库一样设置权限。

以及还支持缓存配置,支持多种配置策略。

上传到云存储

话不多说,接下来通过小程序把选择好的图片上传到云存储中去,在这里要使用 wx.cloud.uploadFile 将本地资源上传至云存储空间。

wx.cloud.uploadFile({
  cloudPath: 'example.png',
  filePath: '', // 文件路径
}).then(res => {
  // get resource ID
  console.log(res.fileID)
})

uploadFile 参数解释:

  • cloudPath:路径名称

    • 建议使用时间戳+随机数来生成
  • filePath:文件路径

    • 不建议存放在根目录,不便于查找
  • 返回值 res

    • fileID:文件ID,可用于查找文件详情

通过上传代码结合刚才到选择图片代码

chooseImg: function () {
    const that = this
    wx.chooseImage({
      count: 1, // 只选择一张图片
      sizeType: ['compressed'], // 使用压缩图
      sourceType: ['album', 'camera'], // 支持照相,相册
      success: function (res) {
        const filePath = res.tempFilePaths[0] //上传第一张图片
        // 生成规则:文件夹路径 + 时间戳 + 随机数 + 文件后缀
        const cloudPath = `top-img/${Date.now()}-${Math.floor(Math.random(0, 1) * 100000)}` + filePath.match(/.[^.]+?$/)[0]
        wx.cloud.uploadFile({
          cloudPath,
          filePath,
          success: res => {
            console.log('上传成功后获得的res:', res)
            that.setData({
              topImgUrl:res.fileID
            })
          },
          fail:err=>{
            console.log(err)
          }
        })
      }
    })
  }

上传成功 res

存储管理,自动生成了一个文件夹且图片上传到这里来了

删除在线文件

当然上传那就肯定有删除,因为总会有不喜欢的图片需要删除。需要使用 wx.cloud.deleteFile 从云存储空间删除文件。

wx.cloud.deleteFile({
  fileList: ['cloud://demo-3gf9i3wu06a03ab1.6465-demo-3gf9i3wu06a03ab1-1306451997/top-img/1627462991919-39954.png']
}).then(res => {
  console.log(res.fileList)
})

deleteFile 参数解释:

  • fileList:文件ID数组

    • 可以支持批量 ID 获取
  • 返回值 res

    • fileList:删除结果列表

      • 通过找到对应下标的删除结果

接下来我来拿刚才的文件ID来使用看下返回结果

获取在线链接

当获取到FileID还是无法显示,这个时候需要通过FileID去获取图片路径,使用 wx.cloud.getTempFileURL 用云文件 ID 换取真实链接。

wx.cloud.getTempFileURL({
  fileList: ['cloud://xxx', 'cloud://yyy'],
  success: res => {
    // get temp file URL
    console.log(res.fileList)
  },
  fail: err => {
    // handle error
  }
})

getTempFileURL 参数解释:

  • fileList:文件ID数组

    • 可以支持批量 ID 获取
  • 返回值 res

    • fileList:路径列表

      • 通过找到对应下标的 tempFileURL 获取图片路径

接下来我来拿刚才的文件ID来使用看下返回结果

接下来我们需要娶到路径,最终代码

chooseImg: function () {
    const that = this
    // 1. 选择图片
    wx.chooseImage({
      count: 1,
      sizeType: ['compressed'],
      sourceType: ['album', 'camera'],
      success: function (res) {
        const filePath = res.tempFilePaths[0] //上传第一张图片
        const cloudPath = `top-img/${Date.now()}-${Math.floor(Math.random(0, 1) * 100000)}` + filePath.match(/.[^.]+?$/)[0]
        console.log(cloudPath)
        // 2. 上传图片
        wx.cloud.uploadFile({
          cloudPath,
          filePath,
          success: res => {
            // 3. 获取链接
            wx.cloud.getTempFileURL({
              fileList: [res.fileID],
              success: res => {
                that.setData({
                  topImgUrl: res.fileList[0].tempFileURL
                })
              }
            })
          }
        })
      }
    })
  }

终于通过几经波折上传到图片显示出来了

相信你看到这里,肯定会吐槽为什么这么麻烦?能不能简单点?

当然可以,其实我们可以省略一步,就是去获取链接,因为 image 组件的 src 属性支持文件ID,这样机会你需要获取链接这一步骤了。

除此之外可以看到如果是自定义头部图片气泡就没有存在的意义了,因为会挡住图片本身的内容,所以我们就做个调整,如果有自定义图片就显示一张图片,如果没有就按照原来的设计来。

  1. 修改布局,抽象出来样式

    /* 头部大小 /
    .head {
    width: 750rpx;
    height: 540rpx;
    }
    /
    头部背景 */
    .head-bg {
    background-image: url('https://6465-demo-3gf9i3wu06a03ab1-1306451997.tcb.qcloud.la/head_bg.png');
    background-size: 100% 100%;
    }

  2. 具体布局结构变化,通过topImgUrl这个参数来控制显示隐藏

    <image wx:if="{{fileID}}" src="{{fileID}}" class="head"></image>
    <view wx:if="{{! fileID}}" class="head head-bg" >
    <view bindtap="randomMsg" class="head-bubble">

    <view class="user-avatar">
    <open-data type="userAvatarUrl"></open-data>
    </view>

    <text>,{{message}}</text>
    </view>
    <image bindtap="chooseImg" class="img-add" src="../../images/img_add.png" />
    </view>

  3. 上传图片完整代码

    chooseImg: function () {
    const that = this
    // 选择图片
    wx.chooseImage({
    count: 1,
    sizeType: ['compressed'],
    sourceType: ['album', 'camera'],
    success: function (res) {
    const filePath = res.tempFilePaths[0] //上传第一张图片
    const cloudPath = top-img/${Date.now()}-${Math.floor(Math.random(0, 1) * 100000)} + filePath.match(/.[^.]+?$/)[0]
    // 上传图片
    wx.cloud.uploadFile({
    cloudPath,
    filePath,
    success: res => {
    // 设置文件ID
    that.setData({
    fileID: res.fileID
    })
    }
    })
    }
    })
    },

虽然效果以及达到了,但是这样还是有个问题就是下次进来还是显示默认的图片,数据没有保存下来,所以这个时候要用到我们学到的数据库操作,如果将背景数据进行在云端数据库管理?

背景图片管理

别小看这个功能,这个功能虽然在之前我们已经实现了小程序端的业务,但是在数据逻辑处理,还是有些东西需要思考全面的。

按照惯例,先分析具体实现思路:

  1. 新建背景集合存放背景信息
  2. 保存背景的时候需添加记录
  3. 替换背景时候需删除再新增
  4. 删除背景时同时需删除图片
  5. 用户进入查询背景数据显示

以上所使用到的只是都是在之前分享内容学习过的内容,本次用同样的知识来实现下不一样的业务,相当于对大家之前知识的一个巩固复习的过程,加强大家对这些知识点的印象。

新建数据集合

用于存放背景图片信息

新建一个叫做 background 存放管理背景数据,然后我们看下权限:

因为实际业务需求中,这个背景只是当前用户可以看到,所以默认的权限就适合我们当前的业务,不需要再做调整。

定义操作接口

小程序端需要操作 background 数据库,所以我们在 api 文件夹在创建一个 background.js 来写相关的数据库操作方法。

// 获取背景
function getBackground() {
}

// 添加背景
function addBackground(data)
}

// 删除背景
function delBackground(id) {
}

// 导出声明
export {
  getBackground,
  addBackground,
  delBackground
}

根据实际的需求,分贝定义来获取背景、添加背景、删除背景,然后为了让其他js能引入使用,在最后做了一个导出声明。

保存上传背景

首先实现下添加数据的方法

// 添加背景
function addBackground(data) {
  // 1. 获取数据库引用
  const db = wx.cloud.database()
  // 2. 找到集合获取数据
  const background = db.collection('background')
  // 3. 添加创建时间
  data.createTime = db.serverDate()
  // 4. 集合添加数据
  return background.add({data})
}

在这个我给大家做了一个小小的加餐,使用了 serverDate 获取服务端时间,可用于查询条件、更新字段值或新增记录时的字段值。

serverDate 参数说明:

  • offset:单位毫米,可以设置时间偏移量

    • 支持正数(延后时间)或负数(提前时间)

    • 案例:往后一天

      • db.serverDate({ offset: 24 * 60 * 60 * 1000 })

然后再到列表页面去进行使用,先引入文件方法:

添加到 list.js 头部

import {
  addBackground
} from '../../api/background.js'

在选择完图片上传完成之后,使用添加方法:

chooseImg: function () {
    const that = this
    wx.chooseImage({
      count: 1,
      sizeType: ['compressed'],
      sourceType: ['album', 'camera'],
      success: function (res) {
        const filePath = res.tempFilePaths[0] //上传第一张图片
        const cloudPath = `top-img/${Date.now()}-${Math.floor(Math.random(0, 1) * 100000)}` + filePath.match(/.[^.]+?$/)[0]
        console.log(cloudPath)
        wx.cloud.uploadFile({
          cloudPath,
          filePath,
          success: res => {
            let data = {
              fileID: res.fileID
            }
            that.setData(data)
            addBackground(data)
          }
        })
      }
    })
  },

经过添加操作后,数据被添加到了数据库:

我们可以编辑下 createTime 字段:

可以看到这个是一个时间类型的字段参数。

添加完成之后还需要做两件事情:

  1. 进入的时候去查询背景信息
  2. 替换背景时候先删除再添加

查询背景信息

首先实现查询数据方法:

// 获取背景
function getBackground() {
  // 1. 获取数据库引用
  const db = wx.cloud.database()
  // 2. 找到集合获取数据
  const background = db.collection('background')
  // 3. 查询集合数据
  return background.get()
}

在 list.js 引入查询方法:

import {
  addBackground,
  getBackground
} from '../../api/background.js'在 onLoad 进行查询调用:

在 onLoad 进行查询调用:

/**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    // 获取背景图
    this.getBackground()
    // 获取问候语
    this.randomMsg()
  },
  // 获取背景图
  getBackground(){
    getBackground().then(res => {
      // 判断是否有数据
      if (res.data.length) {
        this.setData({
          fileID:res.data[0].fileID // 获取第一条数据
        })
      }
    })
  }

当用户进入列表页面就会显示显示已上传的背景。

替换背景信息

这里需要采用先删除后添加的方式,当然也可以采用修改的方式进行实现。在这里需要注意,无论采用什么方式都需要对之前背景文件进行删除,无用的图片就需要及时清理掉,要不然就会白白的占用服务器资源,存储资源是需要收费。虽然存储费用不贵,但是要保持一个良好的节约习惯。

先实现删除方法:

// 删除背景数据同时删除背景图片
function delBackground(id,fileID) {
  // 1. 获取数据库引用
  const db = wx.cloud.database()
  // 2. 获取集合对象
  const background = db.collection('background')
  // 3. 删除背景图片
  wx.cloud.deleteFile({
    fileList: [fileID]
  })
  // 4. 删除当条背景数据
  return background.doc(id).remove()
}

在 lis.js 引入删除方法:

import {
  addBackground,
  getBackground,
  delBackground
} from '../../api/background.js'

在这里因为删除需要id,所以在获取的背景的时候需要保存id

getBackground(){
    getBackground().then(res => {
      if (res.data.length) {
        const background = res.data[0]
        this.data.background = background
        this.setData({
          fileID:background.fileID
        })
      }
    })
  }

然后在选择图片的逻辑中判断是否有id,如果有的话证明之前上传过图片则进行删除操作

chooseImg: function () {
    const that = this
    wx.chooseImage({
      count: 1,
      sizeType: ['compressed'],
      sourceType: ['album', 'camera'],
      success: function (res) {
        const filePath = res.tempFilePaths[0] //上传第一张图片
        const cloudPath = `top-img/${Date.now()}-${Math.floor(Math.random(0, 1) * 100000)}` + filePath.match(/.[^.]+?$/)[0]
        console.log(cloudPath)
        wx.cloud.uploadFile({
          cloudPath,
          filePath,
          success: res => {
            let data = {
              fileID: res.fileID
            }
            that.setData(data)
            addBackground(data)
            // 判断是否之前上传过图片
            if(that.data.background){
              let id = that.data.background._id
              let fileID = that.data.background.fileID
              delBackground(id,fileID)
            }
          }
        })
      }
    })
  }

JS逻辑处理代码写完,意外发现上传完图片后居然发现拍照的ICON不见了,后来查看布局代码发现原来拍照ICON在未上传图片状态布局的里面,所以一并没隐藏了,我们需要把布局移除来。

<!-- 头部 -->
  <image wx:if="{{fileID}}" src="{{fileID}}" class="head"></image>
  <view wx:if="{{!fileID}}" class="head head-bg" >
    <view bindtap="randomMsg" class="head-bubble">
      <!-- 头像 -->
      <view class="user-avatar">
        <open-data type="userAvatarUrl"></open-data>
      </view>
      <!-- 问候语 -->
      <text>,{{message}}</text>
    </view>
    <!-- 原来的位置 -->
    <!-- <image bindtap="chooseImg" class="img-add" src="../../images/img_add.png" /> -->
  </view>
  <image bindtap="chooseImg" class="img-add" src="../../images/img_add.png" />

大功告成!码仔内心窃喜,于是偷偷的换上了一张它和码妞的合影。码仔前后想了想"这个功能,还是很有必要的!"。

总结

  1. 学习了小程序图片操作:wx.chooseImage() ,选择图片

  2. 小程序图片云存储管理:

    1. wx.cloud.uploadFile:上传文件
    2. wx.cloud.deleteFile :删除文件
    3. wx.cloud.getTempFileURL:获取在线链接
  3. 还对之前的学习过的数据库:新增、查询、删除操作通过实现一个需求进行了组合使用

学习更多微信小程序云开发快速入门知识请关注CRMEB

相关推荐
郭wes代码5 小时前
Cmd命令大全(万字详细版)
python·算法·小程序
.生产的驴10 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
汤姆yu15 小时前
基于微信小程序的乡村旅游系统
微信小程序·旅游·乡村旅游
计算机徐师兄15 小时前
基于TP5框架的家具购物小程序的设计与实现【附源码、文档】
小程序·php·家具购物小程序·家具购物微信小程序·家具购物
曲辒净16 小时前
微信小程序实现二维码海报保存分享功能
微信小程序·小程序
朽木成才17 小时前
小程序快速实现大模型聊天机器人
小程序·机器人
peachSoda717 小时前
随手记:小程序使用uni.createVideoContext视频无法触发播放
小程序
何极光17 小时前
uniapp小程序样式穿透
前端·小程序·uni-app
小墨&晓末18 小时前
【PythonGui实战】自动摇号小程序
python·算法·小程序·系统安全
oil欧哟1 天前
🤔认真投入一个月做的小程序,能做成什么样子?有人用吗?
前端·vue.js·微信小程序