微信小程序开发-倾听天气(二)

我的微信小程序,倾听天气终于更新了0.2.1版本了,这个版本页面效果要比第一版的好很多了,主要的原因在于我申请的和风天气开发者权限通过了,所以获得更多的数据。比如24小时内间隔2小时的天气数据,最近7天的天气数据。

因此我的小程序所展示的数据可以更加详细。此外,我又在iconfont.cn搜集了一些icon来优化小程序的展示,并给逐小时天气预报做了一个折线图。下面我就以这几点来整理一下小程序的开发。

申请过程

这里就简单说一下申请的过程:和风天气的认证个人开发者很简单。只要申请的时候实名并提供自己的作品中使用了和风天气的api即可。我是在完成了倾听天气的第一版之后申请中,中间还给他们发了一封邮件,因为申请的信息要求的作品选项没有包括微信小程序,所以我发了邮件去咨询了一下。很快就回复了我微信小程序可以申请。所以我在申请的时候直接在作品一栏写明是微信小程序倾听天气。虽然那天刚好申请后隔天是周末,但到了周日就来邮件说申请通过了,周末都处理申请,好厉害的样子…

之后我在我的小程序中就发现原来3天的天气预报数据变成7天了,说明api的权限已经开好了。

开发总结

这里整理一下在0.2.1版本中涉及到的一些开发总结。主要分微信小程序滚动组件,iconfront引入及canvas绘制折线图。

滚动组件scroll-view

之前整个小程序中都没有用到这个组件是因为没有太多的数据需要做这样的显示。不过当原来3天的天气预报数据变成7天之后,在屏幕上横着显示7天的数据就比较拥挤了,所以这个时候就需要用到滚动组件scroll-view了。

scroll-view用起来不难,首先需要有一个父级组件包住scroll-view,然后通过scroll-xscroll-y来控制滚动的方向。最后,如果是垂直方向的滚动需要给scroll-view增加一个高度的样式,而如果是水平方向的话,给父级标签增加一个固定宽度就可以了。

我这是因为是要水平方向展示7天的天气预报数据,所以我给组件scroll-view一个父级组件,固定width为100%,然后给组件scroll-view一个类,这里使用flex布局,让内部的子组件都并排在一行内,并固定宽度。这样的基本完成了水平滚动的实现了:

1
2
3
4
5
6
7
8
9
10
11
12
13
<view class='forecast-wrapper' wx:if="forecast.daily_forecast">
<scroll-view scroll-x enable-flex class='scroll-view-x'>
<view
wx:for="{{ forecast.daily_forecast }}"
wx:for-index="index"
wx:for-item="item"
wx:key="item.date"
class='forecast-item'
>
<!-- -->
</view>
</scroll-view>
</view>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.forecast-wrapper {
width: 100%;
overflow: hidden;
// ...
}

.scroll-view-x {
// display: flex;
width: auto;
white-space: nowrap;
// flex-wrap: nowrap 测试无效
}

.forecast-item {
display: inline-block;
width: 20%;
}

scroll-view组件的enable-flex属性相当于直接设置flex布局。还有很多属性可以设置,比如scroll-into-view滚动到某一子节点,enable-back-to-top支持垂直方向滚动的点击屏幕顶部后滚动条返回顶部,等等。具体可以去读官网文档。

iconfont引入

其实iconfont的引入本应没什么可以说的,但是鉴于微信小程序中写样式的文件叫wxss文件,我们平时写的样式文件是css,所以还是有点不一样的。

网上找到的解决方案一般都是先下载icon文件,然后把.ttf文件转码base64格式,然后再放到对应的wxss文件中,最后再引用。

但是我嫌这种方案比较复杂,而且需要下载icon文件存放在目录下也可能需要费些空间(我的项目还好,只是想找懒)。都知道微信小程序是有限项目大小的,所以有没有更好的方案。

有,很简单,就是通过iconfont直接生成unicode,把unicode复制放到wxss文件中,再下载icon文件,把icon的css样式在复制放到wxss文件中(我是直接放到app.wxss中,暂时先这样处理),然后就可以快速的使用了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**iconfont online**/
@font-face {
font-family: 'iconfont'; /* project id 1265794 */
src: url('//at.alicdn.com/t/font_1265794_rsipcjqri8.eot');
src: url('//at.alicdn.com/t/font_1265794_rsipcjqri8.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_1265794_rsipcjqri8.woff2') format('woff2'),
url('//at.alicdn.com/t/font_1265794_rsipcjqri8.woff') format('woff'),
url('//at.alicdn.com/t/font_1265794_rsipcjqri8.ttf') format('truetype'),
url('//at.alicdn.com/t/font_1265794_rsipcjqri8.svg#iconfont') format('svg');
}

/**iconfont.css**/
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

这样就不需要把icon文件都放到项目中了。

目前项目中已经大面积的使用icon显示一些信息了,比如天气状态,生活指数,一些常用的功能icon。看起来要比原来纯文字的效果要好很多。

canvas绘制

canvas绘制应该是这一版本中最难的部分。原本想引入ECharts微信小程序版来实现24小时温度折线图的,但是因为没有用过,一下子使用有难度,再者最近看到不少canvas绘制图表的博文,所以想自己试试,所以最后选择了canvas绘制。

其实canvas绘制不难,它的操作逻辑就是在页面上建立一张画布,然后用坐标标识绘制的关键点,最后把方法当成指令这样使用就可以了,剩下就是想画好看点就用一些。

首先还是要对数据做处理。绘制一个24小时逐小时温度折线图需要确定要画布的宽跟高,这样才能确定最高温度跟最低温度的y轴值,最近时间温度跟最远时间温度的x轴值;然后找到所有温度数据中的最大值刚跟最小值,可以确定每个温度阶的间隔值,最后再计算每个时间温度对应的坐标。

这里我使用wx.getSystemInfo来获得屏幕的宽度,然后动态的计算画布的宽度跟高度(宽度为屏幕宽度,高度为宽度的1/5)。再用getTmps方法获得温度数据的数组跟最高最低温度值。最后用getCoordinate方法计算获得所有的坐标,最后在drawHourly方法中绘制。

微信小程序中canvas的绘制跟H5中有一点区别,但逻辑是一样的。首先要创建一个content,然后根据折线图的需要绘制线,绘制圆,绘制最大温度跟最小温度标识,最后把content绑定到页面上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
drawHourly(arr, maxCoo, minCoo, maxTmp, minTmp) {
var context = wx.createContext();
context.draw(); // 清空
context.setStrokeStyle("#fff");
context.setLineWidth(1);
context.moveTo(arr[0].x, arr[0].y);
for (let i = 1; i < arr.length; i++) {
context.lineTo(arr[i].x, arr[i].y);
}
context.stroke();

for (let i = 0; i < arr.length; i++) {
// 设置描边颜色
context.setStrokeStyle("#ffffff");
context.moveTo(arr[i].x, arr[i].y);
context.arc(arr[i].x, arr[i].y, 2, 0, 2 * Math.PI, false);
context.closePath();
// 填充路径
// context.fill();
context.stroke();
}

context.setFontSize(10);
context.setFillStyle("#fff");
context.fillText(`${maxTmp}℃`, maxCoo.x - 10, maxCoo.y + 5);
context.fillText(`${minTmp}℃`, minCoo.x - 10, minCoo.y + 5);

wx.drawCanvas({
canvasId: 'hourlyCanvas',
actions: context.getActions()
});
}

这个绘制也是比较简单,也没有做效果更好的平滑曲线,达到效果就可以了。

以上就是新版本倾听天气小程序开发的整理。接下来会做新的优化,具体会在下一个版本出来后再整理。