你可曾思索,为何天气预报员总能在风雷雨雪间笃定自若,仿若洞悉天机?如今,轮到你了!借助 ECharts,绘制一幅玄妙的七日天象图,分分钟登上掘金,化身掌控风云的“气象秘师”。
且看下图!
不吹牛逼了, 其实就是一个echart图表(狗头保命)
功能介绍
- 每日日期。
- 风力等级。
- 白天的天气图标。
- 每日的最高气温和最低气温。
开搞!用代码说话
以下是项目的核心代码逻辑分解:
<template>
<div class="three-echart-height">
<Echart :options="waterOptions" />
</div>
</template>
具体echart组件自行封装就行
使用的是和风天气免费api获取数据
methods: {
async getWeather() {
const key = 'YOUR_API_KEY';
const location = '根据需要填写';
try {
const res = await axios.get('https://geoapi.qweather.com/v2/city/lookup?', { params: { key, location } });
if (res.data.code === '200') {
const locationId = res.data.location[0].id;
const weatherData = await this.fetchWeatherData(locationId, key);
this.processDailyWeather(weatherData.daily);
}
} catch (error) {
console.error('Error', error);
}
}
}
更新数据
processDailyWeather(dailyData) {
this.dateList = dailyData.map(item => item.fxDate.slice(5));
this.tempMaxs = dailyData.map(item => item.tempMax);
this.tempMins = dailyData.map(item => item.tempMin);
this.iconDays = dailyData.map(item => item.iconDay);
this.waterOptions.xAxis[0].data = this.dateList;
this.waterOptions.series[0].data = this.tempMaxs;
this.waterOptions.series[1].data = this.tempMins;
}
添加天气图标, 需要提前下载好和风天气的icon图标,我这里是ui设计师重新设计的新图标
updateIconLabels() {
this.iconDays.forEach(val => {
this.waterOptions.xAxis[1].axisLabel.rich[val] = {
backgroundColor: {
image: require(`@/assets/qwIcons/${val}-fill.svg`)
},
height: 30,
width: 30
};
});
}
以下是options配置项
export const waterOptions = {
grid: {
show: true,
backgroundColor: 'transparent',
opacity: 0.3,
borderWidth: '0',
top: '130',
bottom: '50'
},
tooltip: {
trigger: 'axis'
},
legend: {
show: false
},
xAxis: [
// 日期
{
type: 'category',
boundaryGap: false,
position: 'top',
offset: 90,
zlevel: 100,
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
formatter: [
'{a|{value}}'
].join('\n'),
rich: {
a: {
color: 'white',
fontSize: 14,
}
}
},
nameTextStyle: {
},
data: ["8/25","8/26","8/27","8/28","8/29","8/30","8/31"]
},
// 天气图标
{
type: 'category',
boundaryGap: false,
position: 'top',
offset: 30,
zlevel: 100,
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
formatter: function(value, index) {
return `{${value}|}`;
},
rich: {
0: {
backgroundColor: {
image: 'https://xxx.png'
},
height: 40,
width: 40
},
b: {
color: 'white',
fontSize: 12,
lineHeight: 30,
height: 20
}
}
},
nameTextStyle: {
fontWeight: 'bold',
fontSize: 19
},
data: ["小雨","小雨","阴","小雨","多云","小雨","小雨"]
},
// 风级
{
type: 'category',
boundaryGap: false,
position: 'bottom',
offset: 18,
zlevel: 100,
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
interval: 0,
formatter: function (value) {
return `{b|}` + `{value|${value}级}`;
},
rich: {
b: {
backgroundColor: {
image: require('@/assets/images/windLevel.png')
},
height: 12,
width: 12
},
value: {
color: '#fff',
fontSize: 12,
},
}
},
data: ["<3",">3","1","2","3","4","1"]
}
],
yAxis: {
type: 'value',
show: false,
axisLabel: {
formatter: '{value} °C',
color: 'white',
},
axisLine: {
show: true
},
},
series: [
{
name: '最高气温',
type: 'line',
data: ["16.3","16.2","20.6","14.2","17.6","15.7","14.3"],
symbol: 'emptyCircle',
symbolSize: 6,
showSymbol: true,
smooth: true,
itemStyle: {
normal: {
color: '#F38200'
}
},
label: {
show: true,
position: 'top',
color: 'white',
fontSize: 14,
formatter: '{c} °C'
},
lineStyle: {
width: 1,
// color: 'white'
},
areaStyle: {
opacity: 1,
color: 'transparent'
}
},
{
name: '最低气温',
type: 'line',
data: ["0","-2","-5","12.5","12.4","13.2","13"],
symbol: 'emptyCircle',
symbolSize: 6,
showSymbol: true,
smooth: true,
itemStyle: {
normal: {
color: '#178FFF'
}
},
label: {
show: true,
position: 'bottom',
color: 'white',
fontSize: 14,
formatter: '{c} °C'
},
lineStyle: {
width: 1,
},
areaStyle: {
opacity: 1,
color: 'transparent'
}
},
]
}
完整代码如下:
<template>
<div class="three-echart-height">
<Echart :options="waterOptions"></Echart>
</div>
</template>
<script>
import Echart from '@/components/commonEchart/index.vue'
import { waterOptions } from './echartOptions.js'
import axios from 'axios'
export default {
components: {
Echart
},
data() {
return {
waterOptions,
dateList: [], // 日期
windScaleDays: [], // 风力等级
tempMaxs: [], // 最高温
tempMins: [], // 最低温
iconDays: [], // 白天天气图标
nowWeather: '' // 当前天气
};
},
created() {
this.getWeather();
},
methods: {
async getWeather() {
const key = 'YOUR_API_KEY';
const params = {
key,
location: '根据需要填写',
};
try {
// 获取城市 location 值
const res = await axios.get('https://geoapi.qweather.com/v2/city/lookup?', { params });
if (res.data.code === '200') {
const locationId = res.data.location[0].id;
const weatherData = await this.fetchWeatherData(locationId, key);
if (weatherData.daily) {
this.processDailyWeather(weatherData.daily);
}
if (weatherData.now) {
this.nowWeather = weatherData.now;
}
}
} catch (error) {
console.error('Error', error);
}
},
async fetchWeatherData(locationId, key) {
const params = { key, location: locationId };
try {
const [dailyResponse, nowResponse] = await Promise.all([
axios.get('https://devapi.qweather.com/v7/weather/7d?', { params }),
axios.get('https://devapi.qweather.com/v7/weather/now?', { params })
]);
return {
daily: dailyResponse.data.code === '200' ? dailyResponse.data.daily : null,
now: nowResponse.data.code === '200' ? nowResponse.data.now : null
};
} catch (error) {
console.error('Error fetching individual weather data:', error);
return {};
}
},
processDailyWeather(dailyData) {
this.dateList = dailyData.map(item => item.fxDate.slice(5));
this.windScaleDays = dailyData.map(item => item.windScaleDay);
this.tempMaxs = dailyData.map(item => item.tempMax);
this.tempMins = dailyData.map(item => item.tempMin);
this.iconDays = dailyData.map(item => item.iconDay);
// 更新图表数据
this.waterOptions.xAxis[0].data = this.dateList;
this.waterOptions.xAxis[2].data = this.windScaleDays;
this.waterOptions.series[0].data = this.tempMaxs;
this.waterOptions.series[1].data = this.tempMins;
this.waterOptions.xAxis[1].data = this.iconDays;
this.updateIconLabels();
},
updateIconLabels() {
this.iconDays.forEach(val => {
this.waterOptions.xAxis[1].axisLabel.rich[val] = {
backgroundColor: {
image: require(`@/assets/qwIcons/${val}-fill.svg`)
},
height: 30,
width: 30
};
});
}
}
};
</script>
欢迎各位留言(轻点骂)