前段时间我还在想,如果小程序能使用无服务器计算产品那该多好,果不其然,最近微信与腾讯云联合开发的原生 serverless 云服务产品——小程序 · 云开发,其具备简化运维、高效鉴权等优势,让你零门槛快速上线小程序。为此,我决定尝试下这种新的开发方式,看看是不是真的如官方所说。
那么,用什么项目去尝试呢?看了下自己以前写的文章,发现这篇如何在小程序中实现人脸识别功能文章关注量还挺多,况且腾讯云人脸识别API于2019年1月25日全量更新为了最新的3.0版本,API调用方式及也有较大变化。我完全可以用最新版的API结合云开发去体验下这个过程。
当然,最大的优势在于省钱!!!小程序 · 云开发这款产品还在免费阶段,同时腾讯云人脸识别服务每月为各个接口提供 1 万次 的免费调用,很划算。
这篇文章将分享我开发过程中的一些思路,如何考虑产品应用性,如何优化逻辑等问题。同时也会分享整个的开发过程,从怎么注册账户到怎么调用API,以及代码是如何一点一点拼接的。大家也可以将这篇文章看为一篇教程,我会从0~1分享整个项目的开发过程。当然,如果你是一名Developer,请直接使用我撰写好的代码,已经分享到了GitHub,欢迎大家参阅!
那么,我们就开始吧!
在撰写代码之前,我们需要先准备一下小程序的开发环境,所需要的环境有Git
、NodeJS
、npm
、微信开发者工具
。同时,因为要调用腾讯云人脸识别API,我们还需要注册腾讯云的账号,同时还需要注册腾讯云的API密钥。
git是一个分布式版本控制软件,开发小程序的时候做好代码版本控制非常重要,如果代码写错,可以使用Git快速恢复。安装Git较为简单,我们只需要打开Git官网,点击右侧的Download 2.20.1 for Windows
,当然,版本号和系统都可能不同,大家按照自己的系统及最新的版本号下载即可。
下载完成后双击打开安装包,然后一路点击下一步直至安装完成。安装完成后我们按键盘上的Win
+R
,然后输入CMD
打开命令提示符窗口,然后在命令提示符窗口中输入git
,如果你看到类似下面的截图,证明你的Git安装成功,可以进行下一步了。
NodeJS是一个可以跨平台在服务端运行JavaScript的运行环境,我们小程序云开发所使用的服务端环境就是NodeJS,为了优化并测试代码,建议在本地安装NodeJS运行环境。npm是Node包管理器,通过npm包管理器,我们可以非常方便的安装云开发所需要的环境。
首先,我们打开NodeJS官网,下载NodeJS安装包。
下载完成后双击打开,并一路下一步安装。
安装完成后,打开命令提示符,试试node
命令和npm
命令是否正常。
看到如图类似的内容,证明你的node
和npm
都已经安装成功了。
开发小程序的第一步,你需要拥有一个小程序帐号,通过这个帐号你就可以管理你的小程序。
点击 https://mp.weixin.qq.com/wxopen/waregister?action=step1 根据指引填写信息和提交相应的资料,就可以拥有自己的小程序帐号。
如果你注册过小程序,可以点击右侧的立即登录。如果没有的话,请重新注册,值得注意的是,邮箱必须填写未在微信公众平台、未在微信开放平台、个人未绑定的邮箱,不然这里是无法注册的。密码请填写你能记住的密码即可。
现在登录https://mp.weixin.qq.com/,点击左侧的设置——开发设置,在这里,我们就能看到你小程序的AppID了。
当小程序的ID拿到之后,我们就可以下载安装开发工具了。
现在,打开 开发者工具下载页面 ,根据自己的操作系统下载对应的安装包进行安装。
我这里使用的是Windows 64位操作系统,所以我点击Windwos 64位
按钮进行下载。下载完成后,右键,然后以管理员身份运行安装文件。
之后,一路点击下一步安装即可。
接下来,就可以开始运行开发者工具了。使用前需要我们扫描二维码才能开始使用,请打开微信,然后点击发现——扫一扫,扫描开发者工具展示的二维码,之后在手机上点击登录即可。
如果要使用人脸识别API,必须在腾讯云进行实名认证,实名认证后,您可以登录腾讯云 控制台进行使用。如果没有账号,请参考账号 注册教程。注册完成后,需要创建相关开发密钥,不然无法使用API。
您需要在 访问管理 创建密钥,点击图中的新建密钥,即可创建密钥。
创建完成后,点击SecretKey的显示按钮,显示当前SecretKey,然后将APPID
、SecretId
、SecretKey
记录下了,后面教程中使用。
现在,开发小程序所需要的所有环境就已经搭建完成,我们可以开始创建一个新的项目了。
首先,我们新建一个云开发的项目,注意AppID
是你自己在小程序AppID,同时不要勾选建立云开发模版。
接下来,我们新建两个目录,一个目录(client)存放小程序的客户端,一个目录(server)存放小程序云开发的服务端,如图。
接下来,打开配置文件project.config.json
,我们需要新增两行文件。
1 | "cloudfunctionRoot": "server/", |
cloudfunctionRoot
参数填写你新建的云开发服务器的文件目录,miniprogramRoot
填写你小程序客户端的目录,如图。
当你的server
文件夹图标变成了☁的样式,证明我们云开发环境就搭建完成了。
在开始写代码之前,我们先理一下思路。什么东西放在服务端,什么东西放在客户端?
从安全角度考虑,我们在腾讯云申请到的API密钥是不能暴漏的,否则别人可以通过抓包去获取我们的ID,从而滥用造成经济上的损失,接下来就是为了识别人脸而上传的图片文件,用户数据十分重要,图片千万不能暴漏。小程序官方也提供了一些如数据库、存储、云函数所相关的能力,我们可以通云开发提供的云函数能力将腾讯的API密钥存放在服务端运行,同样的,也可以使用期所提供的云存储和数据库存放用户的图片及数据。
从产品开发角度考虑,希望产品运行足够的快,减少客户端与服务器的通讯次数,降低运维压力,增加并发数,同时,也要考虑到后期维护,所以代码尽可能的精简。
具体思路是这样子的:
- 客户端选择完图片,然后在小程序端调用云存储上传API上传图片到云存储,之后由云存储返回一个文件的ID到客户端。
- 客户端获取文件上传后的ID,调用云函数,在云函数端去读取云存储的文件,读取其真实的URL地址。
- 将获取到的地址在云函数端发送至腾讯云人脸识别API,等待人脸识别接口返回相关内容。
- 人脸识别API返回内容后,云函数原封不动的将数据发回给客户端。
- 客户端做解析,并展示给前端。
整个过程云函数只与客户端通讯两次,同时将人脸识别API调用及用户图片存放在服务端,保证密钥及资料的安全,能够达到我们的要求。
首先,我们先开发服务端,因为服务端作为架构的中心枢纽,负责接收和发送数据,非常重要。当开发完服务端,撰写客户端数据处理的时候,才能事半功倍。
接下来,我们开始新建云函数,在server
文件夹上面点击右键,选择新建NodeJS云函数
,然后输入你要建立云函数的名称,我这里命名为Face_Detection
。
新建完成后,系统会自动生成index.js
和package.json
文件。其中index.js
是官方给出的Demo文件,我们将生成的代码稍微处理下,只保留最基本的模版。
云函数 - index.js
1 | // 云函数入口文件 |
我们打开腾讯云人脸识别的官网,先看看官方文档的API怎么调用。
我们看到API概览中有很多人脸相关的接口,因为我们只做最基本的人脸检测,所以,选择人脸检测与分析相关接口
。
点击人脸检测与分析DetectFace
接口,查看API文档。我们看到接口提供了人脸(Face)的位置、相应的面部属性和人脸质量信息,位置包括 (x,y,w,h),面部属性包括性别(gender)、年龄(age)、表情(expression)、魅力(beauty)、眼镜(glass)、发型(hair)、口罩(mask)和姿态 (pitch,roll,yaw),人脸质量信息包括整体质量分(score)、模糊分(sharpness)、光照分(brightness)和五官遮挡分(completeness)等信息的识别,那么我们的小程序所返回的相关数据也逃不出这几个内容,所以,给用户展示的信息建议也从这里面的参数中选取。向下拉,查看请求相关参数。
请求参数如图,必填的是Action
和Version
,分别对应接口名称及版本号,按照文档,我们这里选择DetectFace
和2018-03-01
。其他数据是选填的,如MaxFaceNum
人脸数,Url
图片的地址等。我们项目架构中由云存储所分享的是图片的地址,所以URL
参数是必要的。同时我们想获取图片的人脸属性信息,所以按照表内容的内容,NeedFaceAttributes
参数也是必要的。
输入参数看完了,我们看看输出参数。
输出参数有4组,分别是图片的宽高,人脸的信息以及请求的ID。当然,最重要的还是我们的FaceInfos
参数,我看点击蓝色的FaceInfos
,看看具体有什么内容。
数据蛮多的,这里的FaceAttributesInfo
参数我们会用到,因为在输入参数中,我们需要NeedFaceAttributes
,所以当NeedFaceAttributes
参数等于1
的时候,FaceAttributesInfo
参数才会返回相关的数据,我们点开FaceAttributesInfo
参数看看。
这里就是返回参数的具体数据了,有性别,年龄,微笑程度等信息,具体大家请看描述。我们看到还有一个Hair
参数,是头发的长度、刘海、发色等信息,点开FaceHairAttributesInfo
看看。
这里就是该接口的相关信息及所有的参数了,心里大概有个底就可以了。
继续向下看文档,我们发现,API中给我们提供了相关的SDK。因为我们客户端的代码是NodeJS的,官方也提供了相关的SDK,那么就直接使用吧!
咦,等下,API Explorer
是什么,点击去看看,原来,这是官方给我们提供的一个GUI页面,通过简单的设置,即可生成API调用的代码,能显著降低使用云 API 的难度。
我们就用这个工具来生成我们NodeJS端的代码吧!(注:当然,这里也可自己写相关代码去调用API,但是文档中对签名验证这块讲的模糊不清,所以我还是打算使用SDK)
点开API Explorer工具,我们看到一个页面,我们看到框内有我们前面所准备的SecretId
和SecretKey
,同时也有前文中我们提到的输入参数Url
、NeedFaceAttributes
等。等下,必填Action
和Version
参数去哪里了?
原来,当我们进入人脸识别的页面后,系统已经自动帮我们填写好了Action
和Version
参数,我们只需要直接使用就行了。
我们填写下SecretId
和SecretKey
这两个参数,然后Url
参数中,我们填入一张人脸的图片,这里大家可以自己去搜索下,然后将图片的地址粘贴到这里就可以。最后,将NeedFaceAttributes
参数为1
,根据文档,我们要返回人脸属性。Region
参数大区可以不填,文档中已经说明。
如图,当填写完后,我们点击代码生成,然后选择NodeJS
,系统会自动生成我们所需要的代码。(这里有个BUG,URL地址不识别冒号,希望官方修复)
我们点击右侧的在线调用,然后点击发送请求,看看是否返回了正常的数据。
如图,这样的数据就是正常的响应结果。如果显示说您未开通人脸识别服务,请前往这里开启。我们回到代码生成页面,复制NodeJS环境的所有代码。
1 | const tencentcloud = require("../../../../tencentcloud-sdk-nodejs"); |
我们分析下代码,第一行代码是引入名为tencentcloud-sdk-nodejs
的包文件,这个是腾讯云SDK所依赖的文件。后面几行代码就是声明人脸识别的相关版本,定义HTTP请求等。之后的cred
是声明我们的在腾讯云的相关密钥,注意你使用的时候改成自己的,httpProfile.endpoint
是我们的接口地址,接下来是重点,params
参数是我们人人脸识别特有的接口,后续要增加或删除相关参数都在这里操作。最后的内容是回调函数,并通过console.log
控制台输出,那么如何在小程序端调用呢?
我们稍微修改下代码。
云函数 - index.js
1 | const cloud = require('wx-server-sdk')// 云函数入口文件 |
这里,我们将官方所给的代码封装成名为synDetectFace
的函数,然后在最后通过synDetectFace()
去调用这个函数。exports.main
暂时留空,我们先做第一步测试。注意删掉tencentcloud
参数中多余的../../../../
因为后面我们将用npm包管理器安装这个依赖,无需多余的../../../../
。
接下来,我们需要安装相关的依赖文件,因为不管是运行云开发还是运行腾讯云SDK都需要相关的依赖文件,这里,我们就需要用到NodeJS
运行环境和npm
包管理器了。在我们的云函数目录上面右键,选择在终端中打开
。
然后输入下面的命令,通过npm
包管理器,安装云函数和腾讯云SDK的依赖文件。
1 | npm install tencentcloud-sdk-nodejs --save |
这两行命令即可安装我们需要的依赖文件,如图所示。
不要关闭这个窗口,我们对我们的人脸识别接口进行测试,看看能否正常返回数据,运行下面的命令。
1 | node index.js |
如果看到类似的内容,就证明你的代码配置没有错误,可以进行下一步了。
根据上面的架构,我们在服务端获取到文件的ID后,使用文件ID去云存储文件的URL地址,目前我们在云存储端还没有文件。那么,第一步,将文件上传到云存储。还好,云开发控制台可以直接上传文件,打开控制台,点击存储管理
,如图。
我们在这里随便上传一个文件,建议上传一张人脸的照片,已方便我们后续测试。上传之后点击右侧的复制按钮,复制文件的ID。
接下来,我们打开小程序云存储上传文档,调用getTempFileURL
接口,然后将ID传送给云存储。等待云存储返回URL地址,这里我们直接复制官方文档给出的代码。
1 | const cloud = require('wx-server-sdk') |
将代码中的cloud://xxx
更换为刚才复制的文件ID。
1 | const fileList = ['cloud://test-f97abe.7465-test-f97abe/demo.jpg'] |
现在,打开我们云函数的index.js
文件,将上面的代码整合到其中,并将返回的内容result.fileList
打印到控制台。
云函数 - index.js
1 | const cloud = require('wx-server-sdk')// 云函数入口文件 |
接下来,我们部署下云函数,让其在云开发端运行,我们看看能不能正常读取到我们所需要的文件。在云函数上右键,选择上传并部署:所有文件
,这一步,我们将我们刚刚写的代码及所需要的依赖环境部署在服务端。
当弹出的对话框显示上传并部署完成后,我们就可以打开云开发的控制台进行测试了。
点击云函数按钮,选择我们刚刚上传的云函数,然后单击右侧的测试。
当点击运行测试
按钮后,查看当前返回结果,如果显示成功,返回结果内有你提交的文件ID及文件的URL地址,证明我们云存储在服务端的调用执行成功。
既然腾讯云人脸API和云函数端的云存储API已经调用并测试成功,那么就需要我们整合下两个代码,因为现在咱们服务端的代码是分离的,况且代码中传入的图片也不是我们想要的图片。
云函数 - index.js(最终版)
1 | const cloud = require('wx-server-sdk') //小程序云开发SDK |
我们将两个代码进行了整合,并增加了相关的备注。
首先,将腾讯云人脸识别API整体封装成为一个名为synDetectFace
异步函数,该函数携带名为url
的变量,当调用函数的时候,我们传入url
参数,函数会通过Promise
方式将人脸识别返回的内容重新返回给调用端。
接下来,为了方便云函数的调用,我们将客户端传过来的内容(文件ID)存为变量data
,并向云存储发起URL请求,将请求的返回值传到异步函数synDetectFace(url)
,此时,该函数会向腾讯云发起AI识别请求,返回的请求值最终会返回给客户端。
修改完代码,别忘了部署在服务端。到这一步,我们服务端的开发工作就全部搞定了。
服务端开发完成后,我们已经完成了三分之二的代码,接下来就是撰写客户端的代码。关掉server
文件夹。打开client
文件夹,然后新建一个名为app.json
的文件,如图。
将下面的代码复制到app.json
文件中。
1 | { |
保存完成后,系统将自动生成相关目录及文件。
根据流程,我们的第一步就是选择图片了,小程序官方也提供了图片选择API,废话不多说,我们直接看代码。首先,打开index.js
文件,注意,这里选择的是客户端的文件,不是服务端的。
客户端 - index.js
1 | // pages/index/index.js |
同样,官方也提供了一堆已经存在的函数,为了方便我们撰写代码,我们删除用不到的内容。
客户端 - index.js
1 | Page({ |
data
存放我们一些静态数据,以便前端调用,onLoad
是小程序的初始化执行函数,当小程序页面加载成功后会自动调用该函数,我们后续会用到。
接下来我们新建一个函数,这个函数用于当用户在前端点击某个按钮的时候,会执行该函数,我们将其命名为UploadImage
。
客户端 - index.js
1 | Page({ |
参考小程序官方的文档中的示例代码,修改代码如下。
客户端 - index.js
1 | Page({ |
参考官方的文档,参数中,我们定一个图片的张数,图片的尺寸、来源。之后该API回调返回tempFilePaths
临时图片地址。
后端函数写完了,我们需要点击一个按钮执行上传,撰写下前端,打开index.wxml
文件,修改代码如下。
客户端 - index.wxml
1 | <button type="primary" bindtap="UploadImage">上传照片</button> |
当用户点击图中的上传照片按钮的时候,会自动调用我们在后端撰写的UploadImage
函数,如图。
当我们选择照片后,会在控制台输出当前文件的临时地址,有了临时地址,接下来一步就是将临时地址传给云存储的API,让其将文件上传。
同选择图片API一样,微信官方文档中也提供了相关的实例代码。我们可以直接使用,先看代码。
客户端 - index.js
1 | Page({ |
当上传图片API返回tempFilePaths
参数后,我们需要将其传入云存储上传文件的目录。,根据文档,filePath
参数就是文件资源的目录。我们直接将返回tempFilePaths
参数放在该参数下,当选择完图片,会自动调用该API上传名为example.jpg
的图片文件,同时我们上传的文件只有一张,也就是临时目录的第一张,所以返回的参数应改为res.tempFilePaths[0]
。
根据文档要求,在调用云开发之前,我们还必须初始化,才能正常使用。所以代码中我们调用了wx.cloud.init
方法,并填写了env
参数,这里的参数请改为你自己的,打开云开发控制台可查看到你的环境ID
。
上传成功后,返回回调内容,并在控制台打印出其文件ID。
控制台第一行是我们选择图片后的临时地址,第二行上传到云存储后的文件ID。
当云存储调用完成后,我们拿到了文件的ID,下一步就是真正的调用云函数了,我们将文件ID传给云函数,并等待云函数返回人脸识别的结果。看一下官方的文档。
我们必须填写的有云函数的名字,选填的有data
和config
,由于我们不更改局部配置文件,所以config
用不到。但是我们需要将我们的文件ID传送给服务端,所以要填写的还有data
参数。
参考官方代码,我们调用下上面撰写的Face_Detection
云函数。
客户端 - index.js
1 | Page({ |
这里的代码逻辑是,当我们图片上传完成后,通过返回的文件ID去调用名为Face_Detection
的云函数,该函数在服务端进行一系列操作后,将数据返回给客户端,最终通过控制台打印出来。
如果看到类似的结果,证明客户端基本的请求操作已经写完,这里返回的内容就是我们人脸识别后腾讯云API所返回的数据,我们可以进行下一步操作了。
当然,这里代码中有一个BUG,就是所有上传的图片名称都是example.jpg
,一个人使用当然不会造成什么问题,但如果多个人并发使用这个小程序,就会产生一个很大的BUG,同一时间内请求的图片地址相同,那么返回的结果也相同,更有可能造成云存储系统BUG。
为此,我将图片的名称变更为一个随机数,这个同一时间内随机数的内容不同,那么图片请求的时候就不会有多大问题,修改代码如下。
客户端 - index.js
1 | Page({ |
我们新增了一个名为random
的随机数,这个随机数是当前的UTC时间与4位随机数相加而得到的一个结果,然后将这个随机数存为我们的图片文件的名称。这样写的好处是,在同1秒内,最多可以支持1000张图片的并发。
接下来,我们将返回的数据展示在前端,先随便找一个参数返回在前端。先简单测试下,我们将部分数据输出到控制台。首先,我们看看腾讯云人脸识别返回的参数列表。
简单点,我们返回人脸Beauty
参数到控制台吧,参考人脸识别返回的json数据,修改上面代码中的console.log(res.result)
返回参数。
1 | console.log(res.result.FaceInfos[0].FaceAttributesInfo.Beauty) |
再次上传一遍数据,看看返回结果变成什么了。
这里返回的就是当前的魅力值,接下来,我们将这里的魅力数据传到前端。我们可以使用官方的setData
方法。修改整体代码如下。
客户端 - index.js
1 | Page({ |
客户端 - index.wxml
1 | <button type="primary" bindtap="UploadImage">上传照片</button> |
我们在data
中,新增一个Beauty
变量,然后在下面的UploadImage
函数中,使用myThis.setData
函数改变变量Beauty
数据。最后,我们在index.wxml
文件中去显示这个返回的内容。
当然,返回的一个参数没有多大用,我们将后台的所有数据都返回到前端,并参考腾讯云官方的文档,优化下首页显示。
客户端 - index.js
1 | Page({ |
客户端 - index.wxml
1 | <button type="primary" bindtap="UploadImage">上传照片</button> |
如图,我们已经将所需要的数据展示在前端了。但是展示的不够完美,很多数据给用户展示用户也无法看懂。比如性别:0
、头发长度:3
、有无刘海:1
等。参考腾讯云API文档,我们将这里的数据使用switch
和if
语句做下判断,不同的数据返回不同的内容,让用户看明白。
客户端 - index.js
1 | Page({ |
现在,我们已经将返回的内容正常显示在前端了。
接下来,我们可以优化前端了。
首先,最难看的莫过于这里交错的文字了,这里就需要修改index.wxss
文件。
客户端 - index.wxss
1 | .text_viwe_size{ |
我们定义一下文本显示框的大小,并定义文本显示方式和色彩。然后,修改index.wxml
文件,让其引用index.wxss
文件。
客户端 - index.wxml
1 | <button type="primary" bindtap="UploadImage">上传照片</button> |
参考小程序官方的文档,调用progress
组件,我们新增一个进度条组件,打开index.wxml
文件,先在前端显示相关内容。
客户端 - index.wxml
1 | <button type="primary" bindtap="UploadImage">上传照片</button> |
当然,前端展示了还无法显示当前进度,我们需要在后端调用返回相关进度,然后再向前端展示。
客户端 - index.js
1 | Page({ |
这里的代码中,我们将wx.cloud.uploadFile
存为名为uploadTask
的变量,然后在最后调用onProgressUpdate(res)
方法,并通过setData
方法,将数据展示在前端。接下来,优化下wxss
的代码,将前端修改漂亮点。
客户端 - index.wxss
1 | .text_viwe_size{ |
现在展示端还不够完美,人脸识别,当然是要将用户的照片展示在前端,我们在index.wxml
文件中插入图片。
客户端 - index.wxml
1 | <view class="image_viwe_size"> |
然后,我们需要在后端去写image_src
图片地址,做展示,打开index.js
文件,在data
中指定图片地址。同时,当用户点击图片上传按钮的时候,我们将图片地址替换为上传的临时文件。
客户端 - index.js
1 | Page({ |
最后,优化下前端的index.wxss
文件。
客户端 - index.wxss
1 | .image_viwe_size{ |
现在,整个UI好看多了。
现在,我们已经有了上传图片进度条,但是用户上传图片后没有相关提示信息给用户,用户也不知道图片上传后是返回结果是不是正常的。那么,怎么去优化这块呢?幸好微信官方给我们提供了交互接口,我们直接调用就行,直接上代码。
客户端 - index.js
1 | Page({ |
图片文件选择成功后,我们调用wx.showLoading
接口,展示加载中的提示框。当云函数回调成功后,我们立刻调用wx.hideLoading
隐藏加载中的提示框。同时,我们调用wx.showToast
接口,显示消息成功提示框。
现在,我们就完成了一款人脸识别小程序产品的开发,并能够正常展示给用户。
项目终于写完了,你学会了整体的小程序·云开发并通过腾讯云人脸识别流程了吗?希望这篇文章能给你带来一些新的经验和想法!
当然,这里的项目还有一些问题,比如图片上传到云存储后会一直存在,没有清空缓存的机制。比如一秒内用户最大并发是1000,因为图片我们设置的随机数最大是1000,后面建议将随机数改为读取图片的md5
值然后显示出来。这些BUG我也会慢慢去优化,喜欢请关注(Star)我的小程序人脸识别项目(https://github.com/Techeek/WX_TencentAI_Face)。
感谢您阅读我的文章,如果有什么新的意见或者建议,请在评论区留言。BUG反馈请在Github提交Issues。
]]>当然,小程序·云开发这款产品可不止调用云函数这个功能,云开发提供了一块存储空间,提供了上传文件到云端、带权限管理的云端下载能力,开发者可以在小程序端和云函数端通过 API 使用云存储功能。
今天的这篇文章中,我们将介绍如何使用云开发上传和下载文件,在教程开始之前,需要搭建搭建好小程序的基础开发环境和云开发的基本环境,关于如何配置,大家可以参考如何入门小程序开发和如何进行小程序云函数开发这篇两文章的入门教程。
小程序官方文档给我们提供了两个方式去调用存储API,分别是从客户端调用及从云函数端调用,两种调用方式有一点点差异,这篇文章中,我们将分两块对存储API调用进行讲解。
小程序·云开发提供了一系列存储操作 API,此处是存储小程序端的 API 参考文档。
API | 说明 |
---|---|
uploadFile | 上传文件 |
downloadFile | 下载文件 |
deleteFile | 删除文件 |
getTempFileURL | 换取临时链接 |
废话不多说,我们先上代码给大家演示下这个过程,这一步需要大家准备一个文件,不管是图片还是视频都可以,然后将其放在你小程序的client
目录任意位置。为了演示方便,我这里将图片存放在与首页index.js
同级目录下(注意是你小程序客户端的目录,不是云开发的目录!),如图。
接下来,我们打开index.js
文件,写下下面的代码。
1 | Page({ |
和调用云函数一样,我们需要使用wx.cloud.init
API去初始化云函数,在env
内填写你云开发的环境ID,每个人的ID都不相同,请在云开发控制台找到你自己的环境ID填入。
之后我们调用了上传文件的APIwx.cloud.uploadFile
,cloudPath
为你需要上传在云开发的文件名,我们想将文件上传后改名,则命名为test1.png
。filePath
为本地目录,这里我填写绝对文件路径pages/index/image/test.png
。success
和fail
为回调函数,当上传成功则执行success
,失败则执行fail
。
当文件上传完成后,我们调用console.log(res.fileID)
方法将文件 ID打印到控制台。fileID
为这个文件的文件ID,这个很重要,我们下载或删除文件都会用到。
我们看控制台第一行,已经打印出来了cloud://test-f97abe.7465-test-f97abe-1258578239/test1.png
这就是我们的文件ID。打开云开发控制台,已经能看到上传成功的文件了。
关于上传文件具体请求参数和回调成功参数可见下表。
请求参数
字段 | 说明 | 必填 |
---|---|---|
cloudPath | 云存储路径 | 是 |
filePath | 要上传文件资源的路径 | 是 |
header | HTTP 请求 Header, header 中不能设置 Referer | 是 |
success | 成功回调 | |
fail | 失败回调 | |
complete | 结束回调 |
success 返回参数
字段 | 说明 | 数据类型 |
---|---|---|
fileID | 文件 ID | String |
statusCode | 服务器返回的 HTTP 状态码 | Number |
上传文件后,我们就可以对文件进行其他操作,比如说下载文件,官方提供了wx.cloud.downloadFile
API去下载文件,我们先看看怎么使用。
1 | Page({ |
使用wx.cloud.downloadFile
去下载我们的文件,代码中,我们指定了需要下载文件的fileID
,这里的fileID
是我们第一步上传后得到的ID,我这里填写的是cloud://test-f97abe.7465-test-f97abe/test1.png
,每个人的文件不同。之后我们调用回调函数success
和fail
,当文件下载成功后返回文件的临时目录地址tempFilePath
。
运行成功后,文件已经正常被下载。请求及返回字段见下表。
请求参数
字段 | 说明 | 数据类型 |
---|---|---|
fileID | 云文件 ID | String |
success | 成功回调 | |
fail | 失败回调 | |
complete | 结束回调 |
success 返回参数
字段 | 说明 | 数据类型 |
---|---|---|
tempFilePath | 临时文件路径 | String |
statusCode | 服务器返回的 HTTP 状态码 | Number |
在开发的时候,我们经常需要去获取用户上传之后文件的URL,来做其他应用,比如AI图像识别,音频识别等。那么,如何获取上传之后文件的URL地址呢?微信官方提供了wx.cloud.getTempFileURL
API来通过文件的fileID
去获取真实的地址。如何操作呢?看看代码。
1 | Page({ |
代码中,我们调用wx.cloud.getTempFileURL
去获取相关文件的URL,细心的同学发现了,以前的fileID
去哪里了?原来fileID
变为了fileList
,根据官方文档fileList
可以是一个数组,代码中我只写了一个文件的ID,我们可以写多个如:
1 | fileList: [ |
代码运行后,我们看到已经返回了正常的fileID
和tempFileURL
,由于test2.png
文件我们并没有上传,所以第二行返回值报错。
需要注意的是,目前取回的URL地址是有时间限制的,默认一天且最大不超过一天。一次最多取 50 个,也就是说我们的fileList
最长不能超过50个文件。具体的请求及返回字段见下表。
请求参数
字段 | 说明 | 数据类型 |
---|---|---|
fileList | 要换取临时链接的云文件 ID 列表 | String[] |
success | 成功回调 | |
fail | 失败回调 | |
complete | 结束回调 |
fileList 数组
字段 | 说明 | 数据类型 |
---|---|---|
fileID | 云文件 ID | String |
tempFileURL | 临时文件路径 | String |
status | 状态码,0 为成功 | Number |
errMsg | 成功为 ok,失败为失败原因 | String |
我们甚至可以先上传文件后直接去获取其URL,代码如下
1 | Page({ |
wx.cloud.deleteFile
是删除云存储API,用法和获取文件URL地址API十分相似,我们先看看代码。
1 | Page({ |
同样,也是使用fileList
列表去删除相关的文件,如下图所示。
再看看云开发的控制台,我们的文件已经被删除干净了。
有了这四个文件操作API,我们就可以写一个上传图片并获取其URL地址的小应用了。首先,撰写后端,打开index.js
文件。
1 | Page({ |
然后带index.wxml
文件,写下简单的前端界面。
1 | <button bindtap="UploadImage">上传图片</button> |
这里的代码中,我们通过图片上传APIUploadImage
去等待用户上传图片,然后通过wx.cloud.uploadFile
去上传这个图片,上传成功后调用wx.cloud.getTempFileURL
API去获取当前图片的临时URL,最后一步展示给前端用户。
同样的,云存储API在我们的云函数也可以直接调用,云开发同样提供了四种操作API,名称与在客户端调用时接近。
首先,我们打开云开发的index.js
文件,编写云函数(注意!是云开发的函数,这里是server
目录!)打开/server/UpdateFile/index.js
文件。
然后撰写下面的代码。
云函数端的index.js文件
1 | // 云函数入口文件 |
在上传前,我们需要安装wx-server-sdk
相关依赖,具体安装教程不在赘述,详见如何进行小程序云函数开发这篇文章。
安装完成依赖后,需要准备我们需要上传的文件,这里我还是以demo.png
为例,上传该文件。首先,在云函数上面右键,然后使用硬盘打开,将图片拖放至云函数的根目录。
这里的代码意思很简单,我们首先引入wx-server-sdk
、fs
、path
三个包文件,然后通过fs.createReadStream
方法去读取demo.png
文件,之后通过cloud.uploadFile
函数去上传文件,并返回相关接口内容。
然后再次在云函数上点击右键,选择上传并部署:所有文件
之后就是耐心等待。上传完成后,我们需要调用云函数,这里需要大家打开客户端的index.js
和index.wxml
文件,写下下面的代码。
客户端的index.js文件
1 | Page({ |
客户端的index.wxml文件
1 | <button bindtap="UploadImage">云函数上传文件</button> |
这里的代码意思是我们在前端展示一个按钮,当点击这个按钮后,执行UploadImage()
函数,该函数调用云开发APIwx.cloud.callFunction
,然后执行云函数UpdateFile
上传云函数目录下的demo.png
文件。之后由云函数返回成功的数据及文件的fileID
,在前端展示,效果如图。
我们看到控制台输出了上传文件的状态,同时前端也返回了文件的ID。打开控制台看看,果然,文件已经上传成功了~
当然,我们也可以下载该文件,修改云函数端的index.js代码,如下所示。
1 | // 云函数入口文件 |
这里我们调用cloud.downloadFile
函数,并下载指定的fileID
文件。然后将文件内容进行编码,转换为utf8
的字符串,返回给客户端。客户端接收代码如下。
index.js
1 | Page({ |
index.wxml
1 | <button bindtap="UploadImage">云函数下载文件</button> |
这里我们将返回的utf8
字符串打印到控制台,如图。
获取文件的URL地址与下载文件大同小异,我们只需要在服务端返回URL地址就行,云函数端代码如下。
1 | // 云函数入口文件 |
微信客户端逻辑我们可不做修改,点击按钮后,我们就可以在控制台看到相关的输出了。
同上面几个函数一样,删除文件也非常简单,修改代码如下就可以执行。
1 | // 云函数入口文件 |
微信客户端逻辑我们可不做修改,点击按钮后,我们就可以在控制台看到相关的输出了。
喜欢的小伙伴请持续关注本专栏。这篇教程我们介绍了小程序·云开发的文件处理的使用,学会了吗?利用小程序云开发实现快速上线和迭代。欢迎免费使用!
]]>小程序·云开发是微信与腾讯云联合开发的原生 serverless 云服务,具备简化运维、高效鉴权等优势,让你零门槛快速上线小程序。
今天这篇文章中,我们将从0~1介绍小程序云开发的基本使用过程。同时,分享一个demo来体验云开发的优势。在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
首先,我们新建一个云开发的项目,注意AppID
是你自己在小程序AppID,同时不要勾选建立云开发模版。
接下来,我们新建两个目录,一个目录(client)存放小程序的客户端,一个目录(server)存放小程序云开发的服务端,如图。
接下来,打开配置文件project.config.json
,我们需要新增两行文件。
1 | "cloudfunctionRoot": "server/", |
cloudfunctionRoot
参数填写你新建的云开发服务器的文件目录,miniprogramRoot
填写你小程序客户端的目录,如图。
当你的server
文件夹图标变成了☁的样式,证明我们云开发环境就搭建完成了。
我们先不写客户端,先谈谈云开发,云开发的优势是省去了服务器,在云端运行的代码,微信私有天然鉴权,开发者只需编写自身业务逻辑代码。小程序的客户端也提供了一些接口,可快速调用云函数,就如同在本地调用一样方便。
创建了第一个云开发小程序后,在使用云开发能力之前需要先开通云开发。在开发者工具工具栏左侧,点击 “云开发” 按钮即可开通云开发。云开发开通后自动获得一套云开发环境,各个环境相互隔离,每个环境都包含独立的数据库实例、存储空间、云函数配置等资源。每个环境都有唯一的环境 ID 标识,初始创建的环境自动成为默认环境。
我这边已经开通了小程序云开发,该页面是小程序云开发的控制台,通过该控制台,我们能查看小程序云开发的基本数据并进行管理。开通后,我们就可以新建云函数了,如图。
win新建一个名为add的云函数,这个名称很重要,后面在客户端调用的时候我们会用到。
接下来,就可以编写云函数相关的代码了,我们打开server
端add函数下的index.js
文件夹。
然后粘贴下面的代码。
1 | // 云函数入口文件 |
这里代码很简单,首先,我们引入wx-server-sdk
云开发的node包文件,然后使用init()
方法初始化云函数。之后,我们创建一个云函数入口exports.main
,之后通过event
方法去读取a,b
两个文件,然后将其相加,最后返回改数据。
这里的代码意思是获取a,b
两个数据,然后相加在返回给客户端。我们只需记住云开发最基本的函数格式就行,如下所示。
1 | const cloud = require('wx-server-sdk') |
云函数服务端运行依赖wx-server-sdk
包,所以运行前,我们一定要安装相关运行依赖文件才行。因为我们云开发服务端是NodeJS运行环境,安装wx-server-sdk
包,首先要在本地搭建相关运行环境。
首先,我们打开NodeJS官网,下载NodeJS安装包。
下载完成后双击打开,并一路下一步安装即可。
安装完成后,打开命令提示符,试试node
命令和npm
命令是否正常。
看到如图所示的内容,证明你的node
和npm
都已经安装成功了,接下来我们就可以安装相关依赖文件了。
在你新建的云函数上面单击右键,选择在终端中打开,如图。
然后执行下面的命令安装所需依赖文件。
1 | npm install wx-server-sdk --save |
如图所示,看到类似下图的内容,就证明依赖环境下载并安装完成了。
接下来,我们进行测试,看看我们的服务端代码是否能正常运行。
还是打开上一步的终端,然后输入下面的代码。
1 | node index.js |
如果什么都没有输出,证明没有错误,可以正常运行。接下来,我们将整个项目上传到云函数中。
如图,我们在创建的云函数中右键,然后选择上传并部署:所有文件
,等待系统上传后,我们云函数就部署完成了。
参考如何入门小程序开发这篇文章的入门教程,我们在client
目录下新建一个名为app.json
的文件,并在文件中写下下面的代码。
1 | { |
保存后,系统会自动生成pages
文件夹,并生成index
文件夹及其他相关文件,如图。
接下来,我们看看客户端如何调用云函数。小程序官方文档提供了云函数调用APIwx.cloud.callFunction()
,废话不多说,我们先撰写最简单的一行代码演示下,打开客户端目录下的index.js
文件,撰写下面的代码。
1 | Page({ |
保存后,我们看到控制台已经输出了数字3
。
这里的代码意思是调用名为add
的云函数,然后将数据a
、b
数据传至云函数,之后如果云函数执行成功后,返回云函数所得到的数据。值得注意的是,代码运行前需要初始化云函数wx.cloud.init
,并配置相关参数,具体详见官方文档,代码很简单,但是代码中name
、data
等参数到底是什么意思呢?我们来看看官方的文档中参数介绍。
参数 | 类型 | 必填 | 说明 |
---|---|---|---|
name | String | 是 | 云函数名 |
data | Object | 否 | 传递给云函数的参数 |
config | Object | 否 | 局部覆写 wx.cloud.init 中定义的全局配置 |
success | Function | 否 | 返回云函数调用的返回结果 |
fail | Function | 否 | 接口调用失败的回调函数 |
complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
原来name
后面是填写你云函数的相关名称,我们这里是add
。data
是传递给云函数的参数,我们这里填写a
,b
两个参数,参数a=1
,b=2
。最后看到如果云函数执行成功后,返回相关参数。
我们优化下代码,将返回的参数显示在前端。
index.wxml
1 | <text>云函数返回数据{{sum_num}}</text> |
index.js
1 | Page({ |
如图,我们已经将后端的数据传送到前端展示。
喜欢的小伙伴请持续关注本专栏。这篇教程我们介绍了小程序·云开发的基本使用,学会了吗?利用小程序云开发实现快速上线和迭代。欢迎免费使用!
]]>appid
和session_key
以便确认用户的身份。但是,仅仅通过appid
和session_key
不能去获取用户的信息。那么,这篇文章中,我们将介绍如何在小程序中获取用户的昵称、头像、性别、城市等信息。在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
在小程序1.4.0版本开始,小程序就已经支持了在前端展示用户信息的能力,这个能力我们称之为open - data
。而且,open - data
在小程序中是以组件形式存在的,不需要用户授权,我们就可以获取到用户的群名称、用户昵称、用户头像、用户性别、用户所在城市、用户所在省份、用户所在国家、用户的语言,但是值得注意的是,这些数据只能用户自己看到,其他人是看不到的,所以不需要用户授权。那么open - data
如何使用呢?我们向下看。首先,打开你的index.wxml
文件,我们向其中写入如下代码。
1 | <open-data type="userAvatarUrl"></open-data> |
不用做任何设置,我们就可以直接获取到该用户的头像和性别信息,我们只需要将想要获取展示的内容写在type
参数内即可,那么type有效值有哪些呢?请看下表。
type 有效值 | 说明 |
---|---|
groupName | 拉取群名称 |
userNickName | 用户昵称 |
userAvatarUrl | 用户头像 |
userGender | 用户性别 |
userCity | 用户所在城市 |
userProvince | 用户所在省份 |
userCountry | 用户所在国家 |
userLanguage | 用户的语言 |
当然,我们代码中还有一个lang
参数,顾名思义,这个参数是语言,是负责咱们展示数据的语言,微信官方默认的展示语言是英语。如果想修改其他语言,就需要修改其的有效值了。官方给定的有效值有三个,分别是:en
、zh_CN
、zh_TW
,分别对应英文、中文简体和中文繁体。而且,lang
参数必须当type
类型为user
开头时才生效,否则不生效,什么意思呢?我们看看下面的代码。
1 | <open-data type="userCity"></open-data> <!-- 不指定lang参数,默认为`en`,显示英语 --> |
我们看到,我们指向同样的type
参数类型,但是最终显示出来的语言是不同的,第一行代码不指定lang参数,默认为en
,显示英语。第二行代码指定lang参数为en
,显示英语。第三行代码,指定lang参数为zh_CN
,显示中文简体。第四行代码,指定lang参数为zh_TW
,显示中文繁体。第五行代码,type类型不以user
开头,lang参数不生效。
细心的小伙伴还会看到open - id
官方文档中还介绍了一个名为open - gid
的参数,该参数为群的名称,我们可以通过wx.getShareInfo
API去获得,但是这里涉及加密解密等功能,本文暂不涉及。后续介绍敏感数据加密解密的时候我们将做介绍。我们整合type
参数和lang
参数,优化下代码。
1 | <view style='height:100px;width:100px;'> |
我们就可以展示用户的相关信息了。那么,有点问题,这里我只是让用户看到了自己的头像和其他数据,开发者能不能获取到相关数据呢?答案肯定是可以的,但是这里必须需要用户同意我们才能获取到相关数据。微信提供了wx.getUserInfo
和bindgetuserinfo
两种方式让我们获取用户数据,但是官方为了优化接口,已经抛弃了wx.getUserInfo
接口,本文均介绍这两种接口,推荐开发者优先使用bindgetuserinfo
接口。
wx.getUserInfo
接口已经不推荐使用,官方也有相关说明。本文将仅仅对该接口做简单介绍。首先,修改index.wxml
文件如下。
1 | <button bindtap="get_user">授权登录</button> |
这里我们在前端展示一个按钮,该按钮点击下后执行index.js
中的get_user()
函数。
index.js
中代码如下。
1 | Page({ |
这里的代码信息为将获取到的用户信息,通过console.log
方法打印到控制台,如图。
这里只是最简单的获取用户信息,我们可以通过后端代码将其发至服务器或者展示在地方。如图所示,官方已经抛弃相关接口,所以开发者们请用下面的接口来进行用户信息的获取。
bindgetuserinfo
接口是微信官方推荐的接口,我们可以使用该接口来获取用户的数据。调用方式和wx.getUserInfo
相差不大。首先,我们修改index.wxml
文件。
1 | <button open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">授权登录</button> |
接下来,打开index.js
文件,修改代码如下。
1 | Page({ |
代码工作原理同wx.getUserInfo
,通过按钮去执行index.js
下面相关的函数,不过值得注意的是,open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo"
这两个参数是小程序button
组件特有的特性。详见小程序官方文档,当open-type
参数为getUserInfo
时bindgetuserinfo
就可以回调相关函数,并返回相关数据,这里我们通过console.log
将数据打印在控制台出来。
当然,为了优化用户体验,我们应该先提前判断下用户是否授权了相关权限,如果授权了,则不展示相关按钮。
index.wxml
1 | <button |
index.js
1 | Page({ |
当用户已经授权过的时候,我们就不在展示相关授权按钮,而展示已授权的信息。
这篇文章中,我们分享了如何使用微信相关的开放能力,在前端展示数据。也分享了微信获取用户数据的两个接口,你学会了吗?
喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>首先分析下需要准备的内容,每天发邮件内的表格如图。
表内的标题是可以点击的,当点击后需要转跳到相关页面。那么就需要标题
和链接
这两个参数。我们还需要是否回答
这个参数,以及当前问题的标签
,为了方便判断当前问题是什么时候提问的,还需要时间
这个参数。总计5个参数,接下来,看看如果用爬虫的话,我们能不能在社区抓到这几个数据?
分析下问答社区,我们看到,图中的几个参数基本上都能在首页获取到,就是这个时间藏的比较深,在前端页面并没有返回给用户,需要点击问题才能看到提问时间。还有点麻烦,需要模拟成浏览器,再点击地址,最后用正则或者其他方式获取数据。不仅麻烦效率还低啊,然后继续看网页代码。
突然发现问答社区的内容都是通过API接口去获取的,通过POST去请求某个地址,然后在本地解析这些数据,最重要的是,这些数据是json数据。那么我也可以通过这些数据去做统计呀,研究下json数据。
我们看到数据中有标题数据title
,标签tags
,回答数answerCount
,没有时间和链接啊,等下研究下,有UTC时间戳writeTime
和updateTime
。通过这两个数可以转换成当前时间,链接呢?分析下问答社区的地址,都是https://cloud.tencent.com/developer/ask/
加一段数字。那么这个数字就是问题ID,在json数据中显示为id
。有了这些数据,我可以向腾讯云的接口去请求这些数据,然后等其返回json数组,然后我再本地解析不就OK了嘛~看起来蛮简单的。
通过Chrome浏览器,我们可以轻轻松松的查看到请求的参数,如图。
请求数据也是json,简单分析下就知道,pageNumber
是请求页,pageSize
是请求数,queryType
是请求类型。打开API测试软件postman,测试下接口能不能用。
运气不错,直接POST参数过去就能返回相关值,看来社区没有做限制,尝试修改pageSize
和pageNumber
参数,发现pageSize
最大值为50。本来还想着一次请求几百条数据,然后做筛选呢,没办法了,只能动态修改pageNumber
参数去做处理了。
写代码的过程真的是辛酸史啊……人呐,就是欠,本来可以用PHP以及Python轻松搞定的事情,非要用NodeJS。然后遇到了回调地狱……当然这是后话,先写最基础的代码。
因为要做request请求,PHP及Python都支持的比较好,但是想到要导出excel文件,使用NodeJS的NPM包,想必更简单,于是决定用NodeJS去写。
首先就是发起request请求了,通过npm install request
安装完相关依赖。打开vscode,写下下面的代码。
1 | var request = require("request"); |
没有难度嘛(天真),请求数据顺利打印出来,接下来就是处理了。因为返回的body
数据是json格式,可以直接将其解析出来。
1 | request(options, function (error, response, body) { |
这样就能解析其是否成功,但是为什么console.log(body.data.list.title);
就不能显示呢?因为以前没用过json数据处理,这里的json数组是一个多维数组,更懵逼了,搜了几个小时资料,发现console.log(body.data.list[0].title)
能显示第一条问答的标题,console.log(body.data.list[1].title)
能显示第二条数据,那么我可以通过枚举法将内容解析出来。用for循环。
1 | for(i=0;i<50;i++){ |
这样就能循环输出标题了,同理,输出时间,id,回答数。
1 | for(i=0;i<50;i++){ |
将ID拼接为链接,然后将UTC时间转换为正常人能看懂的时间
1 | data_url = "https://cloud.tencent.com/developer/ask/" + body.data.list[i].id |
接下来发现标签内也是数组,那么依然用for循环。但是提前并不知道标签数,所以需要知道标签的json长度,我们可以使用length方法。
1 | var data_tags = new Array() |
难度并不大,然后使用默认的fs模块将其写成csv文件。
1 | var fs_integral = data_url + ',' + dates + ',' + body.data.list[i].title + ',' + body.data.list[i].writeTime + ',' +data_tags; |
完整代码如下
1 | var request = require("request"); |
(注:因为文章写的比较晚,上面的代码是重写的,没有测试,大家大概能看懂意思就行)
本来想着写完了用了两天发现几个问题:
首先是导出excel问题,这个简单,安装node-xlsx
依赖即可。接下来是输出前50问题,再加一个for循环应该能解决,比较简单吧(天真)。第三个问题,难度也不大,将输出内容通过文本形式保存,然后使用excel的函数HYPERLINK
将其连接起来。第四个无解,除非重写。第五个,我可以通过当前UTC时间和发布的UTC时间来判断问题发表是几秒前发布的的,如果这个秒数小于24小时,就将这条问题输出到excel。这样就解决了按照天数输出问题,我可以直接输出24小时内的问题,更新下代码。
1 | var request = require("request"); |
这个只能解决输出当天的问题,当天提问数大于50,这个工具就失效了,功能还是明显的鸡肋。我想到可以使用for循环去改变pageNumber的数值,然后将返回的data
值统一存起来,等请求完了处理。理想很丰满,现实很骨感……改完代码发现每次输出的都是当前pageNumber
页面的问题数,以前的数据全没了。那么我可以将data存在数组中啊,在改下代码。哈?数组为空?????为啥,原来request
请求返回是由回调函数返回的,我不能在回调函数外去调去回调函数的数据。之后我就陷入了两天的回调函数处理……
google和百度都翻遍了……根本没有找到NodeJS如何将回调函数中的数据返回在外面,然后通过其他函数去调用。突然,我看到了Promise
方法和async/await
方法,这也是我写本篇文章的原因,分享一下这两个方法是使用。原来,在NodeJS中,回调函数都是通过异步方法去写的,想去外面调用异步函数的内容,真是比登天还难。有了Promise
方法和async/await
顺顺利利解决了我无法在外部调用回调函数内数据的问题,修改request请求代码如下。
1 | var request = require('request'); |
现在,我可以通过调用synchronous_post函数来实现同步调用异步,并将回调函数的数据赋予到其他变量中,依然按照以前的思路,重构下代码。
1 | var request = require('request'); |
重写一遍神清气爽~演示效果如下(图片较大,耐心等待)。
虽然项目很简单,但是学到了一些新的知识,学会了json的数据处理,学会了node异步变同步,这应该是我目前写过逻辑最复杂的脚本了,又啃了几天回调地狱的硬骨头。蛮开心的,将项目分享到了GayHub(https://github.com/Techeek/ask_community_index_status),欢迎对request,异步,json数据处理有疑问的同学前去讨论哦~
]]>小程序端也支持直接调用罗盘信息,这篇教程,我们将教大家小程序端罗盘的基础使用,并结合现实应用,开发一款指北针demo。
在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
小程序官方提供了wx.onCompassChange()
API去调用系统的罗盘,并返回与正北方向的夹角度数。返回的夹角数频率为5次每秒,返回会返回两个值,一个是direction
,与正北方向的夹角度数。另一个是accuracy
返回的值为当前的精度,可以参考官方文档。这里我们主要看direction
参数,该参数返回的为0°~360°,这里的值为与正北方向的夹角度数。我们可以通过下面的代码来调用api,并将夹角度数返回打印到控制台。
1 | Page({ |
然后点击开发界面的真机调试
按钮,并使用手机微信扫描二维码。扫描完成后,你电脑会弹出类似下面的界面,这里返回的数字就是我们目前与正北方向的夹角。
我们看到,调用API很简单,能不能将这里的数据实时反馈到前端呢?打开index.wxml
文件,添加下面的代码。
1 | <view>{{compass}}°</view> |
然后修改index.js
文件
1 | Page({ |
效果如图
我们也可以将accuracy
参数加进来
1 | Page({ |
除了罗盘基础事件调用,小程序还提供了开始和停止罗盘监听的两个API,调用起来比较简单,参考下面的代码。
index.js
1 | Page({ |
index.wxml
1 | <view>{{compass}}°</view> |
利用上面的这些API,结合小程序wx.createAnimation()
动画API,就可以实现指北针的实现。关于动画API的调用本文暂不涉及,具体使用大家相见官方文档。
我们修改上一步中的代码,添加指北针的图片,然后通过wx.createAnimation()
API去旋转这个图片。
index.js
1 | Page({ |
index.wxml
1 | <image animation="{{animation}}" mode="aspectFit" src='https://techeek-cn-1251732175.cos.ap-chengdu.myqcloud.com/wx-compass/img.png'></image> |
这段代码中,我们首先在index.wxml
文件中指定了指北针的图片,然后通过animation
方法去等待index.js
传至前端的动画事件,并等待compass
变量的数据。
index.js
文件中,我们将wx.onCompassChange
的返回值res.direction
通过.toFixed(0)
方法做了去小数处理,然后使用360
减去与正北方向的夹角,得到图片需要旋转的度数。然后通过this.setData()
将得到的数据返回给前端。效果如图。
不论我们怎么旋转手机当前指向都为正北方向。有了与正北方向的夹角,我们可以通过判断这个数值来判断当前的方向,可以使用if或者switch方法去判断,这里我用switch,代码如下。
index.js
1 | Page({ |
index.wxml
1 | <view style='display:flex;justify-content:center;align-items:center;'> |
稍微优化下前端样式,我们就可以得到一个比较好看的指北针了!
怎么样,简单吗?赶快去体验下吧,后续我将会对其他组件做详细的介绍。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>还好,小程序提供了wx.onAccelerometerChange
接口来帮我们解决这些问题,本教程将为大家介绍wx.onAccelerometerChange
在小程序中的基本使用,并通过若干demo做简单的实验。
在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
调用API很简单,在开始使用之前,我们直接上代码吧。打开你的index.js
文件,然后写下下面的代码。
1 | Page({ |
然后点击真机调试
按钮,扫描二维码后晃动手机,你可能会在电脑端看到类似下面的内容。
这里的数值,就是我们调用小程序的wx.onAccelerometerChange
接口,然后通过console.log
在控制台打印出来当前的手机的加速度计状态。但是这里数据太乱了,我们根本无法得知那个是x,y,z三个轴上的加速力。优化下代码,我们将数据传输到前端看看。打开index.wxml
文件,写下下面的代码。
1 | <view>加速度计</view> |
然后打开index.js
文件,将代码修改如下。
1 | Page({ |
现在重新编译下,你就可以在小程序端查看到当前手机的加速度状态了。
通过上面的数据,经过推算,我们可以得到这么一张图,通过这些数据,我们就可以得到当前手机的状态了。
除了监听加速度数据事件wx.onAccelerometerChange
API,微信官方还提供了wx.startAccelerometer
和wx.stopAccelerometer
来开始或停止当前小程序的加速度计的监控。我们可以通过这两个API,来实现基本的加速度计的控制。修改index.js
代码如下。
1 | Page({ |
然后修改index.wxml
文件代码如下
1 | <view>加速度计</view> |
这里我们调用了wx.startAccelerometer()
和wx.stopAccelerometer()
两个API,我们先看看wx.startAccelerometer()
的官方文档。
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
interval | string | 否 | 监听加速度数据回调函数的执行频率,合法值为game \ui \normal ,game适用于游戏回调频率,20ms/次。ui适用于UI回调频率,60ms/次。normal为普通回调频率,200ms/次。 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
这里我们仅仅设置了了当前的回调频率,设置为ui
,也就是60ms更新一次。大家可以按照自己的需求更改。
然后我们在前端通过button
按钮去调用startAccelerometer
函数和stopAccelerometer
去开启关闭加速度计。
那么,有了这些数据,可以做到那些高阶玩法呢?我们可以使用小程序来做一个3D相册。
为了让小程序内的图片动起来,我们需要调用小程序的动画接口wx.createAnimation
。然后使用该函数的.rotate3d
等方法让小程序内的图片旋转起来。首先,插入一张图片,然后设置动画参数,打开index.wxml
,写下下面的代码。
1 | <image animation="{{animation}}" src='https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/230px-Cat03.jpg'></image> |
我们需要在后端调用动画,所以还需要编写后端代码,打开index.js
文件,写下下面的代码。
1 | var x = 0 |
现在,左右晃动手机,你会发现图中的猫咪沿着你晃动手机的方向旋转。
讲讲代码的原理吧,index.wxml
文件中,我们定义了猫咪的图片,并设置了animation
属性,该属性的参数需要通过后端返回的数据获取。
index.js
文件中,我们将调用onAccelerometerChange
的接口,然后获取加速度计返回值X,因为返回值为小数,为了将图片旋转度数变大,将这个值乘以180。然后通过animation
接口去设置旋转动画。但是这里仅仅是2D画面,怎么设置3D的相册呢?我们引入另外的变量Y,Z,修改index.js
文件。
1 | var x = 0 |
这里我们引入了x,y,z三个变量,从而实现使小程序中的图片变为3D的效果,如图。
我们将手机的变量返回给了动画参数,从而实现图片随手机状态变化而变化。我们甚至可以实现旋转手机的时候图片不旋转。
1 | var xy = 0 |
但是这样的方式不够完美,如果要实现较为流畅的图片旋转,我们就需要引入陀螺仪使用的角速度概念,关于陀螺仪的介绍,我们将放在后面的文章做介绍。
现在学会加速度计的使用了吗?后续我将会对其他组件做详细的介绍。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>wx.request()
、wx.closeSocket()
、wx.downloadFile()
、wx.uploadFile()
等与服务器通信的接口,以前的文章中,我们已经介绍了wx.closeSocket()
、wx.downloadFile()
、wx.uploadFile()
这三个接口的使用,这篇文章中,我们将介绍HTTP通信接口wx.request()
。在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
因为要与服务端进行通信,在小程序端教程开始之前,我们需要在服务器搭建相关环境。服务端的环境有很多选择NodeJS、PHP、Python等大部分主流语言都可以部署HTTP服务,今天我们将教大家使用PHP语言进行环境部署,其他语言请同学们自行部署。
我这里以Ubuntu Server 16.04 LTS为例,我们需要安装php
运行环境及Nginx
Web服务,同时也需要申请免费的SSL证书和域名,关于证书和域名的申请注册请参考如何快速搭建微信小程序这篇文章。注册完域名及证书申请,我们就可以开始部署服务器了!首先,登录服务器,执行下面的命令。
1 | sudo apt update |
安装完成后,使用浏览器访问你的服务器IP地址,如果看到下面的内容,则证明Web服务已经启动。
因为小程序获取远程数据,必须为HTTPS环境,所以目前搭建的环境,在小程序无法使用,接下来,我们将使用SSL证书加密小程序访问你服务器之间的流量。这里就需要刚才注册的域名及证书了。首先,将下载的证书,上传到你的服务器,并记录下这个位置。然后,我们将配置Nginx服务,以让其支持HTTPS流量。
我们找到/etc/nginx/conf.d
文件夹,新建配置文件,为了方便后续修改,我将这里的配置文件修改为weixin.techeek.cn.conf
大家可以根据自己的需求修改。
1 | cd /etc/nginx/conf.d |
在nano
编辑器中,我们写下下面的代码
1 | server { |
一定注意,将文中server_name
中的weixin.techeek.cn
更换成你的域名。将ssl_certificate
和ssl_certificate_key
中证书的路径更换成你刚上传证书的路径。然后,执行下面的命令重启nginx服务。
1 | sudo service nginx restart |
之后,打开你电脑的浏览器,然后通过域名访问,注意,这里一定要在域名前加https://
,比如我访问的域名https://weixin.techeek.cn
。
如果域名前有小锁标志,则证明你已经配置成功,可以开始下一步了。
基本环境配置好之后,可以登录 微信公众平台 配置通信域名了。我们点击微信公众号右侧的设置,然后找到服务器域名配置。
进入微信公众平台管理后台设置服务器配置,如上图所示,需要将你的服务器域名配置为你自己的域名。我这里的域名是weixin.techeek.cn
。
当我们配置完上面的所有步骤后,就可以开始为本教程服务端的代码编写了。因为我们需要与小程序进行通信,所以需要在服务端搭建一个request接口,以方便小程序访问服务器时,返回相关的数据,为了方便小程序解析,这里我们返回的是json
格式数据。
首先打开你的网站所在的根目录,然后新建一个index.php
文件,写下下面的代码。
1 |
|
这里代码意思很简单,首先创建一个数组,然后通过json_encode()
方法将这些变量变成json数据,最后通过echo
方法打印出来这串json
字符串。
打开浏览器,访问你的域名,注意加https://
和?get=get
,我这里的域名是https://weixin.techeek.cn?get=get
如果看到下面的输出,证明服务器搭建完毕。
当然除了上面的代码我们也可以使用下面的代码,只不过为了方便演示当前是什么请求,我使用了上面的代码。
1 |
|
小程序端只能发起HTTPS请求,且只能使用上面绑定的域名,所以在开发小程序前,一定要配置好通讯域名。
小程序使用wx.request()
函数来发起HTTPS请求,目前支持OPTIONS
、GET
、HEAD
、POST
、PUT
、DELETE、TRACE
、CONNECT
这几种请求方式。教程中我们只讲解GET
和POST
这两种方式的请求,其他请求大同小异,请大家自行摸索。
在发起请求之前,我们先看看官方文档。
属性 | 类型 | 默认值 | 是否必填 | 说明 |
---|---|---|---|---|
url | string | 是 | 开发者服务器接口地址 | |
data | string/object/ArrayBuffer | 否 | 请求的参数 | |
header | Object | 否 | 设置请求的 header,header 中不能设置 Referer。 content-type 默认为 application/json | |
method | string | GET | 否 | HTTP 请求方法 |
dataType | string | json | 否 | 返回的数据格式 |
responseType | string | text | 否 | 响应的数据类型 |
success | function | 否 | 接口调用成功的回调函数 | |
fail | function | 否 | 接口调用失败的回调函数 | |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
这里只需要url
参数,那请求比较简单,打开index.js
,然后写下下面的代码。
1 | Page({ |
我们将wx.request()
API写在官方要求的生命周期函数onReady
中,这样当编译完微信,就能看到连接效果。
我们看到系统自动发送了一个GET方法的HTTP请求,我们目前没有传递任何参数,也没有看到任何返回值,现在,参考官方文档,看看如何传递数据进去。
1 | Page({ |
我们在服务器端使用条件语句判断,当通过GET方法传入的值是get
时,系统才会返回我们在服务端设置的json数据,使用上面的代码,编译完成后,看看会返回什么样的数值。点击控制台的Network
,我们可以看到通过GET方法传出去的数组已经获取到了返回值。
现在,优化下代码,将返回的数值在前端显示,代码如下。
index.wxml
1 | <view><text style='color:red'>请求方式:{{request}}</text></view> |
index.js
1 | Page({ |
如图,我们传过来的数组文件已经能够正常在首页显示了。
因为已经有了GET的经验,我们可以参照官方文档中请求的表格,增加POST参数。
object.method 的合法值
值 | 说明 |
---|---|
OPTIONS | HTTP 请求 OPTIONS |
GET | HTTP 请求 GET |
HEAD | HTTP 请求 HEAD |
POST | HTTP 请求 POST |
PUT | HTTP 请求 PUT |
DELETE | HTTP 请求 DELETE |
TRACE | HTTP 请求 TRACE |
CONNECT | HTTP 请求 CONNECT |
修改上面的代码如下。
1 | Page({ |
当header
参数为POST
时,我们就可以发起POST请求了。
网络请求方式较多,大家可以参考如何在小程序中实现文件上传下载和如何在小程序中实现 WebSocket 通信实现更多与服务器请求。赶快去自己试试吧~喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>在这种情况下,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。WebSocket只需要与服务器进行一次握手,即可实现实时的数据连接,并且传输协议是全双工的,服务器可以随时主动向客户端发送数据,并且WebSocket协议在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小,能明显降低服务器及客户端开销。
我们的小程序也支持WebSocket通信,如果你想为你的小程序实现聊天室、服务器推送、小程序之间数据交互等功能,那就非常有必要搭建一个WebSocket服务器来进行WebSocket通讯。这篇文章中,我们将简单介绍小程序WebSocket通信使用方法,并通过实例搭建一个WebSocket服务器。实现小程序与服务器之间的通讯。
在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
既然要实现WebSocket通讯,那必须要拥有一台WebSocket服务器,服务端的环境有很多选择NodeJS、PHP、Python等大部分主流语言都可以部署WebSocket服务,今天我们将教大家使用PHP语言进行环境部署,其他语言请同学们自行部署。
我这里以Ubuntu Server 16.04 LTS为例,我们需要安装php
运行环境及Nginx
Web服务,同时也需要申请免费的SSL证书和域名,关于证书和域名的申请注册请参考如何快速搭建微信小程序这篇文章。注册完域名及证书申请,我们就可以开始部署服务器了!首先,登录服务器,执行下面的命令。
1 | sudo apt update |
安装完成后,使用浏览器访问你的服务器IP地址,如果看到下面的内容,则证明Web服务已经启动。
因为小程序获取远程数据,必须为HTTPS或WSS环境,所以目前搭建的环境,在小程序无法使用,接下来,我们将使用SSL证书加密小程序访问你服务器之间的流量。这里就需要刚才注册的域名及证书了。首先,将下载的证书,上传到你的服务器,并记录下这个位置。然后,我们将配置Nginx服务,以让其支持WSS流量。
我们找到/etc/nginx/conf.d
文件夹,新建配置文件,为了方便后续修改,我将这里的配置文件修改为weixin.techeek.cn.conf
大家可以根据自己的需求修改。
1 | cd /etc/nginx/conf.d |
在nano
编辑器中,我们写下下面的代码
1 | server { |
一定注意,将文中server_name
中的weixin.techeek.cn
更换成你的域名。将ssl_certificate
和ssl_certificate_key
中证书的路径更换成你刚上传证书的路径。然后,执行下面的命令重启nginx服务。
1 | sudo service nginx restart |
之后,打开你电脑的浏览器,然后通过域名访问,注意,这里一定要在域名前加https://
,比如我访问的域名https://weixin.techeek.cn/
。
如果域名前有小锁标志,则证明你已经配置成功,可以开始下一步了,这里502报错不用在意,因为我们还没有搭建WebSocket服务,所以服务器会返回502错误。
基本环境配置好之后,可以登录 微信公众平台 配置通信域名了。我们点击微信公众号右侧的设置,然后找到服务器域名配置。
进入微信公众平台管理后台设置服务器配置,如上图所示,需要将你的服务器域名配置为你自己的域名。我这里的域名是weixin.techeek.cn
。
上述步骤准备完成后 ,就可以撰写WebSocket服务端的代码了,我这里使用的是PHP socket即时通讯框架Workerman来进行搭建。有了这个框架,我们就可以非常方便的搭建WebSocket服务。因为本文主要讲解小程序端的WebSocket的使用,关于Workerman的详细使用教程,可以参考Workerman官方手册,本文仅做基础环境安装的介绍。
首先,我们创建一个运行WebSocket
服务的目录,我这里创建名为php-websocket-server
,目录位置可以自定义,我这里就将项目放在ubuntu用户的根目录下。
1 | mkdir /home/ubuntu/php-websocket-server |
接下来,我们使用composer
包管理器安装WebSocket
运行环境。因为某些原因,国内访问composer
可能会报错,所以我们需要使用国内的composer
镜像。然后就可以安装Workerman了。
1 | sudo composer config -g repo.packagist composer https://packagist.phpcomposer.com |
安装完成后,默认情况下会有三个文件,composer.json
、composer.lock
、vendor
这三个文件,如果没有,请重新执行上面的命令。
1 | ├── composer.json |
安装完workerman依赖文件,我们就可以撰写系统所需的代码了。使用nano
编辑器,新建一个可执行的php文件,我这里创建的文件名为webSocket.php
,大家可自行更改。
1 | nano webSocket.php |
代码如下
1 | <?php |
这时,一个最基本的websocket服务就编辑完成了,这里的代码意思是,通过/vendor/autoload.php
引入Workerman的php文件,然后在8080端口创建websocket服务,并设置进程为4个进程。然后执行onMessage
回调函数,该函数接收客户端所发过来的数据$data
,然后使用send方法将数据发回给客户端。
接下来,我们就可以运行服务器了,执行下面的代码即可运行。
1 | sudo php webSocket.php start |
如果看到类似下面的输出,证明我们websocket服务器已经启动,接下来就可以开始配置小程序端的代码了。
小程序连接Websocket服务器是通过wx.connectSocket()
API进行连接的,为了方便连接API,我们先看看官方的文档。
属性 | 类型 | 是否必填 | 说明 |
---|---|---|---|
url | string | 是 | 开发者服务器 wss 接口地址 |
header | Object | 否 | HTTP Header,Header 中不能设置 Referer |
protocols | Array. | 否 | 子协议数组 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
我们看到只有url
是必填项,其他属性可以不填,那么连接服务器就比较简单了,我们打开index.js
文件,写下下面的代码。
1 | Page({ |
有小程序开发经验的小伙伴都知道,这里的onReady
是小程序的生命周期函数,负责在小程序初次渲染完成后执行的函数,这样我们编译完小程序,小程序就自动连接服务器。现在编译一下试试,咦,好像不行啊,怎么没看到小程序有反应。我们打开控制台,点击Network
按钮,如果看到类似下面的内容,就证明你的小程序已经成功链接服务器了。
这里的HTTP状态码是101,101
状态码是websocket特有的状态码,我们已经成功连接搭建的服务器。但是我们能不能直观点看到已经连接服务器呢?当然可以,参考文档使用success
属性,我们在其中加入回调函数。修改代码如下。
1 | Page({ |
我们增加一个回调函数,如果服务器连接成功,向小程序控制台打印出连接服务器成功
。反正打印连接服务器失败
。
当然,我们也可以将成功的内容展示给小程序前端,代码如下,首先修改index.wxml
代码。
1 | <view><text>连接服务器状态:{{status}}</text></view> |
然后打开index.js
文件,修改代码
1 | Page({ |
现在重新编译小程序,你会看到类似这样的界面。
服务器搭建我们说到,我们的服务器的代码内容是将小程序发给服务器的任意字符前加hello
之后返回给小程序,现在,我们已经成功连接服务器了。接下来,我们需要修改代码,以便小程序将数据发给服务器。
官方文档中,使用wx.sendSocketMessage()
API将数据发给服务器,根据官方文档,通过 WebSocket 连接发送数据。需要先 wx.connectSocket
连接服务器,并在 wx.onSocketOpen
回调之后才能发送。所以在调用wx.sendSocketMessage()
前,需要先调用wx.onSocketOpen
监听WebSocket连接是否打开。代码如下。
1 | Page({ |
现在,我们就可以使用wx.sendSocketMessage()
发送数据到服务器了,先看看官方文档,怎么使用。
属性 | 类型 | 是否必填 | 说明 |
---|---|---|---|
data | string/ArrayBuffer | 是 | 需要发送的内容 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
我们只需要传data 内容给API,就能发内容给服务器了,那么修代码内容如下。 |
1 | Page({ |
现在,我们的数据已经可以发给服务器了,可是我们还没有看到服务器返回的数据,这时,我们就该使用另一个API了,监听WebSocket 接受到服务器的消息事件wx.onSocketMessage()
,该API返回服务器发出的消息。但是onReady
函数是页面加载就运行的,这时服务器还没反应过来,数据返回了没收到该怎么处理?我们可以引入另一个生命周期函数onLoad
,这个函数是小程序负责监听页面加载的函数,我们可以将服务器消息事件监听的API写在这里,当接收到数据,由这个函数返回相关内容。所以代码如下。
1 | Page({ |
为了方便观察服务器返回的数据,我们修改下前端,增加服务器消息监听的内容。
1 | <view><text>连接服务器状态:{{status}}</text></view> |
现在,重新编译,就能看到服务器返回Hello 你好
的内容,我们发出的内容为你好
,服务器在内容前加一个Hello
然后返回给小程序。我们可以修改你好
为任意内容,看看服务器能否正常返回相关内容。稍微优化下前端和后端代码,如下。
index.wxml
1 | <button type="primary" bindtap="connect">连接webSocket服务器</button> |
index.js
1 | Page({ |
这样,我们就实现了向服务器发送数据,同时服务器返回数据的全部流程。
有人可能会问,这个HTTP通信方式没有区别啊,还是小程序先请求数据到服务器,然后服务器返回数据啊,我没看到什么不同。虽然表现是这样,但是现在小程序和服务器是长连接状态,服务器可以直接推送内容到小程序,不信?我们试试。打开你的服务器Websocket.php
文件,将代码修改为下面的内容。
1 | <?php |
然后运行服务器。
1 | sudo php webSocket.php start |
这行代码中,我们实现了小程序连接服务器后,服务器每隔10秒主动推送数据你好
给小程序,无需小程序主动请求内容,同时,小程序发出的内容,可以在服务端显示。现在点击你小程序连接webSocket服务器
按钮,看看效果。
然后我们向服务器发点消息试试。服务器也已经收到了小程序发出的数据。
websocket通信在小程序端还是比较简单的,赶快去自己试试吧~后续我还会介绍一篇利用websocket通讯进行聊天室搭建的教程,喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>腾讯云人脸识别服务每月为各个接口提供 1 万次 的免费调用,我们可以利用腾讯云人脸识别服务所提供的API来实现我们一些简单的demo实验。目前腾讯云人脸识别服务所提供人脸检测与分析、五官定位、人脸比对与验证、人脸检索、多脸检索、静态活体检测等功能,为了方便演示,本教程只介绍人脸检测与分析API的使用,更多接口使用请参考腾讯云人脸识别文档。
在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
如果要使用人脸识别API,必须在腾讯云进行实名认证,实名认证后,您可以登录腾讯云 控制台 进行使用。如果没有账号,请参考账号 注册教程。注册完成后,需要创建相关开发密钥,不然无法使用API。
您需要在 访问管理 创建密钥,点击图中的新建密钥,即可创建密钥。
创建完成后,点击SecretKey的显示按钮,显示当前SecretKey,然后将APPID
、SecretId
、SecretKey
记录下了,后面教程中使用。人脸识别服务通过签名来验证请求的合法性,所以接下来的步骤,我们将介绍如何进行签名。
签名步骤官方文档写的非常详细,本文仅作简单介绍。签名方法非常简单,就两个步骤,拼接签名、生成签名。
拼接签名主要需要APPID
、Secret ID
、bucket
、expiredTime
、currentTime
、rand
、fileid
这几个参数,APPID
、Secret ID
、在上一步骤中我们已经介绍。Bucket
是图片资源的组织管理单元,历史遗留字段,可不填。expiredTime
为签名的有效期。currentTime
为当前时间。rand
为随机串,需要自己生成。fileid
资源存储的唯一标识,如果你的签名想使用多次,可不填。
当拼接完成后,需要HMAC-SHA1 算法对拼接签名进行加密,之后在将签名结果放在末尾,在进行base64编码。最终生成签名,是不是签名生成过程看蒙了?没关系,官方提供了相关签名代码,我们直接使用。我们只需要APPID
、Secret ID
、SecretKey
这三个参数即可生成签名。首先,根据如何在小程序中实现文件上传下载文章,搭建好上传文件所需环境,然后在服务器端,网站根目录,新建一个名为signature.php
的文件。
1 | cd /usr/share/nginx/html |
然后写入下面的代码
1 | <?php |
注意,将YOUR APPID_ID
替换为你的APPID
,将YOUR SECRET_ID
替换为你的Secret ID
,将YOUR SECRET_KEY
替换为你的SecretKey
,如图。
保存后,在浏览器访问你配置服务器的地址,比如我的签名地址是https://weixin.techeek.cn/signature.php
,如图。
这里会输出三行数据,第一行为可多次使用的签名,第二行验证与当前操作的文件路径是否一致才能使用的签名,第三行为单次使用签名,为了方便演示,我这里将介绍多次使用的签名使用,复制第一行全部内容,保存下来,后续使用。
到这里,我们所有的签名工作就完成了,建议签名完成后删除该文件,以防止其他人访问。
在如何在小程序中实现文件上传下载文章的教程中,我们已经配置好了上传服务器,没有配置好的同学请参考这篇教程。接下来,需要在服务器端增加人脸识别API。
后续小程序将图片传输到服务器,由服务器向腾讯云的服务器发起HTTP请求,并将返回的请求数据返回给小程序。我们修改index.php
文件为下面的内容。注意,将YOUR SIGNATURE
修改为你在上一步中保存的一长串内容。将YOUR APPID_ID
替换为你的APPID
。将YOUR DOMAIN
替换为你的域名,不要加https://
。
1 | <?php |
修改完成后如图。注意,这里上传完图片路径存储在/upload/
目录下,如果你没有按照我的教程去做,请修改你存储图片的目录。
现在,访问你的配置的小程序域名https://weixin.techeek.cn/
如果看到如图的内容,证明服务器已经搭建,这里报错正常,因为我们没有传输图片到这个接口,所以会报错。
到这一步,我们的服务器搭建步骤就完成了。我解释一下服务端代码的作用吧,首先将图片上传到刚刚创建的weixin.techeek.cn
(注意域名,需要改成你自己的)接口,该接口将上传的文件复制到upload/
目录下,之后,服务器向https://recognition.image.myqcloud.com/face/detect
接口发起HTTP请求,将你的图片的url地址及签名信息发送给腾讯云人脸识别接口,人脸识别接口识别图片后,返回相关数据,然后你的服务器将这些数据原封不动返回给前端,接下来的步骤中,我们将这些数据导入到小程序中处理。
服务器端已经配置完成,接下来,我们需要配置小程序端的代码,首先,我们配置后端代码,打开index.js
文件,修改代码如下。
1 | Page({ |
这里就是如何在小程序中实现文件上传下载文章中上传文件的代码,只不success
这里,我们将返回的内容改为了res.data
,有了这段代码,我们就可以实现将服务器端的数据展示出来。接下来,我们撰写前端,修改index.wxml
代码如下。
1 | <button type="primary" bindtap="wx_face">上传</button> |
这里我们调用wx_face
上传图片到服务器,等待服务器返回数据。点击控制台的Network
按钮,然后点击我们前端界面的上传
按钮,选择一张带人脸的照片,看看会发生什么。
图片上传到服务器,我们看到小程序返回了一个json数组,这里返回的数组是腾讯云人脸识别接口返回的数据,证明人脸已经识别成功,这是请求成功返回的数据,这里的数组到底是什么意思呢?我们看看腾讯云人脸检测与分析API的文档,如下表。
请求头 header
参数名 | 必选 | 值 | 描述 |
---|---|---|---|
host | 是 | recognition.image.myqcloud.com | 腾讯云人脸识别服务器域名 |
content-length | 否 | 包体总长度 | 整个请求包体内容的总长度,单位:字节(Byte) |
content-type | 是 | application/json 或 multipart/form-data | 据不同接口选择: 1. 使用 application/json 格式,参数为 url,其值为图片的 url ; 2. 使用 multipart/form-data 格式,参数为 image,其值为图片的二进制内容。 |
authorization | 是 | 鉴权签名 | 多次有效签名,用于鉴权,生成方式见 鉴权签名 |
请求参数
使用 application/json 格式,参数选择 url ;使用 multipart/form-data 格式,参数选择 image。
参数名 | 必选 | 类型 | 参数说明 |
---|---|---|---|
appid | 是 | String | 接入项目的唯一标识,可在 账号信息 或 云 API 密钥 中查看 |
mode | 否 | Int | 检测模式:0-所有人脸,1-最大的人脸 |
image | 否 | Binary | 图片内容 |
url | 否 | String | 图片的 url、image提供一个即可;如果都提供,只使用url |
返回内容
字段 | 类型 | 说明 |
---|---|---|
data.session_id | String | 相应请求的 session 标识符,可用于结果查询 |
data.image_width | Int | 请求图片的宽度 |
data.image_height | Int | 请求图片的高度 |
data.face | Array(faceItem) | 检测出的人脸信息列表 |
code | Int | 返回状态码 |
message | String | 返回错误消息 |
FaceItem 说明
字段 | 类型 | 说明 |
---|---|---|
face_id | String | 人脸标识 |
x | Int | 人脸框左上角 x |
y | Int | 人脸框左上角 y |
width | Float | 人脸框宽度 |
height | Float | 人脸框高度 |
gender | Int | 性别 [0(female)~100(male)] |
age | Int | 年龄 [0~100] |
expression | Int | 微笑[0(normal) |
glass | Bool | 是否有眼镜 [true,false] |
pitch | Int | 上下偏移[-30,30] |
yaw | Int | 左右偏移[-30,30] |
roll | Int | 平面旋转[-180,180] |
Beauty | Int | 魅力[0~100] |
我们先看看请求头 header和请求参数这里的内容眼熟嘛?这里的内容大部分参数我已经将其写在了我们服务器的请求文件index.php
中,大家只需使用即可。撰写小程序时用不到。
我在再看看返回内容和FaceItem 说明,这里的数据是服务器返回的数据,参考这两个表格,我们才能知道当前返回的数据到底是什么意思。为了方便讲解,我将返回的json数组格式化后放在下方。
服务器返回的json数组
1 | { |
因为源文件较长,我将face_shape
中几个数组隐藏掉了。我们对照表格,看看返回的数组到底是什么意思。face_id
为人脸标识,每张图片返回的标识不同,我们可以不用在意。x
、y
为人脸框的坐标标记,返回的数组中为149
和118
。width
和height
为人脸的宽高,返回的数据为202
和202
。接下来pitch
和yaw
为人脸的偏移量,返回的数据为14
和0
证明这张脸基本在中心位置。之后的数据age
为年龄,人脸识别结果为22
岁。gender
为性别,这里的数值为0
根据表格判断为男性。glass
为false
表明不戴眼镜。mask
为当前是否面部被遮挡。这里返回值为0
证明未被遮挡。hat
这里的数值为0
证明没有带帽子。beauty
为魅力,根据表格,这里的魅力为81
。根据这些信息,我们可以判断,这是一个没有戴眼镜,帽子等遮挡物,一个比较帅的小伙子。
但是这里的数据仅仅是给程序员看的,我们能不能把它转换成正常人能读懂的数据呢?当然可以,修改index.wxml
代码如下。
1 | <button type="primary" bindtap="wx_face">上传</button> |
这段代码中,我们判断其是否带帽子,是否戴眼镜,年龄和颜值是多少。接下来,修改后端代码,打开index.js
文件,代码如下。
1 | Page({ |
这段代码中,我们将返回的的数据通过JSON.parse()
方法转为json数据,然后将返回的数据通过setData
方法赋予相关变量,然后前端显示相关变量,比如age: obj.data.face[0].age
这段代码的意思是将json数组中data数组内的face数组中age数组赋予age
变量。然后在前端显示,如图。
现在上传任意带人脸的图片,就能识别用户的颜值等信息。这里的信息还是较少,并且界面不太好看,我们优化下前端代码。
现在试试能不能正常使用。
已经能够正常使用了!这个小程序的代码我将其分享在了github,感兴趣的小伙伴可以去这里下载。
怎么样,现在会使用小程序调用人脸识别API了吗?我们看到腾讯云的API还是非常准确的,那是因为腾讯云人脸识别立足于社交数据大平台,借助腾讯优图领先的人脸识别技术,可应用在美妆美颜、面部动效合成、安防监控追逃、金融领域身份认证等场景,解决各行业客户的多种多样的人脸特效处理及用户身份确认等需求。目前腾讯云人脸识别服务每月为各个接口提供 1 万次 的免费调用,还等什么赶快去体验下吧!
后续我将会对其他组件做详细的介绍。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>在如何实现小程序登录鉴权这篇文章中,我们实现了小程序的wx.request
请求操作,除了request之外,小程序还有文件下载wx.downloadFile
和文件上传wx.uploadFile
请求接口。那么这两个请求如何使用呢?请看本篇文章。
在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
服务端的环境有很多选择NodeJS、PHP、Python等大部分主流语言都可以部署HTTP服务,今天我们将教大家使用PHP语言进行环境部署,其他语言请同学们自行部署。
我这里以Ubuntu Server 16.04 LTS为例,我们需要安装php
运行环境及Nginx
Web服务,同时也需要申请免费的SSL证书和域名,关于证书和域名的申请注册请参考如何快速搭建微信小程序这篇文章。注册完域名及证书申请,我们就可以开始部署服务器了!首先,登录服务器,执行下面的命令。
1 | sudo apt update |
安装完成后,使用浏览器访问你的服务器IP地址,如果看到下面的内容,则证明Web服务已经启动。
因为小程序获取远程数据,必须为HTTPS环境,所以目前搭建的环境,在小程序无法使用,接下来,我们将使用SSL证书加密小程序访问你服务器之间的流量。这里就需要刚才注册的域名及证书了。首先,将下载的证书,上传到你的服务器,并记录下这个位置。然后,我们将配置Nginx服务,以让其支持HTTPS流量。
我们找到/etc/nginx/conf.d
文件夹,新建配置文件,为了方便后续修改,我将这里的配置文件修改为weixin.techeek.cn.conf
大家可以根据自己的需求修改。
1 | cd /etc/nginx/conf.d |
在nano
编辑器中,我们写下下面的代码
1 | server { |
一定注意,将文中server_name
中的weixin.techeek.cn
更换成你的域名。将ssl_certificate
和ssl_certificate_key
中证书的路径更换成你刚上传证书的路径。然后,执行下面的命令重启nginx服务。
1 | sudo service nginx restart |
之后,打开你电脑的浏览器,然后通过域名访问,注意,这里一定要在域名前加https://
,比如我访问的域名https://weixin.techeek.cn
。
如果域名前有小锁标志,则证明你已经配置成功,可以开始下一步了。
因为小程序要求必须使用自己的服务器进行文件上传下载,所以我们在开始之前必须搭建好服务器,否则无法使用小程序。
为了演示下载功能,你需要将一个文件上传到你的网页服务器的根目录,如果你按照我的教程,则这个目录是/usr/share/nginx/html/
下,如图。
上传完成后,我们访问的部署的域名,即可查看到该文件,我这里访问的域名为https://weixin.techeek.cn/download.jpg
。服务器端就准备完成了,我们可以开始准备小程序端的代码了。
接下来,就可以在小程序端去下载这个文件了,打开index.wxml
,撰写如下代码。
1 | <button type="primary" bindtap="wx_download">下载</button> |
这行代码中,我们使用下载按钮去触发wx_download
函数,触发后函数自动返回statusCode
和filePath
的值在前端显示。接下来,我们修改index.js
文件,代码如下。
1 | Page({ |
当我们在前端点击下载按钮之后,调用wx.downloadFile
去下载文件,但是这个wx.downloadFile
函数到底是什么意思呢?我们先看看官方文档。
属性 | 类型 | 默认值 | 是否必填 | 说明 |
---|---|---|---|---|
url | string | 是 | 下载资源的 url | |
header | Object | 否 | HTTP 请求的 Header,Header 中不能设置 Referer | |
filePath | string | 否 | 指定文件下载后存储的路径 | |
success | function | 否 | 接口调用成功的回调函数 | |
fail | function | 否 | 接口调用失败的回调函数 | |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
object.success 回调函数
属性 | 类型 | 说明 |
---|---|---|
tempFilePath | string | 临时文件路径。如果没传入 filePath 指定文件存储路径,则下载后的文件会存储到一个临时文件 |
statusCode | number | 开发者服务器返回的 HTTP 状态码 |
代码中,url
为我们需要下载的文件,success
为返回的事件,我们使用回调函数,判断当前下载的HTTP 状态码statusCode
并在前端展示,如果这个状态码是200
则将文件存储到tempFilePath
的临时目录,之后在前端展示该文件,具体效果如图。
注:当点击下载按钮时,如果出现这种错误请登录小程序后台,点击设置-开发设置-服务器域名,将downloadFile改为你的服务器的域名。
除了回调函数,小程序也提供了一个返回值DownloadTask
我们可以通过这个返回值函数来监控下载进度。代码如下。
index.wxml
1 | <button type="primary" bindtap="wx_download">下载</button> |
index.js
1 | Page({ |
当我们下载视频时,就可以查看当前下载进度。
下载完成后,就可以播放视频了。
在开始上传教程之前,我们需要配置好我们的服务器,否则无法进行本实验。
在第一步中,我们已经教大家部署了基本服务器,但是一直没用到PHP,接下来,将使用PHP代码来运行我们小程序的文件服务器。
服务端已经配置完成,接下来我们就需要撰写服务端代码了,代码也很简单,我们需要将其放在/usr/share/nginx/html
这个目录下,然后创建一个存放数据的upload
文件夹,并赋予相关权限,使用下面的命令。
1 | cd /usr/share/nginx/html |
之后,使用nano编辑器撰写下面的代码。
1 |
|
然后按下键盘上的ctrl+X
之后再按下Enter
键,按Y
即可保存。现在访问你的域名https://weixin.techeek.cn
,看看其是否生效。
因为我们没传入文件,所以文件名部分是空的数据,没关系,能看到这步就证明你的服务器已经搭建完成。我们可以进行试验了!
小程序端代码比较简单,通过几行代码即可实现,首先,我们修改index.wxml
文件,代码如下。
1 | <button type="primary" bindtap="wx_up">上传</button> |
这段代码中,我们使用上传按钮执行wx_up
函数,同时接受返回数据statusCode
。接下来,我们修改index.js
文件,代码如下。
1 | Page({ |
这段代码中,为了方便起见,我调用了wx.chooseImage
去获取图片文件,并将其存储在临时目录,然后通过wx.uploadFile
接口去上传图片文件到我们的服务器。过程比较简单,wx.chooseImage
使用本文暂不介绍,我们来看看上传接口wx.uploadFile
到底是什么意思,首先看看官方文档中的介绍。
属性 | 类型 | 默认值 | 是否必填 | 说明 |
---|---|---|---|---|
url | string | 是 | 开发者服务器地址 | |
filePath | string | 是 | 要上传文件资源的路径 | |
name | string | 是 | 文件对应的 key,开发者在服务端可以通过这个 key 获取文件的二进制内容 | |
header | Object | 否 | HTTP 请求 Header,Header 中不能设置 Referer | |
formData | Object | 否 | HTTP 请求中其他额外的 form data | |
success | function | 否 | 接口调用成功的回调函数 | |
fail | function | 否 | 接口调用失败的回调函数 | |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
object.success 回调函数
属性 | 类型 | 说明 |
---|---|---|
data | string | 开发者服务器返回的数据 |
statusCode | number | 开发者服务器返回的 HTTP 状态码 |
在代码中,url
为我们服务器的地址,填写的为https://weixin.techeek.cn/
这里要更改为自己的接口,filePath
为要上传文件资源的路径,我们这里写的是小程序图片的临时路径,wx.chooseImage
接口的文件就暂存到这里。name
为文件对应的key,我们填写的file
即可。这是三个必填项,后续请求数据可以不填写。
接下来,需要在函数执行成功后,填写回调函数,这里,我们将返回的 HTTP 状态码通过setData
方法,将数据存返回到前端。如果你看到如图的效果,证明文件上传完成。
接下来,看看服务器端是否有我们上传的图片文件。
我们看到,图片文件已近成功上传。
那么,上传完成后,除了返回的statusCode
,还有data
参数,那么data参数如何使用?请关注本专栏,下篇文章,我们将讲解《如何在小程序中实现人脸识别功能》。
后续文章中我们将对这部分做详细介绍,并提供相关Demo做演示。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
我们可以直接在前端调用video
组件进行视频播放,打开你的index.wxml
文件,写下如下代码。
1 | <video src="https://qcloudbbs-10019892.cos.ap-shanghai.myqcloud.com/Donald%20Duck.mp4"></video> |
有前端开发经验的小伙伴应该能看懂吧,src
是我们视频的地址。通过这段简单的代码,我们就可以实现在小程序中播放视频。
但是,有没有其他功能呢?我们可以看看官方文档中的内容。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
src | String | 要播放视频的资源地址,支持云文件ID(2.2.3起) | |
initial-time | Number | 指定视频初始播放位置 | |
duration | Number | 指定视频时长 | |
controls | Boolean | true | 是否显示默认播放控件(播放/暂停按钮、播放进度、时间) |
danmu-list | Object Array | 弹幕列表 | |
danmu-btn | Boolean | false | 是否显示弹幕按钮,只在初始化时有效,不能动态变更 |
enable-danmu | Boolean | false | 是否展示弹幕,只在初始化时有效,不能动态变更 |
autoplay | Boolean | false | 是否自动播放 |
loop | Boolean | false | 是否循环播放 |
muted | Boolean | false | 是否静音播放 |
page-gesture | Boolean | false | 在非全屏模式下,是否开启亮度与音量调节手势 |
direction | Number | 设置全屏时视频的方向,不指定则根据宽高比自动判断。有效值为 0(正常竖向), 90(屏幕逆时针90度), -90(屏幕顺时针90度) | |
show-progress | Boolean | true | 若不设置,宽度大于240时才会显示 |
show-fullscreen-btn | Boolean | true | 是否显示全屏按钮 |
show-play-btn | Boolean | true | 是否显示视频底部控制栏的播放按钮 |
show-center-play-btn | Boolean | true | 是否显示视频中间的播放按钮 |
enable-progress-gesture | Boolean | true | 是否开启控制进度的手势 |
objectFit | String | contain | 当视频大小与 video 容器大小不一致时,视频的表现形式。contain:包含,fill:填充,cover:覆盖 |
poster | String | 视频封面的图片网络资源地址或云文件ID(2.2.3起支持)如果 controls 属性值为 false 则设置 poster 无效 | |
bindplay | EventHandle | 当开始/继续播放时触发play事件 | |
bindpause | EventHandle | 当暂停播放时触发 pause 事件 | |
bindended | EventHandle | 当播放到末尾时触发 ended 事件 | |
bindtimeupdate | EventHandle | 播放进度变化时触发,event.detail = {currentTime, duration} 。触发频率 250ms 一次 | |
bindfullscreenchange | EventHandle | 视频进入和退出全屏时触发,event.detail = {fullScreen, direction},direction取为 vertical 或 horizontal | |
bindwaiting | EventHandle | 视频出现缓冲时触发 | |
binderror | EventHandle | 视频播放出错时触发 | |
bindprogress | EventHandle | 加载进度变化时触发,只支持一段加载。event.detail = {buffered},百分比 |
通过上表,我们可以实现一些功能,比如我想实现视频播放静音,并显示封面,打开手势控制及手势音量亮度控制,循环播放,播放时从60秒开始,并且静音播放,参考上表则可以使用下面的代码。
1 | <video src="https://qcloudbbs-10019892.cos.ap-shanghai.myqcloud.com/Donald%20Duck.mp4" poster="http://a0.att.hudong.com/13/68/01300542392970143494689930378.jpg" enable-progress-gesture loop muted page-gesture initial-time=“60” ></video> |
视频调用比较简单,微信还推出了相关的API以方便我们使用视频播放组件。我们可以通过VideoContext
接口来控制当前视频,在使用该接口之前,需要使用wx.createVideoContext()
创建对象。创建完对象后,我们可以使用下面的方法去做视频的基本控制。
wx.createVideoContext()
需要指定当前组件的ID才能使用,所以我们修改index.wxml
内容如下。
1 | <video src="https://qcloudbbs-10019892.cos.ap-shanghai.myqcloud.com/Donald%20Duck.mp4" id="Video" danmu-btn enable-danmu></video> |
在这段代码中,我们指定了打开弹幕,并设置几个按钮去调用index.js
中的数据,这里id内的内容可随意指定,但需要记录其内容。接下来,我们在index.js
文件的page()
中,写出下面的代码。
1 | Page({ |
这段代码中,我们创建了几个函数,这几个函数去调用微信的接口,从而实现播放,暂停,弹幕等功能。
聪明的你学会了吗?赶快自己去部署一个小程序实现自己想要的功能吧!后续我将会对其他组件做详细的介绍。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
音频组件使用较为简单,在index.wxml
文件中撰写调用audio
组件即可。
1 | <audio controls src="https://qcloudbbs-10019892.cos.ap-shanghai.myqcloud.com/%E6%99%AE%E9%80%9ADisco%20-%20%E6%B4%9B%E5%A4%A9%E4%BE%9D%20_%20%E8%A8%80%E5%92%8C.mp3"></audio> |
有前端开发经验的小伙伴肯定能看懂,src
中是我们要播放音频的地址,那么controls
是什么意思呢?我们先看看官方的文档吧,如下表。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
id | String | audio 组件的唯一标识符 | |
src | String | 要播放音频的资源地址 | |
loop | Boolean | false | 是否循环播放 |
controls | Boolean | false | 是否显示默认控件 |
poster | String | 默认控件上的音频封面的图片资源地址,如果 controls 属性值为 false 则设置 poster 无效 | |
name | String | 未知音频 | 默认控件上的音频名字,如果 controls 属性值为 false 则设置 name 无效 |
author | String | 未知作者 | 默认控件上的作者名字,如果 controls 属性值为 false 则设置 author 无效 |
binderror | EventHandle | 当发生错误时触发 error 事件,detail = {errMsg: MediaError.code} | |
bindplay | EventHandle | 当开始/继续播放时触发play事件 | |
bindpause | EventHandle | 当暂停播放时触发 pause 事件 | |
bindtimeupdate | EventHandle | 当播放进度改变时触发 timeupdate 事件,detail = {currentTime, duration} | |
bindended | EventHandle | 当播放到末尾时触发 ended 事件 |
原来,controls
的意思是是否显示默认控件,默认值是不显示的,当我们写出controls
才会显示播放的控件。当然,我们还可以为当前控件加入其它属性。
1 | <audio controls src="https://qcloudbbs-10019892.cos.ap-shanghai.myqcloud.com/%E6%99%AE%E9%80%9ADisco%20-%20%E6%B4%9B%E5%A4%A9%E4%BE%9D%20_%20%E8%A8%80%E5%92%8C.mp3" poster="http://i1.hdslb.com/bfs/archive/89252dadd2525f8190485a069f73cdf3d783cabc.jpg" name="普通disco" author="洛天依/言和"></audio> |
我们增加了音乐名称和作者,并给该音频配置了封面。为了优化代码,我们可以这样写。首先修改index.wxml
文件如下。
1 | <audio poster="{{poster}}" name="{{name}}" author="{{author}}" src="{{src}}" controls></audio> |
之后,我们将音频数据存储在index.js
目录下,将下面的代码放在data{}
之间。
1 | poster: 'http://i1.hdslb.com/bfs/archive/89252dadd2525f8190485a069f73cdf3d783cabc.jpg', |
这时,我们就做到了前后端数据分离,后续可以实现更多功能,比如可以通过后端实现下一曲的功能。
index.wxml
1 | <audio poster="{{poster}}" name="{{name}}" author="{{author}}" src="{{src}}" controls></audio> |
index.js
1 | data: { |
这时,当我们点击下一曲按钮时,会执行next()
函数,自动更换poster
、name
、author
、src
等数据。
我们已经学会了音频组件的基本调用步骤,控制音频暂停,播放,转跳等功能需要相关API的支持,接下来,我们就看看如何使用API来实现这些功能。
音频播放暂停、播放等功能需要AudioContext
接口,在使用该接口之前,需要使用wx.createAudioContext()
创建对象。创建完对象后,我们使用播放音频方法AudioContext.play(),暂停音频方法AudioContext.pause(),跳转到指定位置方法AudioContext.seek(number position)来控制当前音频。
wx.createAudioContext()
需要指定当前组件的ID才能使用,所以我们修改index.wxml
内容如下。
1 | <audio id="Audio" poster="{{poster}}" name="{{name}}" author="{{author}}" src="{{src}}" controls ></audio> |
这里id内的内容可随意指定,但需要记录其内容。接下来,我们在index.js
文件的page()
中,写出下面的代码。
1 | data: { |
这段代码中,我们指定了默认的音乐数据,存放在data()
中,然后创建audioPlay
、audioPause()
、audio14()
、audioStart()
四个函数,来控制当前音乐,在onReady
函数中,我们指定了当前音频的ID。
新版的小程序中,官方推荐使用InnerAudioContext
接口来替代AudioContext
接口,并且后续AudioContext
将不再维护。同时<audio>
组件也不在维护,我们需要自己去写代码去实现前端展示功能。
InnerAudioContext
接口使用和AudioContext
比较接近,在调用前,我们不需要指定相关ID。我们可以使用下面的代码来实现基本的播放功能。
index.js
1 | data: { |
index.wxml
1 | <button type="primary" bindtap="audioPlay">播放</button> |
InnerAudioContext
接口参数较多,官方文档写的比较粗糙,为了看起来易懂,我将其做成表格。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
src | string | 音频资源的地址,用于直接播放。2.2.3 开始支持云文件ID | |
startTime | number | 0 | 开始播放的位置(单位:s),默认为 0 |
autoplay | boolean | false | 是否自动开始播放,默认为 false |
loop | boolean | false | 是否循环播放,默认为 false |
obeyMuteSwitch | boolean | true | 是否遵循系统静音开关,默认为 true 。当此参数为 false 时,即使用户打开了静音开关,也能继续发出声音 |
volume | number | 1 | 音量。范围 0~1。默认为 1 |
duration | number | 当前音频的长度(单位 s)。只有在当前有合法的 src 时返回(只读) | |
currentTime | number | 当前音频的播放位置(单位 s)。只有在当前有合法的 src 时返回,时间保留小数点后 6 位(只读) | |
paused | boolean | 当前是是否暂停或停止状态(只读) | |
buffered | number | 音频缓冲的时间点,仅保证当前播放时间点到此时间点内容已缓冲(只读) |
同样,也给出了若干接口,本文只列出几个常用的接口,其他接口使用请见官方文档。
接口 | 说明 |
---|---|
InnerAudioContext.play() | 播放 |
InnerAudioContext.pause() | 暂停。暂停后的音频再播放会从暂停处开始播放 |
InnerAudioContext.stop() | 停止。停止后的音频再播放会从头开始播放。 |
InnerAudioContext.seek(number position) | 跳转到指定位置 |
参考上表,我们可以为我们的小程序增加暂停功能,修改代码如下。
1 | <button type="primary" bindtap="audioPlay">播放</button> |
接下来,我们优化下index.js
文件代码。
1 | Page({ |
现在,你学会使用音频组件及API的使用了吗?关于API推荐使用InnerAudioContext
,根据官方说明音频组件和AudioContext
将不再更新。后续我将会对其他组件做详细的介绍。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
takePhoto
API,还有其他API可以使用,这篇教程,我们将介绍录像API的使用。在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
小程序调用相机很简单,只用一行代码即可实现,修改你的index.wxml
文件,为如下代码。
1 | <camera style="width: 100%; height: 450px;"></camera> |
当然这行代码仅仅实现了相机在小程序内显示,无法实现更多功能,我们可以参考官方文档来实现更多功能。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
mode | String | normal | 有效值为 normal, scanCode |
device-position | String | back | 前置或后置,值为front, back |
flash | String | auto | 闪光灯,值为auto, on, off |
bindstop | EventHandle | 摄像头在非正常终止时触发,如退出后台等情况 | |
binderror | EventHandle | 用户不允许使用摄像头时触发 | |
bindscancode | EventHandle | 在扫码识别成功时触发,仅在 mode=”scanCode” 时生效 |
参考上表,我们来实现一个“镜子”的小功能,打开小程序,自动将摄像头转换为前置摄像头,然后默认打开闪光灯,修改代码如下。
1 | <camera device-position="front" flash="on" style="width: 100%; height: 450px;"></camera> |
通过上面的代码,就可以将小程序变为“镜子”。
我们已经学会了使用相机的基本组件的调用,但是在表中我们并没有看到录像等功能的配置。为了前后端分离,小程序将录像等功能封装成了API,我们需要在camera
组件中调用相关函数才能实现录像功能。这里我们需要调用两个函数,分别为开始录像的startRecord
和停止录像的stopRecord
,最后,我们通过回调函数存储相关数据,关于录像API的参数,我们可以参考下表。
startRecord
属性 | 类型 | 默认值 | 是否必填 | 说明 |
---|---|---|---|---|
timeoutCallback | function | 否 | 超过30s或页面 onHide 时会结束录像 | |
success | function | 否 | 接口调用成功的回调函数 | |
fail | function | 否 | 接口调用失败的回调函数 | |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
stopRecord
属性 | 类型 | 默认值 | 是否必填 | 说明 | 支持版本 |
---|---|---|---|---|---|
success | function | 否 | 接口调用成功的回调函数 | ||
fail | function | 否 | 接口调用失败的回调函数 | ||
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
回调函数
属性 | 类型 | 说明 | 支持版本 |
---|---|---|---|
tempThumbPath | string | 封面图片文件的临时路径 | |
tempVideoPath | string | 视频的文件的临时路径 |
参考上表,我们要用到JavaScript语言对相机API进行封装,首先,我们打开index.js
文件,在page()
中,写出下面的代码。
1 | startRecord() { |
这段代码中,我们设定了两个函数startRecord()
和stopRecord()
,在startRecord()
函数中,调用startRecord
API,启动录像功能。在stopRecord()
函数中,调用stopRecord
停止录像,并将录像暂存在res.tempVideoPath
中,同时暂存临时封面tempThumbPath
。接下来,我们撰写前端页面,打开index.wxml
。
1 | <camera flash="on" style="width: 100%; height: 450px;"></camera> |
在index.wxml
文件中,我们首先定义camera
组件,然后通过button
按钮去调用刚才撰写的startRecord()
函数和stopRecord()
函数。之后函数返回videoSrc
链接,让前台video
组件去调用。
现在,就可以实现在小程序端进行录像了!
你学会了嘛?赶快去体验下吧!后续我将会对其他组件做详细的介绍。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>wx.scanCode()
,实现调起客户端扫码界面进行扫码。在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
因为我们要调用小程序的API,就不能像以前那样直接在index.wxml
中写相关组件直接调用,我们可以通过一些组件,如view
或button
之类的组件来调用相关函数。首先,在index.wxml
中写出下面的代码。
1 | <button type="primary" bindtap="scanCode">扫码</button> |
我们新建一个按钮,当点击这个按钮的时候,执行scanCode
函数,去调用wx.scanCode()
API。关于wx.scanCode()API的使用,我们可以参考下表。
属性 | 类型 | 默认值 | 是否必填 | 说明 |
---|---|---|---|---|
onlyFromCamera | boolean | false | 否 | 是否只能从相机扫码,不允许从相册选择图片 |
scanType | Array. | [‘barCode’, ‘qrCode’] | 否 | 扫码类型 |
success | function | 否 | 接口调用成功的回调函数 | |
fail | function | 否 | 接口调用失败的回调函数 | |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
接下来,我们撰写scanCode
函数,打开index.js
文件,然后在page()
之间,写出下面的代码。
1 | scanCode() { |
首先,我们新建sacnCode
函数,接下来,调用wx.scanCode
API。参考上表,我们撰写如下代码,当接口调用成功,执行某个函数。
1 | scanCode() { |
我们可以通下表属性来确定我们在成功后应该执行什么函数。
属性 | 类型 | 说明 |
---|---|---|
result | string | 所扫码的内容 |
scanType | string | 所扫码的类型 |
charSet | string | 所扫码的字符集 |
path | string | 当所扫的码为当前小程序的合法二维码时,会返回此字段,内容为二维码携带的 path |
rawData | string | 原始数据,base64编码 |
这里我想使用console.log
将得到的数据打印在控制台,那么可以将代码写成这样。
1 | scanCode() { |
这时,我们点击微信开发者工具的真机调试按钮,然后使用手机扫码二维码,如果你扫码二维码,控制台返回了二维码相关结果,证明配置成功。
当然,我们还可以将扫描到的二维码数据返回到用户界面,可以使用下面的代码,首先修改index.wxml
。
1 | <view><text>你扫到的是{{scanType}}码</text></view> |
然后,修改index.js
为下面内容。
1 | scanCode() { |
这行代码的意思是,通过setData
将返回的数据赋值给result
和scanType
变量,然后通过index.wxml
在前端展现出来。
我们还可以实现更高阶的玩法,比如扫描几张二维码,扫描出来的二维码对应小程序的某组数据,之后做显示。比如说这里有三张二维码图片,扫描出来数据分别为11111
、22222
、33333
。
我们可以自定义这三张二维码給用户返回的数据,比如说扫描到11111
显示一张狗狗的照片。扫描到22222
显示一张猫咪的照片,扫描到33333
显示一张鹦鹉的照片。我们可以使用switch
语句来返回相关的照片。修改index.wxml
代码如下。
1 | <view><image src='{{src}}'></image></view> |
我们新建image
组件,然后将src
图片地址设为变量,等待index.js
返回相关参数。接下来我们写逻辑部分,index.js
代码如下。
1 | scanCode() { |
现在,当我们扫描上面的二维码时,会自动显示猫、狗、鹦鹉的照片。而不是将扫描到是数据返回给用户。
怎么样,你学会使用小程序进行扫描了嘛?文中我演示的只是基础的操作。如果再加上request
操作,就可以实现像小程序扫描共享单车开锁之类的功能哦~快去尝试下吧!后续我将会对其他组件做详细的介绍。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
camera
组件的使用,并自己制作一个小程序相机的demo
出来。在教程开始之前,需要搭建搭建好小程序的基础开发环境,关于如何配置,大家可以参考如何入门小程序开发这篇文章的入门教程。
小程序调用相机很简单,只用一行代码即可实现,修改你的index.wxml
文件,为如下代码。
1 | <camera style="width: 100%; height: 450px;"></camera> |
当然这行代码仅仅实现了相机在小程序内显示,无法实现更多功能,我们可以参考官方文档来实现更多功能。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
mode | String | normal | 有效值为 normal, scanCode |
device-position | String | back | 前置或后置,值为front, back |
flash | String | auto | 闪光灯,值为auto, on, off |
bindstop | EventHandle | 摄像头在非正常终止时触发,如退出后台等情况 | |
binderror | EventHandle | 用户不允许使用摄像头时触发 | |
bindscancode | EventHandle | 在扫码识别成功时触发,仅在 mode=”scanCode” 时生效 |
参考上表,我们来实现一个“镜子”的小功能,打开小程序,自动将摄像头转换为前置摄像头,然后默认打开闪光灯,修改代码如下。
1 | <camera device-position="front" flash="on" style="width: 100%; height: 450px;"></camera> |
通过上面的代码,就可以将小程序变为“镜子”。
我们已经学会了使用相机的基本组件的调用,但是在表中我们并没有看到拍照等功能的配置。为了前后端分离,小程序将拍照等功能封装成了API,我们需要在camera
组件中调用相关函数才能实现拍照功能。关于拍照API的参数,我们可以参考下表。
属性 | 类型 | 默认值 | 是否必填 | 说明 |
---|---|---|---|---|
quality | string | normal | 否 | 成像质量 |
success | function | 否 | 接口调用成功的回调函数 | |
fail | function | 否 | 接口调用失败的回调函数 | |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
参考上表,我们要用到JavaScript语言对相机API进行封装,首先,我们打开index.js
文件,在page()
中,写出下面的函数。
1 | takePhoto(){ |
这是第一步,创建一个takePhoto
函数,接下来,我们调用小程序相机的API。
1 | takePhoto(){ |
创建ctx对象,该对象为wx.createCameraContext()
函数。接下来,需要调用createCameraContext()
的takePhoto
组件。
1 | takePhoto(){ |
接下来,参考上表,我们设置我们所需要的参数。
1 | takePhoto() { |
这段代码中,我们定义了拍照的图像质量,并将图片文件存放在tempImagePath
临时路径中,然后通过serData
函数,将路径写给src
变量,后面我们去调用这张图片的地址。后台逻辑处理功能已经写完了,接下来,我们需要去写前端界面,将图片展示出来。
打开index.wxml
文件,我们修改代码如下。
1 | <camera device-position="front" flash="on" style="width: 100%; height: 450px;"></camera> |
我们使用button
按钮调用takePhoto
函数进行拍照,然后将图片地址返回到src
中显示。
这就是基本的小程序相机拍照基本使用方法,你学会了嘛?赶快去体验下吧!后续我将会对其他组件做详细的介绍。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>map
组件的使用,但是对于刚开始接触地图组件的同学,难免有些难以下手。本文将以Hello World为例对地图组件的使用列出一些demo,以方便后续开发。小程序提供的map
组件是原生组件,部分功能需要配合地图相关的API使用,这里先不做涉及,我们后续再讲。先看看如何展示一张地图吧,打开你的微信编辑器,找到index.wxml
文件,写下下面的代码。
1 | <map></map> |
没错,通过这段代码,默认就能调用出一个地图组件,但是仅仅能显示地图而已,并无其他功能,如果我想要一些自定的功能怎么办?我们可以调用map
组件提供的一些属性,具体属性如下表。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
longitude | Number | 中心经度 | |
latitude | Number | 中心纬度 | |
scale | Number | 16 | 缩放级别,取值范围为5-18 |
markers | Array | 标记点 | |
polyline | Array | 路线 | |
polygons | Array | 多边形 | |
circles | Array | 圆 | |
include-points | Array | 缩放视野以包含所有给定的坐标点 | |
show-location | Boolean | 显示带有方向的当前定位点 | |
subkey | String | ‘’ | 个性化地图使用的key,仅初始化地图时有效 |
enable-3D | Boolean | false | 展示3D楼块(工具暂不支持) |
show-compass | Boolean | false | 显示指南针 |
enable-overlooking | Boolean | false | 开启俯视 |
enable-zoom | Boolean | true | 是否支持缩放 |
enable-scroll | Boolean | true | 是否支持拖动 |
enable-rotate | Boolean | false | 是否支持旋转 |
bindmarkertap | EventHandle | 点击标记点时触发,会返回marker的id | |
bindcallouttap | EventHandle | 点击标记点对应的气泡时触发,会返回marker的id | |
bindcontroltap | EventHandle | 点击控件时触发,会返回control的id | |
bindregionchange | EventHandle | 视野发生变化时触发 | |
bindtap | EventHandle | 点击地图时触发 | |
bindupdated | EventHandle | 在地图渲染更新完成时触发 | |
bindpoitap | EventHandle | 点击地图poi点时触发 |
我们可以先从简单的功能开始,目前的地图组件默认位置的是北京的经纬度。我们可以将其改成自己所在位置的经纬度,并设置大小。
1 | <map style='width:500px;height:500px' longitude="113.941133" latitude="22.545999"></map> |
当然,我们可以设置地图是否支持3D,是否能开启指南针,是否支持插件等功能。可以试试下面的代码,建议在真机端测试,因为开发工具的地图是模拟出来的,部分功能无法实现,在真机端可以看到下面的图片样式。
1 | <map style='width:500px;height:500px' longitude="113.941133" latitude="22.545999" scale="18" show-compass="ture" enable-3D="ture" enable-overlooking="ture" enable-rotate="ture" enable-zoom="ture" enable-scroll="ture"></map> |
现在,我们已经是实现了一个简单的demo,如果我们想加入更多功能,比如标记当前你指定的坐标,并作一些信息展示,那么该怎么做呢?
为了解决标记显示问题,小程序增加了markers
属性,我们可以为当前坐标增加相关信息。还是用上图的代码,我们增加一行属性配置代码。
1 | <map style='width:500px;height:500px' longitude="113.941133" latitude="22.545999" scale="18" show-compass="ture" enable-3D="ture" enable-overlooking="ture" enable-rotate="ture" enable-zoom="ture" enable-scroll="ture" markers="{{markers}}"></map> |
然后,我们打开index.js
修改为下面的代码。
1 | Page({ |
这里可能会提醒大家找不到others.png
这个文件,我们需要下载将其复制到index
文件夹下。
之后再次进行预览,你就能看大当前的标志了。
那么,index.js
文件中的代码到底是什么意思呢?我们先看看官方文档。
markers - 标记点用于在地图上显示标记的位置
属性 | 说明 | 类型 | 必填 | 备注 |
---|---|---|---|---|
id | 标记点id | Number | 否 | marker点击事件回调会返回此id。建议为每个marker设置上Number类型id,保证更新marker时有更好的性能。 |
latitude | 纬度 | Number | 是 | 浮点数,范围 -90 ~ 90 |
latitude | 经度 | Number | 是 | 浮点数,范围 -180 ~ 180 |
title | 标注点名 | String | 否 | |
zIndex | 显示层级 | Number | 否 | |
iconPath | 显示的图标 | String | 是 | 项目目录下的图片路径,支持相对路径写法,以’/‘开头则表示相对小程序根目录;也支持临时路径和网络图片(2.3.0) |
rotate | 旋转角度 | Number | 否 | 顺时针旋转的角度,范围 0 ~ 360,默认为 0 |
alpha | 标注的透明度 | Number | 否 | 默认1,无透明,范围 0 ~ 1 |
width | 标注图标宽度 | Number / String | 否 | 默认为图片实际宽度(单位px或rpx,默认为px) |
height | 标注图标高度 | Number / String | 否 | 默认为图片实际高度(单位px或rpx,默认为px) |
callout | 自定义标记点上方的气泡窗口 | Object | 否 | 支持的属性见下表,可识别换行符。 |
label | 为标记点旁边增加标签 | Object | 否 | 支持的属性见下表,可识别换行符。 |
anchor | 经纬度在标注图标的锚点,默认底边中点 | Object | 否 | {x, y},x表示横向(0-1),y表示竖向(0-1)。{x: .5, y: 1} 表示底边中点 |
在index.js
文件中,我们指定了iconPath
图标,指定了latitude
、latitude
经纬度,以及图标的大小,包括标记点的ID
。然后在地图中显示出来。
我们也可以为当前标记增加标签和气泡,参考上表中的callout
和label
,就可以增加相关标记。先上代码,首先修改index.js
文件。
1 | Page({ |
我们可以看看 marker 上的气泡 label和callout支持的属性。
属性 | 说明 | 类型 |
---|---|---|
content | 文本 | String |
color | 文本颜色 | String |
fontSize | 文字大小 | Number / String |
anchorX | label的坐标,原点是 marker 对应的经纬度 | Number / String |
anchorY | label的坐标,原点是 marker 对应的经纬度 | Number / String |
borderWidth | 边框宽度 | Number / String |
borderColor | 边框颜色 | String |
borderRadius | 边框圆角 | Number / String |
bgColor | 背景色 | String |
padding | 文本边缘留白 | Number / String |
textAlign | 文本对齐方式。有效值: left, right, center | String |
可以看到,代码中,我们指定了显示的文本,指定了文本及背景的颜色,指定了文本的大小。当然,这里只是演示了部分功能,小伙伴可以自定更多功能。
有时我们需要在地图中实现坐标点连线功能,如果自己一个一个标记路径非常麻烦,那么我们可以使用小程序给出的polyline
属性,来将地图中的坐标点连成一条线。指定一系列坐标点,从数组第一项连线至最后一项,我们先看看官方文档。
属性 | 说明 | 类型 | 必填 | 备注 |
---|---|---|---|---|
points | 经纬度数组 | Array | 是 | [{latitude: 0, longitude: 0}] |
color | 线的颜色 | String | 否 | 8位十六进制表示,后两位表示alpha值,如:#000000AA |
width | 线的宽度 | Number | 否 | |
dottedLine | 是否虚线 | Boolean | 否 | 默认false |
arrowLine | 带箭头的线 | Boolean | 否 | 默认false,开发者工具暂不支持该属性 |
arrowIconPath | 更换箭头图标 | String | 否 | 在arrowLine为true时生效 |
borderColor | 线的边框颜色 | String | 否 | |
borderWidth | 线的厚度 | Number | 否 |
polyline中需要points
属性数组来展示当前路径,所以我们在index.js
中需要定义points
数组数据。我们还是使用上面的代码进行修改。
1 | <map style='width:500px;height:500px' longitude="113.941133" latitude="22.545999" scale="16" show-compass="ture" enable-3D="ture" enable-overlooking="ture" enable-rotate="ture" enable-zoom="ture" enable-scroll="ture" polyline="{{polyline}}"></map> |
然后打开index.js
修改代码。
1 | Page({ |
在小程序中,我们将这三个坐标通过polyline属性将其连接起来。某些情况下,我们可能还会在地图中显示一和闭合图形,小程序官方也提供了polygons
组件供我们使用。和polyline
使用比较接近,我们可以试试下面的代码。
首先修改index.wxml
文件为下面的代码。
1 | <map style='width:500px;height:500px' longitude="113.941133" latitude="22.545999" scale="16" show-compass="ture" enable-3D="ture" enable-overlooking="ture" enable-rotate="ture" enable-zoom="ture" enable-scroll="ture" polygons="{{polygons}}"></map> |
然后修改index.js
文件为下面的代码。
1 | Page({ |
这时,你会看到如下所示的地图样式。
我们在地图中,画出了一个包含我们在index.js
中定义的points
数组的图形。
除了多边形显示,有事还需要以圆的形式展现,这里我们可以使用map
组件的circles属性来实现。依然修改上面代码。
1 | <map style='width:500px;height:500px' longitude="113.941133" latitude="22.545999" scale="18" show-compass="ture" enable-3D="ture" enable-overlooking="ture" enable-rotate="ture" enable-zoom="ture" enable-scroll="ture" circles="{{circles}}"></map> |
然后,我们在index.js
中,改成下面的代码。
1 | Page({ |
我们来看看官方的文档
属性 | 说明 | 类型 | 必填 | 备注 |
latitude | 纬度 | Number | 是 | 浮点数,范围 -90 ~ 90 |
longitude | 经度 | Number | 是 | 浮点数,范围 -180 ~ 180 |
color | 描边的颜色 | String | 否 | 8位十六进制表示,后两位表示alpha值,如:#000000AA |
fillColor | 填充颜色 | String | 否 | 8位十六进制表示,后两位表示alpha值,如:#000000AA |
radius | 半径 | Number | 是 | |
strokeWidth | 描边的宽度 | Number | 否 |
圆的属性不多,在代码中,我们指定了该圆圆心的经纬度,指定了半径和描边填充颜色。大家可以按照自己需求修改。
小程序也提供了相关的定位功能,我们可以通过wx.getLocation()
函数来获取当前用户的经纬度,然后通过markers属性来将其显示出来。首先,我们看看wx.getLocation()
函数的功能,我们需要传入表中的若干参数,然后查看返回值即可。
属性 | 类型 | 默认值 | 是否必填 | 说明 |
---|---|---|---|---|
type | string | wgs84 | 否 | wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标 |
altitude | string | false | 否 | 传入 true 会返回高度信息,由于获取高度需要较高精确度,会减慢接口返回速度 |
success | function | 否 | 接口调用成功的回调函数 | |
fail | function | 否 | 接口调用失败的回调函数 | |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
这里我们只需要传入type
的值和等待返回success
结果就行,我们看看返回值会返回什么。
属性 | 类型 | 说明 |
---|---|---|
latitude | number | 纬度,范围为 -90~90,负数表示南纬 |
longitude | number | 经度,范围为 -180~180,负数表示西经 |
speed | number | 速度,单位 m/s |
accuracy | number | 位置的精确度 |
altitude | number | 高度,单位 m |
verticalAccuracy | number | 垂直精度,单位 m(Android 无法获取,返回 0) |
horizontalAccuracy | number | 水平精度,单位 m |
我们需要定位,则只需要返回latitude
值和longitude
值即可,为了方便演示,我这边也返回speed
速度,altitude
高度。首先,我们修改index.wxml
文件,创建地图。
1 | <map style='width:500px;height:500px' longitude="{{longitude}}" latitude="{{latitude}}" scale="18" show-compass="ture" enable-3D="ture" enable-overlooking="ture" enable-rotate="ture" enable-zoom="ture" enable-scroll="ture" markers="{{markers}}"></map> |
然后修改index.js
文件
1 | Page({ |
这里我们先在data{}
中指定了默认的数值,以防止开启后地图无法显示内容,然后在wx_getlocation()
函数中调用wx.getlocation
的API来显示位置,同时返回值使用this.setData
改变默认数值,显示在index.js
中。
你学会地图组件的使用了吗?尝试写一个小的demo出来吧!后续我将会对其他组件做详细的介绍。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>audio
音频组件,image
图像组件,video
视频组件,camera
相机组件以及live-player、live-pusher
小程序直播组件。其中直播权限需要相关资质的账号才能开通,本文暂不做介绍。其他组件我们将会以Hello World的demo形式做介绍。音频组件需要调用wx.createInnerAudioContext()
接口使用,我们使用其他组件来调用wx.createInnerAudioContext()
内部的函数,来实现对audio
组件的播放暂停下一曲等操作的调用。首先,先看看代码,修改index.wxml
文件内容,如下。
1 | <view><audio poster="{{poster}}" name="{{name}}" author="{{author}}" src="{{src}}" id="myAudio" controls loop></audio></view> |
之后,修改index.js
文件内容如下。
1 | Page({ |
通过上述代码,你就可以实现一个小的播放器功能,先看看官方文档,然后我们在介绍下代码的意思。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
id | String | audio 组件的唯一标识符 | |
src | String | 要播放音频的资源地址 | |
loop | Boolean | false | 是否循环播放 |
controls | Boolean | false | 是否显示默认控件 |
poster | String | 默认控件上的音频封面的图片资源地址,如果 controls 属性值为 false 则设置 poster 无效 | |
name | String | 未知音频 | 默认控件上的音频名字,如果 controls 属性值为 false 则设置 name 无效 |
author | String | 未知作者 | 默认控件上的作者名字,如果 controls 属性值为 false 则设置 author 无效 |
binderror | EventHandle | 当发生错误时触发 error 事件,detail = {errMsg: MediaError.code} | |
bindplay | EventHandle | 当开始/继续播放时触发play事件 | |
bindpause | EventHandle | 当暂停播放时触发 pause 事件 | |
bindtimeupdate | EventHandle | 当播放进度改变时触发 timeupdate 事件,detail = {currentTime, duration} | |
bindended | EventHandle | 当播放到末尾时触发 ended 事件 |
首先,必须填的内容有id
,scr
,因为我们要通过wx.createAudioContext()
函数去获取当前播放器的id
,获取id后,我们的API才能通过scr
给出的音频地址播放当前的音频。
在在index.wxml
的代码中,我们指定了当前id为myAudio
,指定了音频数据及作者信息,等待从index.js
中获取,并在每个button
指定调用的函数。
在index.js
中,我们指定了初始数据poster
、name
、author
、author
。然后通过wx.createAudioContext('myAudio')
去寻找index.wxml
中的myAudio
文件。接下来,写了4个音频控制函数audioCtx.play()
并通过index.wxml
中的button
去调用。
赶快去实现这个demo给自己做一个播放器吧!
图片也是在小程序开发中最常用的一种功能,调用图片比较简单,通过一行代码即可实现,修改index.wxml
如下。
1 | <image src="https://source.unsplash.com/random/1600x900"></image> |
通过这行代码,你就可以实现在小程序中显示图片,但是,image
组件有没有更多功能呢?我们先看看文档。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
src | String | 图片资源地址,支持云文件ID(2.2.3起) | |
mode | String | ‘scaleToFill’ | 图片裁剪、缩放的模式 |
lazy-load | Boolean | false | 图片懒加载。只针对page与scroll-view下的image有效 |
binderror | HandleEvent | 当错误发生时,发布到 AppService 的事件名,事件对象event.detail = {errMsg: ‘something wrong’} | |
bindload | HandleEvent | 当图片载入完毕时,发布到 AppService 的事件名,事件对象event.detail = {height:’图片高度px’, width:’图片宽度px’} |
我们看到小程序有一个mode
属性,支持图片裁剪和缩放,我们可以尝试下这个功能。首先,先看看mode
属性的文档。
mode 有 13 种模式,其中 4 种是缩放模式,9 种是裁剪模式。
模式 | 值 | 说明 |
---|---|---|
缩放 | scaleToFill | 不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素 |
缩放 | aspectFit | 保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。 |
缩放 | aspectFill | 保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。 |
缩放 | widthFix | 宽度不变,高度自动变化,保持原图宽高比不变 |
裁剪 | top | 不缩放图片,只显示图片的顶部区域 |
裁剪 | bottom | 不缩放图片,只显示图片的底部区域 |
裁剪 | center | 不缩放图片,只显示图片的中间区域 |
裁剪 | left | 不缩放图片,只显示图片的左边区域 |
裁剪 | right | 不缩放图片,只显示图片的右边区域 |
裁剪 | top left | 不缩放图片,只显示图片的左上边区域 |
裁剪 | top right | 不缩放图片,只显示图片的右上边区域 |
裁剪 | bottom left | 不缩放图片,只显示图片的左下边区域 |
裁剪 | bottom right | 不缩放图片,只显示图片的右下边区域 |
这样展示不够直观,我们使用下面的代码,将其展示出来。修改index.wxml
文件如下。
1 | <view class="section section_gap" wx:for="{{array}}" wx:for-item="item"> |
然后打开index.js
文件,修改内容如下。
1 | Page({ |
我们将看到不同的mode
对当前图片造成不同的影响。因为image组件默认宽度300px、高度225px所以,你看的图片可能会变形。
为了更直观的表现,我做了两张图,大家写代码的时候可以参考使用。
明白图片组件如何使用了吗?写代码尝试下吧!
小程序的视频组件支持很多功能,我们同样需要调用wx.VideoContext()
函数来处理视频的播放停止等功能。可以使用下面的代码来体验。首先,修改index.wxml
文件。
1 | <view class="section tc"> |
接下来,修改index.js
文件
1 | function getRandomColor () { |
我们可以使用上述的代码来实现播放暂停视频及发送弹幕功能。首先,我们先看看该组件的常用属性,这里我去掉了不常用的属性按钮,更多属性请参考官方文档。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
src | String | 要播放视频的资源地址,支持云文件ID(2.2.3起) | |
initial-time | Number | 指定视频初始播放位置 | |
duration | Number | 指定视频时长 | |
controls | Boolean | true | 是否显示默认播放控件(播放/暂停按钮、播放进度、时间) |
danmu-list | Object Array | 弹幕列表 | |
danmu-btn | Boolean | false | 是否显示弹幕按钮,只在初始化时有效,不能动态变更 |
enable-danmu | Boolean | false | 是否展示弹幕,只在初始化时有效,不能动态变更 |
autoplay | Boolean | false | 是否自动播放 |
loop | Boolean | false | 是否循环播放 |
muted | Boolean | false | 是否静音播放 |
page-gesture | Boolean | false | 在非全屏模式下,是否开启亮度与音量调节手势 |
direction | Number | 设置全屏时视频的方向,不指定则根据宽高比自动判断。有效值为 0(正常竖向), 90(屏幕逆时针90度), -90(屏幕顺时针90度) |
值得注意的是<video />
默认宽度300px、高度225px,我们可通过wxss设置宽高。在上面的代码中,我们设定了src
的视频地址,设置了相关id
,并打开了弹幕的相关设置。
之后在index.js
中,我们通过bindInputBlur()
函数和bindSendDanmu()
函数来获取你填入的弹幕及显示弹幕。关于API具体使用教程,请参考官方文档,本文只是带大家入门。
在这篇文章中,教大家使用了基础的相机组件的使用,通过相机,拍照返回当前的图片。这里拍照使用的是CameraContext()
API,我们可以使用下面的代码实现相机高阶玩法。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
mode | String | normal | 有效值为 normal, scanCode |
device-position | String | back | 前置或后置,值为front, back |
flash | String | auto | 闪光灯,值为auto, on, off |
bindstop | EventHandle | 摄像头在非正常终止时触发,如退出后台等情况 | |
binderror | EventHandle | 用户不允许使用摄像头时触发 | |
bindscancode | EventHandle | 在扫码识别成功时触发,仅在 mode=”scanCode” 时生效 |
首先我们看看官方文档,这里我们需要调用CameraContext()
API,具体API使用请参考官方文档,本文暂不赘述。可以使用下面的代码来体验相机使用。首先修改index.wxml
文件。
1 | <view class="page-body"> |
接下来,打开index.js
文件,写入下面的代码。
1 | Page({ |
通过这里的代码,那就可以实现相机组件的大部分使用了。那有小伙伴问了,如何实现二维码扫描呢?这里比较简单,我们可以直接调用微信的扫一扫进行二维码的扫描。修改index.wxml
文件如下。
1 | <view class="btn-area"> |
然后打开index.js
文件,写入下面的代码。
1 | Page({ |
这里扫描的二维码,会调用微信的二维码扫描工具进行扫描,扫描完成后,将参数返回给小程序,这里我们将扫描出来的内容通过控制台方式打印出来。
1 | {result: "https://www.techeek.cn/wx-navigator", charSet: "UTF-8", errMsg: "scanCode:ok", scanType: "QR_CODE", rawData: "aHR0cHM6Ly93d3cudGVjaGVlay5jbi93eC1uYXZpZ2F0b3I="} |
我们看到系统已经返回了相关内容,包含扫码内容,类型,字符集及原始的base64编码。
属性 | 类型 | 说明 |
---|---|---|
result | string | 所扫码的内容 |
scanType | string | 所扫码的类型 |
charSet | string | 所扫码的字符集 |
path | string | 当所扫的码为当前小程序的合法二维码时,会返回此字段,内容为二维码携带的 path |
rawData | string | 原始数据,base64编码 |
关于媒体的组件你学会了吗?使用小程序媒体组件,可以实现很多功能哦~赶快去试试吧!后续我将会对其他组件做详细的介绍。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>在开始介绍之前,我们首先需要准备一些准备跳转的页面,我这里先创建两个名为tags
标签页面和cate
目录页面。在小程序项目管理页面,点击pages
目录,然后新建目录
,创建两个名为tags
和cate
的目录。
接下来,分别在这两个文件中创建两个名为tags
和cate
的页面。当创建完页面,小程序会自动创建.js
、.wxss
、.json
这几个文件,如果没有自动生成,可能你的小程序开发工具过旧,请自行创建或升级,如图。
同时,请检查你的app.json
文件,看看该文件是否已经自动创建了"pages/cate/cate",
和"pages/tags/tags"
配置,如果没有请手动自行创建。
接下面,我们打开tags.wxml
文件,写入下面的代码。
1 | <text>我是tags页面</text> |
然后,再打开cate.wxml
文件,写入下面的代码。
1 | <text>我是cate页面</text> |
之后保存即可。
小程序导航是由navigator
组件实现的,我们可以使用该组件实现小程序内外的转跳。首先先来看看小程序的官方文档。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
target | String | self | 在哪个目标上发生跳转,默认当前小程序,可选值self/miniProgram |
url | String | 当前小程序内的跳转链接 | |
open-type | String | navigate | 跳转方式 |
delta | Number | 当 open-type 为 ‘navigateBack’ 时有效,表示回退的层数 | |
app-id | String | 当target=”miniProgram”时有效,要打开的小程序 appId | |
path | String | 当target=”miniProgram”时有效,打开的页面路径,如果为空则打开首页 | |
extra-data | Object | 当target=”miniProgram”时有效,需要传递给目标小程序的数据,目标小程序可在 App.onLaunch() ,App.onShow() 中获取到这份数据。详情 | |
version | version | release | 当target=”miniProgram”时有效,要打开的小程序版本,有效值 develop(开发版),trial(体验版),release(正式版),仅在当前小程序为开发版或体验版时此参数有效;如果当前小程序是正式版,则打开的小程序必定是正式版。 |
hover-class | String | navigator-hover | 指定点击时的样式类,当hover-class="none" 时,没有点击态效果 |
hover-stop-propagation | Boolean | false | 指定是否阻止本节点的祖先节点出现点击态 |
hover-start-time | Number | 50 | 按住后多久出现点击态,单位毫秒 |
hover-stay-time | Number | 600 | 手指松开后点击态保留时间,单位毫秒 |
bindsuccess | String | 当target=”miniProgram”时有效,跳转小程序成功 | |
bindfail | String | 当target=”miniProgram”时有效,跳转小程序失败 | |
bindcomplete | String | 当target=”miniProgram”时有效,跳转小程序完成 |
通过表格,我们可以看到,如果我们想实现转跳到小程序的某个页面,只需要使用该页面的url地址即可,比如我想转跳到tags
和cate
页面,只需要在index.wxml
文件中加入下面的代码即可。
1 | <navigator url="/pages/cate/cate">跳转到cate</navigator> |
通过点击跳转到cate
按钮即可转跳到cate
页面。当然,navigator组件内,你也可以使用其他组件,比如我们想将这两个转跳变为按钮,那可以尝试下面的代码。
1 | <navigator url="/pages/cate/cate"><button type="primary">跳转到cate</button></navigator> |
navigator
组件还可以使用open-type
来调用路由API
来实现不同的功能,具体参数详见下表。
open-type 有效值:
值 | 说明 |
---|---|
navigate | 对应 wx.navigateTo 或 wx.navigateToMiniProgram 的功能 |
redirect | 对应 wx.redirectTo 的功能 |
switchTab | 对应 wx.switchTab 的功能 |
reLaunch | 对应 wx.reLaunch 的功能 |
navigateBack | 对应 wx.navigateBack 的功能 |
exit | 退出小程序,target=”miniProgram”时生效 |
比如我们想实现打开新的页面后,关闭当前页面功能,那么就可以使用wx.redirectTo
API,调用的代码如下。
1 | <navigator open-type="redirect" url="/pages/cate/cate"><button type="primary">跳转到cate</button></navigator> |
现在,点击跳转到cate
和跳转到tags
看看有什么区别?
cate的返回按钮怎么没有了?我们先看看路由API的文档。
API | 说明 |
---|---|
wx.navigateBack | 关闭当前页面,返回上一页面或多级页面 |
wx.navigateTo | 保留当前页面,跳转到应用内的某个页面 |
wx.redirectTo | 关闭当前页面,跳转到应用内的某个页面 |
wx.reLaunch | 关闭所有页面,打开到应用内的某个页面 |
wx.switchTab | 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面 |
原来,open-type="redirect"
这段代码调用了wx.redirectTo
API,该API的作用是“关闭当前页面,跳转到应用内的某个页面”,我们的index.wxml
文件被关闭了,当然无法返回。
你也可以使用``组件转跳到其他小程序,很简单,使用下面的代码即可事项。
1 | <navigator target="miniProgram" open-type="navigate" app-id="" path="" extra-data="" version="release">打开绑定的小程序</navigator> |
值得注意的是,app-id=""
一定要填你绑定的微信小程序的appid
其他可以不填。从 2.4.0 版本开始,开发者提交新版小程序代码时,如使用了跳转其他小程序功能,则需要在代码配置中声明将要跳转的小程序名单,限定不超过 10 个,否则将无法通过审核。该名单可在发布新版时更新,不支持动态修改。配置方法详见 配置。调用此接口时,所跳转的 appId 必须在配置列表中,否则回调 fail appId "${appId}" is not in navigateToMiniProgramAppIdList
。
小程序还提供了一个functional-page-navigator
组件,用于跳转到插件功能页。插件需要调用接口,本文暂不涉及,暂不演示。
这篇教程中,我们介绍了小程序导航组件的使用,你学会了嘛?赶快多写几个页面进行尝试吧!后续我将会对其他组件做详细的介绍。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>这里就是微信提供的11个表单组件,接下来文章中,我们将以Hello World为例,对这11个组件进行介绍。
在表单组件中,最常用的可能就是button
组件了,我们先用代码熟悉下button
的操作。和以前一样,参考这篇教程,搭建好基本的运行环境,然后修改index.wxml
内容如下。
1 | <view class="btn-area" id="buttonContainer"> |
然后打开index.wxss
文件,写入下面的代码。
1 | button{ |
之后保存即可,你会看到batton
大部分组件演示,如图所示。
同样,button
组件也支持很多属性,这里我列出常用的属性,更多内容请参考官方文档。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
size | String | default | 按钮的大小 |
type | String | default | 按钮的样式类型 |
plain | Boolean | false | 按钮是否镂空,背景色透明 |
disabled | Boolean | false | 是否禁用 |
loading | Boolean | false | 名称前是否带 loading 图标 |
form-type | String | 用于 <form/> 组件,点击分别会触发 <form/> 组件的 submit/reset 事件 | |
hover-class | String | button-hover | 指定按钮按下去的样式类。当 hover-class="none" 时,没有点击态效果 |
hover-start-time | Number | 20 | 按住后多久出现点击态,单位毫秒 |
hover-stay-time | Number | 70 | 手指松开后点击态保留时间,单位毫秒 |
size 有效值:
值 | 说明 |
---|---|
default | 默认大小 |
mini | 小尺寸 |
type 有效值:
值 | 说明 |
---|---|
primary | 绿色 |
default | 白色 |
warn | 红色 |
form-type 有效值:
值 | 说明 |
---|---|
submit | 提交表单 |
reset | 重置表单 |
我们可以按照自己的需求设置相关按钮,比如我需要一个小尺寸红色手松开保留1秒的删除按钮,那么,参照上表,我可以这样写。
1 | <button class="mini-btn" type="warn" size="mini" hover-stay-time="1000">删除</button> |
button
组件使用起来就这么简单,大家可以按照自己的需求设置相关按钮哦~
开关组件很简单,直接上代码,编辑index.wxml
1 | <view class="body-view"> |
为了查看我们的按钮是否生效,大家可以打开index.js
,然后填入下面的代码。
1 | Page({ |
编辑并保存,你会在微信控制台看到下图的内容,按钮开启或关闭执行switch1Change
函数,控制台打印输出。
switch组件也支持若干属性,具体如下。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
checked | Boolean | false | 是否选中 |
disabled | Boolean | false | 是否禁用 |
type | String | switch | 样式,有效值:switch, checkbox |
bindchange | EventHandle | checked 改变时触发 change 事件,event.detail={ value:checked} | |
color | Color | switch 的颜色,同 css 的 color |
参考上表,我们可以设置一个默认选中的红色对勾开关按钮,具体代码为
1 | <switch bindchange="switch2Change" type='checkbox' color='red'/> |
大家可以根据自己的需求设置一个自己喜欢的按钮。
除了正常的开关量以外,有时候我们还需要用到模拟量,这时出现一个滑块可供选择,那便是极好的,小程序官方给我们提供了一个slider
组件来负责变量设置,让用过能够通过滑块调整某项数值。首先,我们先写代码,来体验下slider
组件。打开index.wxml
文件,填入下面的代码。
1 | <view class="section section_gap"> |
如图,我们可以自己设定你滑块内容
以下就是slider
所有属性
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
min | Number | 0 | 最小值 |
max | Number | 100 | 最大值 |
step | Number | 1 | 步长,取值必须大于 0,并且可被(max - min)整除 |
disabled | Boolean | false | 是否禁用 |
value | Number | 0 | 当前取值 |
activeColor | Color | #1aad19 | 已选择的颜色 |
backgroundColor | Color | #e9e9e9 | 背景条的颜色 |
block-size | Number | 28 | 滑块的大小,取值范围为 12 - 28 |
block-color | Color | #ffffff | 滑块的颜色 |
show-value | Boolean | false | 是否显示当前 value |
bindchange | EventHandle | 完成一次拖动后触发的事件,event.detail = {value: value} | |
bindchanging | EventHandle | 拖动过程中触发的事件,event.detail = {value: value} |
根据需求,我们可以行设置代码,比如我们需要设置一个背景为橙底,已选择颜色为红色,滑块为黄色,最小值500,最大值10000,步长为20,默认值为5000,并显示当前数值的滑块。那么我的代码可以这样写。
1 | <slider backgroundColor="#FF9900" activeColor="#FF0000" block-color="#FFFF33" min="500" max="10000" step="20" value="5000" show-value/> |
参考表格,大家会发现,其实撰写一个自己喜欢的按钮并不难,赶快去体验下吧。
小程序提供了选择器功能,用户可以通过按钮UI交互选择自己的选项。我们先尝试下面的代码。
1 | <radio-group> |
当然,单项选择器功能不只这些,我们先看看官方文档中的表格。
radio
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
value | String | <radio/> 标识。当该<radio/> 选中时,<radio-group/> 的 change 事件会携带<radio/> 的value | |
checked | Boolean | false | 当前是否选中 |
disabled | Boolean | false | 是否禁用 |
color | Color | radio的颜色,同css的color |
radio-group
单项选择器,内部由多个<radio/>
组成。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
bindchange | EventHandle | <radio-group/> 中的选中项发生变化时触发 change 事件,event.detail = {value: 选中项radio的value} |
可以看到,当<radio/>
有变化的时候,自动执行bindchange
属性指定的事件,同时返回valua携带的值。假设我们的需求为选项为红色,默认选中某个值,并且带标识返回valua值。那么代码可以这样写。首先在index.wxml
中填入下面的代码。
1 | <radio-group bindchange="radioChange"> |
然后打开index.js
文件,填入下面的代码。
1 | Page({ |
将需要的选项都写在js里面,通过for循环需显示,我们看到,当选项发生变化时,会自动执行函数radioChange()
打印当前选项。
怎么样,会使用radio
组件了嘛?我们继续向下学习多项选择器。
同样,微信也提供了多项选择器,有了单项选择器的经验,我们对上面的代码做简单的修改即可实现多项选择器。首先,我们修改index.wxml
文件如下。
1 | <checkbox-group bindchange="checkboxChange"> |
接下来修改index.js
文件。
1 | Page({ |
我们看到,通过不同的选项,checkboxChange()
函数会返回相关的值到控制台。
输入框也是小程序比较常用的功能,废话不多说,直接上代码,和以前一样我们先试试一个简单的demo,修改index.wxml
文件,为如下内容。
1 | <input placeholder="点我可以输入文本"/> |
这就是最简单的用法,当然,小程序官方为input
提供了很多属性,我们先看看。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
value | String | 输入框的初始内容 | |
type | String | “text” | input 的类型 |
password | Boolean | false | 是否是密码类型 |
placeholder | String | 输入框为空时占位符 | |
placeholder-style | String | 指定 placeholder 的样式 | |
placeholder-class | String | “input-placeholder” | 指定 placeholder 的样式类 |
disabled | Boolean | false | 是否禁用 |
maxlength | Number | 140 | 最大输入长度,设置为 -1 的时候不限制最大长度 |
cursor-spacing | Number / String | 0 | 指定光标与键盘的距离,单位px或rpx,默认为px。取 input 距离底部的距离和 cursor-spacing 指定的距离的最小值作为光标与键盘的距离 |
auto-focus | Boolean | false | (即将废弃,请直接使用 focus )自动聚焦,拉起键盘 |
focus | Boolean | false | 获取焦点 |
confirm-type | String | “done” | 设置键盘右下角按钮的文字,仅在type=’text’时生效 |
confirm-hold | Boolean | false | 点击键盘右下角按钮时是否保持键盘不收起 |
cursor | Number | 指定focus时的光标位置 | |
selection-start | Number | -1 | 光标起始位置,自动聚集时有效,需与selection-end搭配使用 |
selection-end | Number | -1 | 光标结束位置,自动聚集时有效,需与selection-start搭配使用 |
adjust-position | Boolean | true | 键盘弹起时,是否自动上推页面 |
bindinput | EventHandle | 键盘输入时触发,event.detail = {value, cursor, keyCode},keyCode 为键值,2.1.0 起支持,处理函数可以直接 return 一个字符串,将替换输入框的内容。 | |
bindfocus | EventHandle | 输入框聚焦时触发,event.detail = { value, height },height 为键盘高度,在基础库 1.9.90 起支持 | |
bindblur | EventHandle | 输入框失去焦点时触发,event.detail = {value: value} | |
bindconfirm | EventHandle | 点击完成按钮时触发,event.detail = {value: value} |
type 有效值
值 | 说明 |
---|---|
text | 文本输入键盘 |
number | 数字输入键盘 |
idcard | 身份证输入键盘 |
digit | 带小数点的数字键盘 |
confirm-type 有效值
值 | 说明 |
---|---|
send | 右下角按钮为“发送” |
search | 右下角按钮为“搜索” |
next | 右下角按钮为“下一个” |
go | 右下角按钮为“前往” |
done | 右下角按钮为“完成” |
通过官方提供的属性,我们可以实现自己想要的一些功能。比如我想获取当前用户输入的返回内容,那么可以使用下面的代码。
index.wxml
1 | <view class="weui-cells__title">实时获取输入值:{{inputValue}}</view> |
index.js
1 | bindKeyInput(e) { |
当用户输入内容的时候,自动调用bindKeyInput()
函数返回当前的内容。
又比如你想设置一个密码是输入框,并且输入密码的时候,优先弹出的是数字键盘,那么可以使用下面的代码。
1 | <view class="weui-cells__title">密码输入的input</view> |
某些情况下,单行输入框不能满足我们的要求,这就需要多行文本框,官方也提供了多行文本框的组件,我们先看代码。在index.wxml
文件中写入下面的代码。
1 | <view class="page-body"> |
如图,在第一个输入框中,我们输入内容后系统会自适应文本内容。第二个点击之后,系统会自动聚焦到输入框,并弹出输入法,我们来看看具体的属性内容。
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
value | String | 输入框的内容 | |
placeholder | String | 输入框为空时占位符 | |
placeholder-style | String | 指定 placeholder 的样式 | |
placeholder-class | String | textarea-placeholder | 指定 placeholder 的样式类 |
disabled | Boolean | false | 是否禁用 |
maxlength | Number | 140 | 最大输入长度,设置为 -1 的时候不限制最大长度 |
auto-focus | Boolean | false | 自动聚焦,拉起键盘。 |
focus | Boolean | false | 获取焦点 |
auto-height | Boolean | false | 是否自动增高,设置auto-height时,style.height不生效 |
fixed | Boolean | false | 如果 textarea 是在一个 position:fixed 的区域,需要显示指定属性 fixed 为 true |
cursor-spacing | Number / String | 0 | 指定光标与键盘的距离,单位px或rpx,默认为px。取 textarea 距离底部的距离和 cursor-spacing 指定的距离的最小值作为光标与键盘的距离 |
cursor | Number | 指定focus时的光标位置 | |
show-confirm-bar | Boolean | true | 是否显示键盘上方带有”完成“按钮那一栏 |
selection-start | Number | -1 | 光标起始位置,自动聚集时有效,需与selection-end搭配使用 |
selection-end | Number | -1 | 光标结束位置,自动聚集时有效,需与selection-start搭配使用 |
adjust-position | Boolean | true | 键盘弹起时,是否自动上推页面 |
bindfocus | EventHandle | 输入框聚焦时触发,event.detail = { value, height },height 为键盘高度,在基础库 1.9.90 起支持 | |
bindblur | EventHandle | 输入框失去焦点时触发,event.detail = {value, cursor} | |
bindlinechange | EventHandle | 输入框行数变化时调用,event.detail = {height: 0, heightRpx: 0, lineCount: 0} | |
bindinput | EventHandle | 当键盘输入时,触发 input 事件,event.detail = {value, cursor},bindinput 处理函数的返回值并不会反映到 textarea 上 | |
bindconfirm | EventHandle | 点击完成时, 触发 confirm 事件,event.detail = {value: value} |
这里的属性和input
很相似,大家可以通过表中内容自行定制需求去修改。
除了单项选择器和多项选择器,小程序还给我们提供了一种比较符合交互的选择器,就是滚动选择器,我们先看看从系统弹出的滚动选择器。修改index.wxml
文件为下列的代码。
1 | <view class="section"> |
接下来,修改index.js
文件,为下列的代码。
1 | Page({ |
我们看看效果
在图中,可以看出,系统已经给出我们需要选择的内容,我们可以在表中修改。
从底部弹起的滚动选择器,现支持五种选择器,通过mode来区分,分别是普通选择器,多列选择器,时间选择器,日期选择器,省市区选择器,默认是普通选择器。因为不同的模式内容较多,我这里就不一一列出,感兴趣的同学可以去这里查看。我这里只演示时间选择器的使用。
时间选择器:mode = time
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
value | String | 表示选中的时间,格式为”hh:mm” | |
start | String | 表示有效时间范围的开始,字符串格式为”hh:mm” | |
end | String | 表示有效时间范围的结束,字符串格式为”hh:mm” | |
bindchange | EventHandle | value 改变时触发 change 事件,event.detail = {value: value} | |
bindcancel | EventHandle | 取消选择时触发 | |
disabled | Boolean | false | 是否禁用 |
你可以使用下面的代码来实现时间选择器的使用,在index.wxml
中写入下面的内容
1 | <picker mode="time" value="{{time}}" start="09:01" end="21:01" bindchange="bindTimeChange"> |
在index.js
中写入下面的内容
1 | Page({ |
配合表格,我们可以看出,picker
中,我们设置当前选中的时间为,就是你选中的时间。同时,我们设置了时间的有效范围,从早上09:01到晚上的21:01,当我们设置完成,触发bindTimeChange
函数,改变选择的时间。
除了上面的页面弹出滚动器,小程序官方还提供了嵌入页面的滚动选择器,这里的选择器不像弹出选择器,提供了一堆模式,在嵌入页面的选择器,我们只能自己撰写逻辑去处理相关数据。比如时间选择器,我们可以这样写,首先,修改index.wxml
文件。
1 | <view> |
接下来,我们写逻辑部分。
1 | const date = new Date() |
通过这样的写法,我们就可以写出嵌入在页面的滚动选择器,如图。
嵌入在页面的选择器与从底部弹出的选择器有些不同,因为没有了mode
我们只能自己去写相关内容。
属性名 | 类型 | 说明 |
---|---|---|
value | NumberArray | 数组中的数字依次表示 picker-view 内的 picker-view-column 选择的第几项(下标从 0 开始),数字大于 picker-view-column 可选项长度时,选择最后一项。 |
indicator-style | String | 设置选择器中间选中框的样式 |
indicator-class | String | 设置选择器中间选中框的类名 |
mask-style | String | 设置蒙层的样式 |
mask-class | String | 设置蒙层的类名 |
bindchange | EventHandle | 当滚动选择,value 改变时触发 change 事件,event.detail = {value: value};value为数组,表示 picker-view 内的 picker-view-column 当前选择的是第几项(下标从 0 开始) |
bindpickstart | EventHandle | 当滚动选择开始时候触发事件 |
bindpickend | EventHandle | 当滚动选择结束时候触发事件 |
功能与picker
组件相同,本文暂不在赘述。
使用过HTML语法的同学,肯定都知道label
组件,该组件可以优化用户选择,增加用户体验。怎么个优化法呢?我们先看看代码,修改index.wxml
文件。
1 | <view> |
在页面中,尝试点击选项一
和选项二
的文本,看看有什么区别。你会发现带label
的标签,点击文本即可自动点击选项,而无label
的标签,点击文字则无任何反应。这就是label的优势,你可以在复杂的表格中利用label优化用户选择。
form表单组件是所有表单组件中最重要的组件,没有form表单组件,上述的所有组件都不能提交数据到服务器或者小程序后端。为了快速体验是怎么一回事,我们先写一个简单的代码。
1 | <form bindsubmit="formSubmit"> |
然后在index.js
文件中,增加下面的代码。
1 | formSubmit: function (e) { |
保存后,我们点击Submit
按钮,你会看到系统提示已经提交了当前的数据。
当然,我们可以提交多个数据,在提交之前,我们先看看官方的文档。
属性名 | 类型 | 说明 |
---|---|---|
report-submit | Boolean | 是否返回 formId 用于发送模板消息 |
bindsubmit | EventHandle | 携带 form 中的数据触发 submit 事件,event.detail = {value : {‘name’: ‘value’} , formId: ‘’} |
bindreset | EventHandle | 表单重置时会触发 reset 事件 |
表单,将组件内的用户输入的<switch/>
<input/>
<checkbox/>
<slider/>
<radio/>
<picker/>
提交。
当点击 <form/>
表单中 formType 为 submit 的 <button/>
组件时,会将表单组件中的 value 值进行提交,需要在表单组件中加上 name 来作为 key。
我们甚至可以多提交一些内容,修改代码为下面的内容,看看效果。
1 | <form bindsubmit="formSubmit" bindreset="formReset"> |
提交信息变更为
1 | form发生了submit事件,携带数据为: {slider: 37, text: "文本123"} |
我们看到系统日志已经返回了我们提交的值。
通过表单组件,你就可以写一个用户注册或用户登录,问卷系统等功能的页面了,后续我将会对其他组件做详细的介绍。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!
]]>