目录
小程序开发学习笔记
今年以试试手的心态报了小程序开发赛,对这方面没什么经验,边学边做,用这个系列记录一下开发中的一些内容。
一、一些问题
1.安装相关
(1).从微信开发者网站下载开发者工具,可以申请一个测试号,如果要申请正式ID没及时点邮箱/不小心退出去了,需要返回主页用邮箱密码登录,如果直接用手机扫码可能登不上或显示已经被注册过。
(2).参赛要求使用正式的AppID发布,因此要注意申请一下正式的ID,如果要用云开发功能的模板也需要正式ID。
(3).这次开发用到了nodejs,装了下环境,注意先安装nodejs,在环境变量Path中添加nodejs文件夹的路径,在小程序中新建一个终端,输入npm初始化语句进行初始化,可以事先在小程序根目录添加package.json,添加要安装的modules。
$ npm init -y #初始化
$ npm install xxx #安装
添加后,会在项目根目录生成node_modules文件夹,接着使用开发者工具-工具-构建npm来进行项目内构建。
(4).使用tsfl.js上线模型,安装TensorFlow.js,这是一个非常方便的基于JavaScript的机器学习模型训练库。这里也是使用了npm安装,注意对应的版本号以及相应的小程序基础库版本。安装后直接import即可。
2.引用Dom | 构造ImageData
由于小程序的线程特点,无法直接使用 document.getElementByXX 如是的语句,如果一定要使用,根据开发文档,应该写为:
handleInfo(){
const that = this;
var query = wx.createSelectorQuery(); //创建选择器
query.select('.kd').boundingClientRect();
query.exec(function (res) {
//返回一个含有指定标签信息的数组,可以对指向的元素含有的信息进行操作
that.setData({
data:res[0].height
})
});
},
在TensorFlow.js中有一个fromPixels()的函数,用于创建指定图像的像素张量,需要一个四维四通道的Tensor图像数据,以及输出的通道数,默认为4。
const tensorImg = tf.browser.fromPixels(input, num);
项目中用到了这部分代码,但input这一块卡了很久,因为第一个参数按照要求,必须是HTMLVideoElement、HTMLImageElement、HTMLCanvasElement、browser中的ImageData或OffscreenCanvas。当时的设想是直接在前端写好识别的逻辑,通过chooseImage()获取到上传的图片后,直接对返回的临时图片进行识别,但这一个参数无法通过url来直接读取图片信息,试过readFile()、把图片转成Base64读取信息、新建Image对象、通过Img元素获取(HTMLImageElement 一般支持<img>而不是<image>,前者src不能使用绝对路径,但由于获取到的临时图片是绝对路径,因而无法使用),这些方法多少都有些欠缺。后来想到了将图片转换为 canvas ,wxml设置canvas-id,初始化页面创建canvas,通过 canvas 调用 canvasGetImageData()。
const dt = wx.canvasGetImageData();
在canvasGetImageData返回的信息中构建一组数据:新建Uint8Array类型化图片数据、画布长宽,之后便可以调用tidy()、fromPixels()、slice() 对图像数据进行处理。
wx.canvasGetImageData({
canvasId: 'canvas',
height: 640,
width: 640,
x: 0,
y: 0,
success: async res=>{
const imgData = {
data: new Uint8Array(res.data),
width: res.width,
height: res.height
};
});
3.使用异步函数加载模型
因为是在前端本地跑模型,有的模型可能非常大,加载模型的时间过长,等待加载的时间相当浪费,使用异步函数 (async) 和 异步方法 (await),await等待async,暂停执行异步函数后面的代码,让出 JS 运行时的执行线程,搭配使用可以不影响页面正常加载而运行,提高程序的效率。
如果有返回值,这个返回值被 Promise.resolve() 包装成一个 Promise 对象,async 始终返回 Promise 对象。在函数外部调用这个函数可以得到它返回的 Promise。
async loadModel(){
await net.load({
//模型参数设置
...
}).then(model => { //有返回值返回一个 Promise 对象,没有则是undefined
console.log("加载完成!");
}).catch(e => {
console.log("加载失败!");
})
...
};
4.canvas 函数
(1).draw函数
使用canvas 绘制时,用到了 canvas.draw() 函数, 该函数表示本次绘制是否接着上一次绘制。即 reserve 参数为 false,则在本次调用绘制之前 native 层会先清空画布再继续绘制;若 reserve 参数为 true,则保留当前画布上的内容,本次调用 drawCanvas 绘制的内容覆盖在上面,默认 false。 第二个参数为一个回调函数,回调函数保证了canvas在清空之前执行逻辑。
draw(
reserve?: boolean,
/** 绘制完成后执行的回调函数 */
callback?: (...args: any[]) => any
): void
回调函数:将函数作为参数传到另一个主函数里,当该主函数执行后,再执行参数函数。回调函数可以是一个匿名函数。
//延时/计时器函数回调
setTimeOut(function () {
...
},1000);
//dom函数回调
document.getElementById("clear").onclick = function() {
...
};
//POST ajax 函数回调
var x = $("input").val();
$.post("index.html",{valu:x}, function(res){
... //传递val = x
});
(2).drawImage函数
该函数可以用wx.chooseImage 获取到图像后用 wx.getImageInfo 得到图像资源信息后调用。
imageResource | 将要绘制的图像资源 getImageInfo / downloadFile 下载网络资源 |
sx,sy | imageResource的矩形选择框的左上角 x、y坐标 |
sW,sH | imageResource的矩形选择框的宽度、高度 |
dx,dy | imageResource的左上角在目标 canvas 上 x、y轴的位置 |
dW,dH | canvas 上 绘制imageResource的宽度、高度,允许对绘制的imageResource进行缩放,canvas 的输出宽度、高度 |
drawImage(imageResource: string,
sx: number,sy: number,
sW: number,sH: number,
dx: number,dy: number,
dW: number,dH: number
): void
5.Mock
当时开发的小程序项目基本上集中于前端开发,为了模拟从后端获取数据的效果,采用了mock。先使用 npm 安装 mock.js ,可以使用 --save-dev 来启用并存入 package.json,保留模块信息。
$ npm install mockjs
在app.js中加入 require(../mockjs) 调用。然后在开发者工具调试器中找到Mock,根据需求调整Mock的配置,之后执行下面的代码得到返回的数据。其他参数参考官方文档 API Mock | 微信开放文档 (qq.com)。
wx.request({
url: 'https://xxxx.com/ajax?dataType=member',
dataType: 'json',
success(res) {
console.log(res)
}
})