1、微信小程序第6章 API应用案例(下)【案例5】模拟时钟【案例7】文件上传与下载【案例6】罗盘动画【案例8】在线聊天系统 学习目标掌握熟悉了解掌握canvas的用法12熟悉canvas 的API对象的用法3了解animation动画的用法4掌握WebSocket的使用 目录点击查看本节相关知识点【案例6】罗盘动画6.26.2点击查看本节相关知识点6.36.3【案例7】文件上传与下载点击查看本节相关知识点【案例5】模拟时钟6.16.1点击查看本节相关知识点【案例8】在线聊天系统6.46.4 知识架构6.1【案例案例5】模拟时钟模拟时钟1案例分析2前导知识3钟表页面布局4钟表页面绘制 知识架构6.
2、2【案例案例6】罗盘动画罗盘动画1案例分析2前导知识3设计罗盘页面布局4手指触摸旋转罗盘5单击按钮操作罗盘 知识架构6.3【案例案例7】文件上传与下载文件上传与下载1案例分析2前导知识3录音和上传4文件的下载 知识架构6.4【案例案例8】在线聊天系统在线聊天系统1案例分析2前导知识3编写Node.js服务器端代码4实现通信功能5编写聊天页面 6.1【案例5】模拟时钟 案例分析 模拟时钟任务需求任务需求:p 使用canvas绘制时钟,实现模拟时钟的功能。p 钟表时间与系统时间保持一致,刻度将24小时制转化为12小时制。p 绘制中心圆p 绘制外层大圆p 绘制分针、时针、秒针。6.1【案例5】模拟时
3、钟 案例分析 页面效果图:时钟模拟 6.1【案例5】模拟时钟 前导知识 canvas组件(原生组件,默认宽高为300px*225px)canvas 常用属性常用属性属性属性类型类型说明说明canvas-idStringcanvas组件的唯一标识符disable-scrollBoolean触摸点在canvas区域移动时且有绑定手势事件时,禁止屏幕滚动及下拉刷新bindtouchstartEventHandle手指触摸动作开始bindtouchmoveEventHandle手指触摸后移动bindtouchendEventHandle手指触摸动作结束bindtouchcancelEventHandl
4、e手指触摸动作被打断,如来电提醒、弹窗bindlongtapEventHandle手指长按500ms后触发,触发了该事件后进行移动不会触发屏幕的滚动binderrorEventHandle当发生错误时触发error事件,detail=errMsg:something wrong 6.1【案例5】模拟时钟 前导知识 canvas用法用法:p 创建canvas.wxml文件。canvas width:300px;height:150px;display:block;position:relative;p canvas组件默认样式如下。6.1【案例5】模拟时钟 前导知识 canvas组件默认效果图:
5、6.1【案例5】模拟时钟 前导知识 值得一提值得一提canvas组件是原生组件,它的层级是最高的,不能通过z-index设置层级,css动画对canvas组件无效。6.1【案例5】模拟时钟 前导知识 canvas绘制矩形,演示绘制的基本步骤基本步骤p 第第1步步:创建Canvas绘图上下文对象CanvasContextconst ctx=wx.createCanvasContext(myCanvas)p 第第2步步:使用Canvas绘图上下文进行绘图描述ctx.setFillStyle(red)/设置填充色为红色/画一个矩形,填充为红色ctx.fillRect(10,20,150,75)/ct
6、x.fillRect(x,y,width,height)6.1【案例5】模拟时钟 前导知识 p 第第3步步:画图ctx.draw()矩形效果图:6.1【案例5】模拟时钟 前导知识 canvas绘制笑脸,示例代码如下:p 第第1步步:创建Canvas绘图上下文对象CanvasContextconst ctx=wx.createCanvasContext(myCanvas)p 第第2步步:设置线条颜色和线宽ctx.setStrokeStyle(#ff0000)ctx.setLineWidth(2)6.1【案例5】模拟时钟 前导知识 p 第第3步步:移动画笔坐标位置,绘制(外部大圆)ctx.move
7、To(160,100)ctx.arc(100,100,60,0,2*Math.PI,true)p 第第4步步:移动画笔坐标位置,绘制(嘴巴线条)ctx.moveTo(140,100)ctx.arc(100,100,40,0,Math.PI,false)6.1【案例5】模拟时钟 前导知识 p 第第5步步:移动画笔坐标位置,绘制(左眼圆圈)ctx.moveTo(85,80)ctx.arc(80,80,5,0,2*Math.PI,true)p 第第6步步:移动画笔坐标位置,绘制(右眼圆圈)ctx.moveTo(125,80)ctx.arc(120,80,5,0,2*Math.PI,true)p 第第
8、7步步:画出当前路径的边框ctx.stroke()6.1【案例5】模拟时钟 前导知识 p 第第8步步:移动画笔坐标位置,绘制(左眼圆圈)wx.draw()笑脸效果图:6.1【案例5】模拟时钟 前导知识 canvas对象方法介绍:p CanvasContext.draw():将之前在绘图上下文中的描述(路径、样式、变形)画到canvas中。p CanvasContext.arc():创建一条弧线。p CanvasContext.rect():创建一个矩形路径。p CanvasContext.lineTo():新增一个新点,用stroke方法来画线条。p CanvasContext.moveTo(
9、):把路径移动到画布中的指定点,不创建线条。6.1【案例5】模拟时钟 钟表页面布局 clock.wxml.mycanvas width:100%;height:100%;position:fixed;clock.wxss 6.1【案例5】模拟时钟 钟表页面绘制 Page(width:0,height:0,/初始化宽高 onLoad:function()wx.getSystemInfo(),/获取系统的宽高 timer:null,onReady:function()function draw()/绘制函数 function drawClock(ctx,radius)/绘制表盘部分 functio
10、n drawHand(ctx,radius)/绘制指针部分 )clock.js 6.2【案例6】罗盘动画 案例分析 风水罗盘动画任务需求任务需求:p 实现旋转动画效果。p 实现缩放动画效果。p 实现移动动画效果。p 实现倾斜动画效果。p 实现旋转和缩放动画同时效果。p 实现旋转后缩放动画效果。6.2【案例6】罗盘动画 前导知识 wx.createAnimation()wx.createAnimation()参数对象的常用属性参数对象的常用属性属性属性类型类型说明说明durationnumber动画持续时间,默认为400,单位mstimingFunctionstring动画的效果,默认为line
11、ardelaynumber动画延迟时间,默认为0,单位mstransformOriginstringtransformOrigin样式,默认为50%50%0 6.2【案例6】罗盘动画 前导知识 animation动画对象p animation.step():动画队列。p animation.export():导出动画。p animation.rotate(number angle):从原点顺时针旋转一个角度。p animation.scale(number sx,number sy):缩放。p animation.skew(number ax,number ay):倾斜p animation.
12、translate(number tx,number ty):平移变换。6.2【案例6】罗盘动画 设计罗盘界面布局 compass.wxml 6.2【案例6】罗盘动画 设计罗盘界面布局 旋转缩放移动倾斜旋转并缩放旋转后缩放同时展示全部按顺序展示全部回到原始状态compass.wxml 6.2【案例6】罗盘动画 手指触摸旋转罗盘var animationvar angle=0 var x1,y1,x3,y3/判断坐标系是顺时针还是逆时针function judgeturn(x1,y1,x3,y3)var x2=150 var y2=150 return!(x2-x1)*(y3-y2)-(y2-y
13、1)*(x3-x2)0)compass.js 6.2【案例6】罗盘动画 手指触摸旋转罗盘 onShow:function()animation=wx.createAnimation(duration:1000,timingFunction:ease,)start:function(e)x1=e.touches0.clientX;y1=e.touches0.clientY ,end:function(e)compass.js创建动画滑动开始滑动结束 6.2【案例6】罗盘动画 单击按钮操作罗盘 rotate:function()animation.rotate(Math.random()*720-
14、360).step()this.setData(animation:animation.export(),编写rotate()函数,实现从原点顺时针旋转一个角度 6.2【案例6】罗盘动画 单击按钮操作罗盘 scale:function()animation.scale(Math.random()*2).step()this.setData(animation:animation.export(),编写scale()函数,实现缩放效果 6.2【案例6】罗盘动画 单击按钮操作罗盘 translate:function()animation.translate(Math.random()*100-5
15、0,Math.random()*100-50).step()this.setData(animation:animation.export(),编写translate()函数,实现平移变换 6.2【案例6】罗盘动画 单击按钮操作罗盘 skew:function()animation.skew(Math.random()*90,Math.random()*90).step()this.setData(animation:animation.export(),编写skew()函数,实现对 X、Y 轴坐标进行倾斜 6.2【案例6】罗盘动画 单击按钮操作罗盘 rotateAndScale:functi
16、on()animation.rotate(Math.random()*720-360).scale(Math.random()*2).step()this.setData(animation:animation.export(),编写rotateAndScale()函数,实现旋转和缩放同时进行 6.2【案例6】罗盘动画 单击按钮操作罗盘 rotateThenScale:function()animation.rotate(Math.random()*720-360).step().scale(Math.random()*2).step()this.setData(animation:anima
17、tion.export(),编写rotateThenScale()函数,实现旋转之后再缩放 6.2【案例6】罗盘动画 单击按钮操作罗盘 all:function()/旋转-缩放-移动-倾斜 animation.rotate(Math.random()*720-360).scale(Math.random()*2).translate(Math.random()*100-50,Math.random()*100-50).skew(Math.random()*90,Math.random()*90).step()this.setData(animation:animation.export(),编
18、写all()函数,实现同时展示全部动画 6.2【案例6】罗盘动画 单击按钮操作罗盘 allOrder:function()/旋转-缩放-移动-倾斜 animation.rotate(Math.random()*720-360).step().scale(Math.random()*2).step().translate(Math.random()*100-50,Math.random()*100-50).step().skew(Math.random()*90,Math.random()*90).step()this.setData(animation:animation.export(),编
19、写allOrder()函数,实现按顺序展示全部动画 6.2【案例6】罗盘动画 单击按钮操作罗盘 reset:function()animation.rotate(0,0).scale(1).translate(0,0).skew(0,0).step(duration:0)this.setData(animation:animation.export()编写reset()函数,实现回到原始状态 6.3【案例7】文件上传与下载 案例分析 文件上传、下载案例任务需求任务需求:p 实现了请求服务器文件的上传与下载。p 实现调起设备录音功能。p 实现停止录音功能。p 实现播放录音功能。p 实现上传录音文
20、件到服务器的功能 6.3【案例7】文件上传与下载 前导知识 录音APIvar rec=wx.getRecorderManager()/获取全局唯一的录音管理器recrecorderManager.start(options)/开始录音recorderManager.onStart()=)/监听录音开始事件recorderManager.onResume()=)/监听录音继续事件recorderManager.onPause()=)/监听录音暂停事件 recorderManager.onStop(res)=const tempFilePath =res)/监听录音结束事件recorderMana
21、ger.onFrameRecorded(res)=const frameBuffer =res)/监听已录制完指定帧大小的文件事件 6.3【案例7】文件上传与下载 前导知识 文件上传API wx.chooseImage(success(res)const tempFilePaths=res.tempFilePaths wx.uploadFile(url:https:/xxxx,/开发者服务器地址 filePath:tempFilePaths0,name:file,/文件对应的key formData:user:test,/HTTPS请求中其他额外的form data success(res)c
22、onst data=res.data /do something )6.3【案例7】文件上传与下载 前导知识 文件下载API wx.downloadFile(url:https:/xxxx,success(res)if(res.statusCode=200)wx.playVoice(filePath:res.tempFilePath)6.3【案例7】文件上传与下载 录音和上传录音停止回放上传index.wxml 6.3【案例7】文件上传与下载 录音和上传var tempFilePath=null /音频文件临时路径var audioCtx=wx.createInnerAudioContext(
23、)/获取音频对象var rec=wx.getRecorderManager()/获取录音管理器对象 rec.onStop(res=tempFilePath=res.tempFilePath console.log(tempFilePath)Page()index.js在Page()前面编写代码,获取音频实例对象和录音管理器对象,并在录音完成后保存音频文件的临时路径 6.3【案例7】文件上传与下载 录音和上传Page(record:function()rec.start(),stop:function()rec.stop(),playback:function()audioCtx.src=tem
24、pFilePath audioCtx.play()upload:function()wx.uploadFile()index.js开始录音停止录音回放录音上传录音文件在Page()中编写代码:6.3【案例7】文件上传与下载 文件的下载 文件的下载任务需求任务需求:p 用户单击“播放文章”按钮,调用wx.downloadFile()方法。p 把服务器文件下载到本地。p 接口调用成功后,在success()回调函数中播放音频文件。6.3【案例7】文件上传与下载 文件的下载播放文章暂停 index.wxml 6.3【案例7】文件上传与下载 文件的下载play:function()/从服务器上下载音频
25、文件 wx.showLoading(/加载提示信息)wx.downloadFile(url:*,/服务器地址 success:res=/播放音频 wx.playVoice(filePath:res.tempFilePath)pause:function()if(audioCtx.pauesd)audioCtx.paly()else audioCtx.pause index.js播放文章暂停/继续播放下载文件 6.4【案例8】在线聊天系统 案例分析 在线在线聊天案例聊天案例实现了客户端和服务器端的对话聊天,服务器端用Node.js来搭建服务,客户端通过小程序中的WebSocket API来实现。
26、在线聊天系统任务需求任务需求:p 服务器向小程序发送消息,展示在聊天界面的左侧。p 小程序向服务器发送信息,展示在聊天界面的右侧。p 小程序发送消息,服务器端收到后自动回复消息返送给小程序。6.4【案例8】在线聊天系统 案例分析 页面效果图:消息展示 6.4【案例8】在线聊天系统 前导知识 WebSocketWebSocket作用作用:p 实现了浏览器和服务器的全双工通信。p 是客户端与服务器之间专门建立的一条通道。p 建立连接后,就可以从通道中实时获取服务器的数据。注意注意事项事项:WebSocket的协议是以ws或wss开头的,在小程序中,正式项目必须使用wss协议,在开发模式下可以使用w
27、s协议。6.4【案例8】在线聊天系统 前导知识 wx.connectSocket(),创建一个WebSocket连接:wx.connectSocket(url:ws:/127.0.0.1:3000 /服务器地址)wx.sendSocketMessage(),通过WebSocket连接发送数据:wx.sendSocketMessage(data:msg,success:()=)6.4【案例8】在线聊天系统 前导知识 wx.onSocketMessage(),监听WebSocket接受到服务器的消息事件:wx.connectSocket(url:ws:/127.0.0.1:3000,)wx.onS
28、ocketOpen(function()console.log(连接成功);)/监听服务器端发送到客户端的消息wx.onSocketMessage(msg=var data=JSON.parse(msg.data)console.log(data)6.4【案例8】在线聊天系统 编写Node.js服务器端代码本节选择使用Node.js搭建开发者服务器,安装Node.js,创建项目:创建项目:npm init y 初始化项目,将会自动创建package.json配置文件。npm install websocket 安装webSocket库。npm install nodemon-g 安装nodem
29、on监控文件修改(如果已经安装则跳过此步)。6.4【案例8】在线聊天系统 编写Node.js服务器端代码执行上述命令后,在项目目录下创建socket.js文件,编写代码如下:const http=require(http)/引入WebSocketconst WebSocketServer=require(websocket).server/创建一个HTTP Serverconst httpServer=http.createServer(request,response)=response.writeHead(404)response.end()引入http模块和WebSocket库。6.4【
30、案例8】在线聊天系统 编写Node.js服务器端代码const wsServer=new WebSocketServer(httpServer,autoAcceptConnections:true)创建一个webSocket Server。事件监听。wsServer.on(connect,connection=connection.on(message,message=if(message.type=utf8)var data=content:自动回复,date:2019-01-16 connection.sendUTF(JSON.stringify(data)/服务器返回的信息 )6.4【案
31、例8】在线聊天系统 编写Node.js服务器端代码 连接的关闭监听。/连接的关闭监听 connection.on(close,(reasonCode,description)=console.log(+new Date()+Peer +connection.remoteAddress+disconnected.)6.4【案例8】在线聊天系统 编写Node.js服务器端代码 接收控制台中的输入。/接收控制台中的输入 process.stdin.on(data,function(data)var data=data.toString().trim()data=content:data,date:2
32、010-01-01 connection.sendUTF(JSON.stringify(data)6.4【案例8】在线聊天系统 编写Node.js服务器端代码 暴露对外访问接口地址。app.listen(3000,()=console.log(+new Date()+server is listening on port 3000)保存上述代码后,执行如下命令,启动服务器。nodemon socket.js 6.4【案例8】在线聊天系统 实现通信功能 创建空白项目,在app.json中添加页面路径。pages:pages/index/index ,window:backgroundTextSt
33、yle:light,navigationBarBackgroundColor:#fff,navigationBarTextStyle:black 6.4【案例8】在线聊天系统 实现通信功能 进入index.js中,连接服务器测试。Page(onLoad:function()wx.connectSocket(url:ws:/127.0.0.1:3000 )/连接成功 wx.onSocketOpen(function()wx.sendSocketMessage(data:你好)wx.onSocketMessage(function(msg)console.log(msg)wx.onSocketCl
34、ose(function(res)console.log(WebSocket已关闭)6.4【案例8】在线聊天系统 实现通信功能执行上述代码,在服务器控制台看到输出结果。message content from client:你好小程序端控制台接收消息结果,如下图所示:6.4【案例8】在线聊天系统 编写聊天界面 index.wxml 6.4【案例8】在线聊天系统 编写聊天界面 发送 index.wxml 6.4【案例8】在线聊天系统 编写聊天界面进入index.js文件,监听服务器发送给客户端的消息,并将消息显示在页面中。wx.onSocketMessage(msg)=var data=JSON
35、.parse(msg.data)data.role=server /设置角色;data.id=+this.id var list=this.data.newslist;list.push(data)this.setData(newslist:list,/将新消息追加到消息列表 message:null /发送完成之后清空输入框信息 )this.rolling_bottom()6.4【案例8】在线聊天系统 编写聊天界面编写rolling_bottom()方法,使聊天内容始终显示在最底端。rolling_bottom:function()var s=0 var list=wx.createSele
36、ctorQuery().selectAll(.list)list.boundingClientRect(rects=rects.forEach(rect=this.setData(scrollTop:rect.bottom).exec(),6.4【案例8】在线聊天系统 编写聊天界面编写input输入框绑定事件bindChange()函数,监听input值的改变。bindChange(res)this.setData(message:res.detail.value)初始化data:数据。data:scrollTop:0,message:,newslist:/消息列表数组 ,6.4【案例8】在线
37、聊天系统 编写聊天界面编写“发送”按钮绑定事件send()函数,判断发送内容是否为空。id:0,send:function()/判断发送内容是否为空 if(this.data.message)/如果不为空 wx.sendSocketMessage(data:this.data.message)this.rolling_bottom();var list=list=this.data.newslist var temp=list.push(temp);this.setData(newslist:list,message:null)else ./在后面编写发送对象为空的逻辑代码 this.roll
38、ing_bottom()6.4【案例8】在线聊天系统 编写聊天界面var temp=id:this.id+,/id content:this.data.message,/输入的内容 /系统时间,引用utils/util.js 中formatTimeNew函数 date:utils.formatTimeNew(new Date(),role:me/角色编写temp对象。6.4【案例8】在线聊天系统 编写聊天界面编写发送对象为空的逻辑代码。else /弹出提示框 wx.showToast(title:消息不能为空哦,icon:none,duration:2000 )this.rolling_bottom()6.4【案例8】在线聊天系统 编写聊天界面编写关闭页面的onUnload()函数,关闭WebSocket连接。/页面卸载,关闭连接onUnload:function()wx.onSocketClose(function()console.log(连接已断开)本章总结本章讲解了canvas绘图、animation动画、文件上传与下载、录音与播放,以及通过WebSocket实现在线聊天系统。通过本章学习,读者应掌握这些技术的使用,能够利用canvas来绘制各种图形;能够使用animation动画实现移动、旋转、移动、缩放等效果;能够根据实际需求开发文件上传、下载、录音、在线聊天等功能。