天气趋势 A

介绍

日常生活中,气象数据对于人们的生活具有非常重要的意义,数据的表现形式多种多样,使用图表进行展示使数据在呈现上更加直观。

本题请实现一个 Y 城 2022 年的天气趋势图。

准备

开始答题前,需要先打开本题的项目代码文件夹,目录结构如下:

1
2
3
4
5
6
7
8
9
10
├── css
│ └── style.css
├── effect-1.gif
├── effect-2.gif
├── index.html
└── js
├── axios.js
├── echarts.min.js
├── vue.min.js
└── weather.json

其中:

  • css/style.css 是样式文件。
  • index.html 是主页面。
  • js/axios.js 是 axios 文件。
  • js/vue.min.js 是 vue2.x 文件。
  • js/echarts.min.js 是 echarts 文件。
  • js/weather.json 是请求需要用到的天气数据。
  • effect-1.gif 是当月和未来七天切换的效果图。
  • effect-2.gif 是最终完成的效果图。

注意:打开环境后发现缺少项目代码,请手动键入下述命令进行下载:

1
2
cd /home/project
wget https://labfile.oss.aliyuncs.com/courses/9788/08.zip && unzip 08.zip && rm 08.zip

在浏览器中预览 index.html 页面效果如下:

初始效果

目标

请在 index.html 文件中补全代码,具体需求如下:

  1. 完成数据请求(数据来源 ./js/weather.json),weather.json 中存放的数据为 12 个月对应的温度数据。在项目目录下已经提供了 axios,考生可自行选择是否使用。注意:调试完成后请将请求地址写死为 ./js/weather.json
  2. data 中的月份数据 monthList, 在 class=month 标签下面的 li 上完成渲染,点击月份则切换对应月份的温度数据同时被点击的月份会变成激活状态(.active 类),x 轴为日期,y 轴为温度,默认显示 1 月份数据。

目标2示例图

  1. 如果点击的月份是当天(通过时间函数动态获取的时间)所在月份,本月和未来七天切换的 tab (即 id=currentMonth 元素)显示,其他月份 currentMonth 元素不显示。
  • 默认显示本月数据。
  • 点击本月显示当月数据,点击未来七天显示从当天(包含当天)开始未来七天的数据,当显示未来七天数据时 x 轴需要显示为月/日格式。
  • 点击 tab本月未来七天会切换激活状态(.active)。

以当天为 5 月 29 号为例,未来七天 x 轴显示示例(即 x 轴显示成:5/29,5/30,5/31,6/1,6/2,6/3,6/4):

目标3示例图

本月未来七天 切换效果见文件夹下 effect-1.gif

最终效果见文件夹下面的 gif 图,图片名称为 effect-2.gif(提示:可以通过 VS Code 或者浏览器预览 gif 图片)

规定

  • 请求地址为./js/weather.json,切勿写成其他地址格式,以免造成无法判题通过。
  • 请严格按照考试步骤操作,切勿修改考试默认提供项目中的文件名称、文件夹路径、class 名、id 名、图片名等,以免造成无法判题通过。

判分标准

  • 完成目标 1,得 5 分。
  • 完成目标 2,得 5 分。
  • 完成目标 3,得 10 分。

题解

这题我把火星子都搓出来了,下面代码业务是实现的,不过逻辑可能有可以优化的地方。让我学习一下视频讲解
视频讲解

题解的函数调用更为合理,对日期的判断使用内置函数来判断,可以不用手动写函数,推迟一天。然后忘了一点v-for遍历对象用三个属性:(val, key, index) in Object.

1
2
3
4
5
6
7
8
for(let i = 0; i < 7; i++) {
let now = new Date()
now.setTime(now.getTime() + 1000 * 60 * 60 * 24 * i)
newX.push(`${now.getMonth() + 1}/${now.getDate()}`)
newY.push(this.list[now.getMonth()][now.getDate() - 1])
}
[this.xData, this.yData] = [newX, newY]
this.initChart
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>天气趋势</title>
<meta
name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"
/>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<script src="./js/axios.js"></script>
<script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
<script
src="js/echarts.min.js"
type="text/javascript"
charset="utf-8"
></script>
</head>

<body>
<div id="app">
<div class="top-bar">2022年 Y 城全年温度统计图</div>
<!-- 主体 -->
<div class="container">
<!-- 月份 -->
<div class="month">
<ul>
<!-- TODO:待补充代码 在下面的 li 标签中完成 12个月份 (即 monthList) 的渲染 -->
<li :class="value === showMonth ? 'active' : ''" v-for="(value, key) in monthList" @click="changeMonth(value)">{{ value }}</li>
</ul>
</div>
<div class="chart">
<!-- TODO:待补充代码 -->
<!-- currentMonth 未来七天和本月 tab 切换,只有当前月才显示 -->
<div id="currentMonth" v-if="showIndex === new Date().getMonth() + 1">
<div class="title">
<h3>{{!isCurentMonth ? '未来7天天气' : '本月天气'}}</h3>
<div class="type">
<span id="seven" :class="!isCurentMonth ? 'active' : ''" @click="changeSeven(true)">未来7天</span>
<span id="current" :class="isCurentMonth ? 'active' : ''" @click="changeSeven(false)">本月</span>
</div>
</div>
</div>
<div id="chart"></div>
</div>
</div>
</div>
</body>
</html>
<script>
// TODO:待补充代码
var vm = new Vue({
el: "#app",
data: {
chart: null, // 图表
chartOptions: null, // 图表配置项
typeTitle: "本月天气",
monthList: {
January: "1月",
February: "2月",
March: "3月",
April: "4月",
May: "5月",
June: "6月",
July: "7月",
August: "8月",
September: "9月",
October: "10月",
November: "11月",
December: "12月",
},
list: [],
// showMonth: (new Date().getMonth() + 1).toString() + '月',
// showIndex: new Date().getMonth() + 1,
showIndex: 1,
showMonth: '1月',
isCurentMonth: true,
sevenXaixs: [],
sevenData: []
},
mounted: function () {
// 先进行axios请求,然后初始化 echarts
axios.get('./js/weather.json').then(res => {
this.list = res.data.map(item => {
return Object.values(item)[0]
})
this.$nextTick(() => {
this.initChart();
})
})

},
methods: {
initChart() {
// 初始化图表
this.chart = echarts.init(document.getElementById("chart"));
// 配置项
this.chartOptions = {
grid: {
top: 35,
bottom: 5,
left: 10,
right: 10,
containLabel: true,
},
tooltip: {
trigger: "axis",
axisPointer: {
lineStyle: {
color: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "rgba(255,255,255,0)",
},
{
offset: 0.5,
color: "rgba(255,255,255,1)",
},
{
offset: 1,
color: "rgba(255,255,255,0)",
},
],
global: false,
},
},
},
},
xAxis: [
{
type: "category",
boundaryGap: false,
axisLabel: {
formatter: "{value}",
fontSize: 12,
margin: 20,
textStyle: {
color: "#bfbfbf",
},
},
axisLine: {
lineStyle: {
color: "#e9e9e9",
},
},
splitLine: {
show: true,
lineStyle: {
color: "#f7f7f7",
},
},
axisTick: {
show: false,
},
// x 轴显示的数据,日期
data: !this.isCurentMonth ? this.sevenXaixs : [
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,
],
},
],
yAxis: [
{
boundaryGap: false,
type: "value",
axisLabel: {
textStyle: {
color: "#bfbfbf",
},
formatter: `{value}\u2103`,
},
nameTextStyle: {
color: "#fff",
fontSize: 12,
lineHeight: 40,
},
splitLine: {
lineStyle: {
color: "#f7f7f7",
},
},
axisLine: {
show: true,
lineStyle: {
color: "#e9e9e9",
},
},
axisTick: {
show: false,
},
},
],
series: [
{
name: "天气",
type: "line",
smooth: false,
showSymbol: false,
symbolSize: 0,
zlevel: 3,
itemStyle: {
color: "#ff6600",
borderColor: "#a3c8d8",
},
lineStyle: {
normal: {
width: 3,
color: "#ff6600",
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: "#ff6600",
},
{
offset: 0.8,
color: "#ff9900",
},
],
false
),
},
},
// Y 轴显示的数据,即温度数据
data: !this.isCurentMonth ? this.sevenData : this.list[this.showIndex - 1],
},
],
};

// 调用此方法设置 echarts 数据
this.chart.setOption(this.chartOptions);
},
changeMonth(value) {
this.showMonth = value
let charArr = value.split('')
charArr.pop()
this.showIndex = parseInt(charArr.join(''))
this.isCurentMonth = true
this.$nextTick(() => {
this.initChart();
})
},
changeSeven(flag) {
this.isCurentMonth = !flag
// 处理七天数据和七天轴
if (this.isCurentMonth === false) {
let sevenData = []
let sevenXaixs = []
let count = 0
let month = new Date().getMonth() + 1
let date = new Date().getDate()
for(let i = date; i < this.list[month - 1].length; i++) {
sevenData.push(this.list[month - 1][i - 1])
sevenXaixs.push(month.toString() + '/' + i.toString())
}
console.log(sevenData);
console.log(sevenXaixs);
if (sevenData.length > 7) {
sevenData = sevenData.splice(0,7)
sevenXaixs = sevenXaixs.splice(0, 7)
} else {
while (sevenData.length < 7) {
sevenData.push(this.list[month][count++])
sevenXaixs.push((month + 1).toString() + '/' + count.toString())
}
}
this.sevenXaixs = sevenXaixs
this.sevenData = sevenData
console.log(sevenData);
console.log(sevenXaixs);


}
this.$nextTick(() => {
this.initChart();

})
}
},
});
</script>