一个简易的绘画板功能?别小看它,知识点可不少!| 【uni-app】【uniCloud】实战系列 | 猿创营

353 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

前言

本文主要记录了我在学习 uni-appuniClound 实战课程 的过程
并记录下实现代码过程中的遇到的问题、以及对应的解决方法,也记录下我对此的思考总结
具体的课程是 大帅老师的 付费课程
目前我已经学完,确实非常的不错
此项目集合已经发布到了线上,大家可以搜索小程序 鱼爸爸 体验一下
小程序刚上线,主要是把学习东西体现出来;
可能存在很多bug,大家可以反馈给我,谢谢!

系列文章

第一篇:《一个简易的绘画板功能?别小看它,知识点可不少!| 【uni-app】【uniCloud】实战系列 | 猿创营

第二篇:《github 中国区大佬排名都有谁?每天凌晨1点定时更新给你看 | 【uni-app】【uniCloud】实战系列 | 猿创营》

第三篇:《更多实用小demo,迈向独立程序员的起点 | 【uni-app】【uniCloud】实战系列 | 猿创营》

前置知识点

效果展示

画板.gif

线上小程序体验

鱼爸爸-小程序.jpg

分析功能

这个demo其实是非常简单的,总共的功能主要如下:

点击绘画板,进入绘画板页面,然后就可以作画了

其中作画的里面可以选择 画笔 的颜色,也可以调整 画笔 的半径大小,画完之后,便可以提交画作

提交完了之后,可以在绘画板作品里面看到自己的画作,会按照时间顺序排列

具体实现步骤

绘画功能

思路

绘画主要通过 canvas 来实现

在移动端,我们主要 通过 touchStartHandlertouchMoverHandler 这两个方法来不断的获取 画笔 的坐标点

获取坐标点之后,将坐标点连成线,这样就可以得到一个连贯的 每一条线

关于设置半径大小和画笔也比较简单,只需要 通过一个全局变量来控制 canvas的参数即可

具体代码如下

页面部分

<view>
        <canvas
        @touchstart="touchStartHandler"
        @touchmove="touchMoverHandler" 
         canvas-id="myCanvas">
        </canvas>
        <slider value="20" @change="sliderChange" min="5" max="80" show-value />
        <scroll-view class="scroll-view_H" scroll-x="true" scroll-left="120">
                <view v-for="(item,index) in listColor" @click="handleColor(item)" 
                         class="scroll-view-item_H" :class="[item.color === currentColor.color ? item.color : '', item.className]" :key="index">
                        <!-- {{item.label}} -->
                </view>
        </scroll-view>
        <button @click="btnPostCanvas">提交画作</button>
</view>

touch事件部分

  /**
   * 当开始触摸屏的时候的事件
   * @param {Object} e
   */
  touchStartHandler(e){
        console.log('touchStartHandler ---',e)
        // 用来接收所有的触控点,后面会有用
        this.listPoint = []
        //移动端设备通常是支持多点触摸的,这里我们不需要处理多个点,取第一个触摸点即可
        const touchPoint = e.changedTouches[0];
        this.listPoint.push({x:touchPoint.x,y:touchPoint.y})
        const context = uni.createCanvasContext('myCanvas');
        // 设置颜色:此处颜色是一个变量,可以提供用户修改【实现设置画笔的颜色的功能】
        context.fillStyle = this.currentColor.color || "red";
        //在手指的触摸位置绘制一个圆形
        // 此处的 this.radius 也是个变量 【实现设置画笔的粗细的功能】
        context.arc(touchPoint.x,touchPoint.y,this.radius,0, Math.PI * 2);
        context.fill();
        // true 不清除 canvas 之前的内容
        context.draw(true);
  },
  /**
   * 手指在触摸屏上移动时候 的回调方法
   * 频率会比较高,在实际用的时候,如果觉得卡的话,可以做一个 “防抖” 的处理
   * @param {Object} e
   */
  touchMoverHandler(e){
          console.log('touchMoverHandler ===',e)
          //获取到移动中的触摸点
          const touchPoint = e.changedTouches[0];
          this.listPoint.push({x:touchPoint.x,y:touchPoint.y})
          const context = uni.createCanvasContext('myCanvas');
          context.fillStyle = this.currentColor.color || "red";
          //在手指的触摸位置绘制一个圆形
          context.arc(touchPoint.x,touchPoint.y,this.radius,0, Math.PI * 2);
          context.fill();
          // 注意:此处 this.listPoint 就是把所有的点 都存起来的变量
          // 1. 取最后两次的点
          // 2. 将最后两次的点 连成一条直线
          let last = this.listPoint[this.listPoint.length-2]
          let next = this.listPoint[this.listPoint.length-1]
          context.beginPath();
          context.strokeStyle = this.currentColor.color || "red";;
          context.lineWidth = this.radius*2;
          context.moveTo(last.x,last.y);
          context.lineTo(next.x,next.y);
          context.closePath();
          context.stroke();
          context.draw(true);
  },

上传绘画

思路

上传绘画的功能实现:
先将canvas转换成图片
再用uniClound云存储 功能将图片存到服务器上,得到一个fileID
最后将此 fileID 与 该用户(此处为小程序的openid)关联起来形成一条数据库的记录

代码如下

uni-app代码

  /**
   * 点击提交画作
   */
  btnPostCanvas(){
          // 将 url 与 openid 关联
          let openid = getApp().globalData.openid
          if(!openid) return uni.showToast({title: '未获取到openid,请稍后再试',duration: 2000});
          //显示加载框
        uni.showLoading({title: '正在加载...'});
        //1.将指定canvas的内容生成png图片文件
        uni.canvasToTempFilePath({
          canvasId:"myCanvas",
          success: (res) => {
          //图片文件的路径
          const imagefile = res.tempFilePath;
          //2.调用uniCloud上传的方法
          uniCloud.uploadFile({
                cloudPath:Date.now()+".png",//文件名,可重复,阿里云云存储不支持子目录
                filePath:imagefile,//要上传的文件路径
                success: (res) => {
                  //3.从函数中获得上传后的云端路径fileID
                  const cloudfile = res.fileID;
                  console.log('上传后的ID===',cloudfile)
                  // 4. 将用户的 openid 与 此文件的 fileID 作为一条记录存在数据库中
                  uniCloud.callFunction({
                        name:'postpainting',
                        data:{openid,url:cloudfile},
                        success:(res)=>{
                                // 保存成功,返回上一层
                                uni.showModal({content:'保存成功',showCancel:true,success:(res)=>{uni.navigateBack()}})
                        },
                        complete:()=>{uni.hideLoading()}
                  })
                },
                fail:(err)=>{ uni.hideLoading();uni.showToast({title: '网络请求出错,请稍后再试',duration: 2000})
                }
          })
          },
          fail: (err) => {uni.hideLoading();uni.showToast({title: '网络请求出错,请稍后再试',duration: 2000})
          },
        },
        )
  },

uniClound服务端代码 【postpainting接口】

exports.main = async (event, context) => {
	//event为客户端上传的参数
	console.log('event : ', event)
	const {openid,url} = event
	// 获取数据库对象
	const db = uniCloud.database()
	// 增加一条记录
	let res = await db.collection('paintings').add({url,openid,createtime:Date.now()})
	return res
};

列表展示

思路

查看本人的绘画作品,相比上面的功能就更简单了 【主要就是服务端的查询接口】

只需要在服务端将此用户的所有画作获取到,再返回给前端即可

代码如下

exports.main = async (event, context) => {
	//event为客户端上传的参数
	console.log('event : ', event)
	const {openid,url} = event
	let db = uniCloud.database()
	let dbRes = await db.collection('paintings').where({openid}).orderBy("createtime","desc").get()
	//返回数据给客户端
	return dbRes.data
};

总结

虽然只是一个很小的demo而已,但是 麻雀虽小,五脏俱全,通过 uni-appuniClound 的配合使用,自己一个人就实现了所有的前后端的工作

后期还可以增加很多功能:比如 可以撤销每一步,等等

回头再看,以后简单的小活,全部都可以自己搞定,而不需要后端同学的配合。自己平时的一些好的想法和构思就能马上实现

最后推荐下大帅老师,确实很厉害,干货多多;

公众号里搜 大帅老猿,在他这里可以学到很多东西