前言
本次小项目是学弟提出的,可视化一般都涉及Echart作图,本次使用Flask框架快速搭建后端,使用Echart作为画图工具
项目结构
+---static # 静态资源目录
| +---css # CSS文件目录
| +---fonts # 字体文件目录
| +---img # 图片文件目录
| \---js # JavaScript文件目录
+---templates # 模板文件目录
+---weather_data # 天气数据目录
│ app.py # 应用程序主文件
│ clean.py # 数据清洗文件
│ ua_info.py # UA信息文件
│ weather_spider.py # 天气爬虫文件
最后效果图
首页图
具体城市页
后端准备工作
模拟随机UA
ua_list = [
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
'User-Agent:Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11',
'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
]
爬虫代码
选取的weather.com.cn
的数据源进行数据爬取
# spider.py
import requests
from bs4 import BeautifulSoup
import csv
import json
from ua_info import ua_list # 使用自定义的ua池
import random
import time
import os
import clean
class WeatherSpider(object):
def __init__(self):
# 初始化url属性
self.url1 = 'http://www.weather.com.cn/weather/{}'
self.url2 = 'http://www.weather.com.cn/weather15d/{}'
self.url3 = 'https://weather.cma.cn/web/weather/{}'
# 地区id
self.weather_id_14 = {
"哈尔滨": 101050101,
"齐齐哈尔": 101050201,
"牡丹江": 101050301,
"佳木斯": 101050401,
"绥化": 101050501,
"黑河": 101050601,
"大兴安岭": 101050701,
"伊春": 101050801,
"大庆": 101050901,
"鸡西": 101051101,
"鹤岗": 101051201,
"双鸭山": 101051301,
"七台河": 101051002,
"阿城": 101050104,
"尚志": 101050111,
"五常": 101050112
}
self.weather_id_mw = {
"哈尔滨": 50953,
"齐齐哈尔": 50745,
"牡丹江": 54094,
"佳木斯": 50873,
"大庆": 50850,
"鸡西": 50978,
"鹤岗": 50775,
"双鸭山": 50884,
"伊春": 50774,
"七台河": 50971,
"黑河": 50468,
"绥化": 50853
}
self.spider_id = 1
def get_html(self, url):
# 请求获得网页内容
try:
headers = {'User-Agent': random.choice(ua_list)}
r = requests.get(url, headers=headers, timeout=30)
r.raise_for_status()
# 判断返回的Response类型状态是不是200,如果是200,将表示返回的内容是正确的,如果不是200,会产生一个HttpError的异常
r.encoding = r.apparent_encoding
print('访问成功--', self.spider_id)
self.spider_id += 1
return r.text
except:
print('访问错误')
return ''
def get_content_7d(self, html):
# 处理得到有用信息保存数据文件
bs = BeautifulSoup(html, 'html.parser') # 创建BeautifulSoup对象
body = bs.body
# 处理当天的数据
data_today = body.find_all('div', {'class': 'left-div'})
text = data_today[2].find('script').string
text = text[text.index('=') + 1:-2] # 移除var,将其变为json数据
jd = json.loads(text)
today = jd['od']['od2'] # 找到当天的数据
final_day = [] # 初始化一个列表保存数据
count = 0
for i in today:
temp = [] # 临时存放数据
if count <= 23 and count != 0: # today数组内的第一个数据无用跳过
temp.append(i['od21']) # 添加时间
temp.append(i['od22']) # 添加当前时刻温度
temp.append(i['od24']) # 添加当前时刻风力方向
temp.append(i['od25']) # 添加当前时刻风级
temp.append(i['od26']) # 添加当前时刻降水量
temp.append(i['od27']) # 添加当前时刻相对湿度
temp.append(i['od28']) # 添加当前时刻空气质量
# print(temp)
final_day.append(temp)
count = count + 1
# 处理7天数据
data_7d = body.find('div', {'id': '7d'}) # 找到div标签且id = 7d
ul = data_7d.find('ul') # 找到所有的ul标签
li = ul.find_all('li') # 找到所有的li标签
final = [] # 初始化一个列表保存数据
i = 0 # 控制爬取的天数
for day in li: # 遍历找到的每一个li
if 7 > i > 0:
temp = [] # 临时存放数据
date = day.find('h1').string # 得到日期
date = date[0:date.index('日')] # 取出日期号
temp.append(date)
inf = day.find_all('p') # 找出li下面的p标签,提取第一个p标签的值,即天气
temp.append(inf[0].string)
tem_low = inf[1].find('i').string # 找到最低气温
temp.append(tem_low[:-1])
if inf[1].find('span') is None: # 天气预报可能没有最高气温
tem_high = None
else:
tem_high = inf[1].find('span').string # 找到最高气温
if tem_high[-1] == '℃':
temp.append(tem_high[:-1])
else:
temp.append(tem_high)
wind = inf[2].find_all('span') # 找到风向
for j in wind:
temp.append(j['title'])
wind_scale = inf[2].find('i').string # 找到风级
index1 = wind_scale.index('级')
temp.append(int(wind_scale[index1 - 1:index1]))
final.append(temp)
i = i + 1
return final_day, final
# print(final)
def get_content_14d(self, html):
# 处理得到有用信息保存数据文件
bs = BeautifulSoup(html, "html.parser") # 创建BeautifulSoup对象
body = bs.body
data = body.find('div', {'id': '15d'}) # 找到div标签且id = 15d
ul = data.find('ul') # 找到所有的ul标签
li = ul.find_all('li') # 找到所有的li标签
final = [] # 初始化一个列表保存数据
i = 0 # 控制爬取的天数
for day in li: # 遍历找到的每一个li
if i < 8:
temp = [] # 临时存放每天的数据
date = day.find('span', {'class': 'time'}).string # 得到日期
date = date[date.index('(') + 1:-2] # 取出日期号
temp.append(date)
weather = day.find('span', {'class': 'wea'}).string # 找到天气
temp.append(weather)
tem = day.find('span', {'class': 'tem'}).text # 找到温度
temp.append(tem[tem.index('/') + 1:-1]) # 找到最低气温
temp.append(tem[:tem.index('/') - 1]) # 找到最高气温
wind = day.find('span', {'class': 'wind'}).string # 找到风向
if '转' in wind: # 如果有风向变化
temp.append(wind[:wind.index('转')])
temp.append(wind[wind.index('转') + 1:])
else: # 如果没有风向变化,前后风向一致
temp.append(wind)
temp.append(wind)
wind_scale = day.find('span', {'class': 'wind1'}).string # 找到风级
index1 = wind_scale.index('级')
temp.append(int(wind_scale[index1 - 1:index1]))
final.append(temp)
return final
def get_html_mw(self, name, html):
# 处理得到有用信息保存数据文件
bs = BeautifulSoup(html, "html.parser") # 创建BeautifulSoup对象
body = bs.body
final = [name]
data_max_all = body.find_all('div', {'class': 'high'})
data_max = data_max_all[0].string
data_max = data_max[data_max.index('℃') - 2:data_max.index('℃')].strip()
data_min_all = body.find_all('div', {'class': 'low'})
data_min = data_min_all[0].string
data_min = data_min[data_min.index('℃') - 2:data_min.index('℃')].strip()
final.append(data_min)
final.append(data_max)
return final
#保存本地CSV文件
def write_to_csv(self, file_name, data, day):
if not os.path.exists('./weather_data'): # 判断是否存在文件夹
os.mkdir('./weather_data') # 添加文件夹
path = os.path.join('./weather_data', file_name) # 拼接相对路径
# 保存为CSV
with open(path, 'w', errors='ignore', newline='') as f:
if day == 14:
header = ['日期', '天气', '最低气温', '最高气温', '风向1', '风向2', '风级']
else:
header = ['小时', '温度', '风力方向', '风级', '降水量', '相对湿度', '空气质量']
f_csv = csv.writer(f)
f_csv.writerow(header)
f_csv.writerows(data)
def run(self):
# 入口函数
print("Weather test")
for key, value in self.weather_id_14.items():
url_id = str(value) + '.shtml'
url1 = self.url1.format(url_id)
url2 = self.url2.format(url_id)
html1 = self.get_html(url1)
data1, data1_7 = self.get_content_7d(html1) # 获得1-7天和当天的数据
html2 = self.get_html(url2)
data8_14 = self.get_content_14d(html2) # 获得8-14天数据
date14 = data1_7 + data8_14
name1 = key + '1.csv'
name2 = key + '14.csv'
self.write_to_csv(name1, data1, 1) # 保存为CSV
self.write_to_csv(name2, date14, 14)
# 每爬取一个页面随机休眠1-2秒钟的时间
time.sleep(random.randint(1, 2))
with open('./weather_data\\mw.csv', 'w', errors='ignore', newline='') as f:
f_csv = csv.writer(f)
header = ['城市', '最低温', '最高温']
f_csv.writerow(header)
for key, value in self.weather_id_mw.items():
url_id = str(value) + '.html'
url3 = self.url3.format(url_id)
html3 = self.get_html(url3)
f_csv.writerow(self.get_html_mw(key, html3))
# 每爬取一个页面随机休眠1-2秒钟的时间
time.sleep(random.randint(1, 2))
if __name__ == '__main__':
start = time.time()
spider = WeatherSpider() # 实例化一个对象spider
spider.run() # 调用入口函数
clean.run()
end = time.time()
# 查看程序执行时间
print('执行时间:%.2f' % (end - start)) # 爬虫执行时间
清空本地数据代码
import pandas as pd
path = './weather_data\\{}'
city = ['哈尔滨', '黑河', '鸡西', '七台河', '绥化', '牡丹江', '大兴安岭', '佳木斯', '双鸭山', '五常', '齐齐哈尔', '尚志', '阿城', '大庆', '伊春', '鹤岗']
def clean_data(path):
data = pd.read_csv(path, encoding='gbk', header=0)
data = data.fillna(axis=0, method='ffill')
data = data.fillna(axis=0, method='bfill')
data.to_csv(path, encoding='gbk', index=0)
def run():
print('开始清洗')
for index in city:
path_1d = path.format(index + '1.csv')
path_14d = path.format(index + '14.csv')
clean_data(path_1d)
clean_data(path_14d)
if __name__ == '__main__':
run()
前端准备工作
本次获取的是黑龙江的数据,前端首页设计了一张黑龙江省全省地形图,所以需要获取到geo数据本次使用了DataV获取GEOJson数据 存放在静态文件(static/js)中进行引用
header页
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<meta charset="utf-8">
<title>天气可视化分析</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content=""/>
<meta name="author" content=""/>
<script src="../static/js/echarts.min.js"></script>
<!-- css -->
<link href="../static/css/bootstrap.min.css" rel="stylesheet"/>
<link href="../static/css/fancybox/jquery.fancybox.css" rel="stylesheet">
<link href="../static/css/flexslider.css" rel="stylesheet"/>
<link href="../static/css/style.css" rel="stylesheet"/>
</head>
</head>
<body>
<!-- start header -->
<header>
<div class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse"
data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index">天气数据爬取及可视化分析</a>
</div>
<div class="navbar-collapse collapse ">
<ul class="nav navbar-nav">
<li><a href="/index">首页</a></li>
<li class="dropdown">
<a href="#" data-toggle="dropdown" class="dropdown-toggle">城市<b
class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="/weather/haerbin">哈尔滨</a></li>
<li><a href="/weather/qiqihaer">齐齐哈尔</a></li>
<li><a href="/weather/mudanjiang">牡丹江</a></li>
<li><a href="/weather/jiamusi">佳木斯</a></li>
<li><a href="/weather/daqing">大庆</a></li>
<li><a href="/weather/jixi">鸡西</a></li>
<li><a href="/weather/hegang">鹤岗</a></li>
<li><a href="/weather/shuangyashan">双鸭山</a></li>
<li><a href="/weather/yichun">伊春</a></li>
<li><a href="/weather/qitaihe">七台河</a></li>
<li><a href="/weather/heihe">黑河</a></li>
<li><a href="/weather/suihua">绥化</a></li>
<li><a href="/weather/daxinganling">大兴安岭</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</header>
<!-- end header -->
</body>
</html>
footer页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<footer>
<div class="container">
<div id="sub-footer">
<div class="container">
<div class="row">
<div class="col-lg-6">
<div class="copyright">
<p>
xxx
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</footer>
</body>
</html>
首页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>天气可视化分析</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content=""/>
<meta name="author" content=""/>
<script src="../static/js/echarts.min.js"></script>
<!-- 黑龙江geoJson数据 -->
<script src="../static/js/geoJson.js"></script>
<!-- css -->
<link href="../static/css/bootstrap.min.css" rel="stylesheet"/>
<link href="../static/css/fancybox/jquery.fancybox.css" rel="stylesheet">
<link href="../static/css/flexslider.css" rel="stylesheet"/>
<link href="../static/css/style.css" rel="stylesheet"/>
</head>
<body>
<div id="wrapper" class="home-page">
<!-- 导入header.html -->
{% include 'header.html' %}
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="visualMap" style="height: 600px;width: 1300px;margin: 0 auto"></div>
<div id="container" style="height: 600px;width: 1300px;margin: 0 auto"></div>
<!-- 导入footer.html -->
{% include 'footer.html' %}
</div>
<a href="#" class="scrollup"><i class="fa fa-angle-up active"></i></a>
<!-- javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script type="text/javascript">
var dom = document.getElementById('container');
var myChart = echarts.init(dom, null, {
renderer: 'canvas',
useDirtyRect: false
});
var app = {};
var option;
const posList = [
'left',
'right',
'top',
'bottom',
'inside',
'insideTop',
'insideLeft',
'insideRight',
'insideBottom',
'insideTopLeft',
'insideTopRight',
'insideBottomLeft',
'insideBottomRight'
];
app.configParameters = {
rotate: {
min: -90,
max: 90
},
align: {
options: {
left: 'left',
center: 'center',
right: 'right'
}
},
verticalAlign: {
options: {
top: 'top',
middle: 'middle',
bottom: 'bottom'
}
},
position: {
options: posList.reduce(function (map, pos) {
map[pos] = pos;
return map;
}, {})
},
distance: {
min: 0,
max: 100
}
};
app.config = {
rotate: 90,
align: 'left',
verticalAlign: 'middle',
position: 'insideBottom',
distance: 15,
onChange: function () {
const labelOption = {
rotate: app.config.rotate,
align: app.config.align,
verticalAlign: app.config.verticalAlign,
position: app.config.position,
distance: app.config.distance
};
myChart.setOption({
series: [
{
label: labelOption
},
{
label: labelOption
},
{
label: labelOption
},
{
label: labelOption
}
]
});
}
};
const labelOption = {
show: true,
position: app.config.position,
distance: app.config.distance,
align: app.config.align,
verticalAlign: app.config.verticalAlign,
rotate: app.config.rotate,
formatter: '{c} {name|{a}}',
fontSize: 16,
rich: {
name: {}
}
};
option = {
title: {
text: ' 各市气温对比'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['最低温', '最高温']
},
toolbox: {
show: true,
orient: 'vertical',
left: 'right',
top: 'center',
feature: {
mark: {show: true},
dataView: {show: true, readOnly: false},
magicType: {show: true, type: ['line', 'bar', 'stack']},
restore: {show: true},
saveAsImage: {show: true}
}
},
xAxis: [
{
type: 'category',
axisTick: {show: false},
data: ['哈尔滨', '齐齐哈尔', '牡丹江', '佳木斯', '大庆', '鸡西', '鹤岗', '双鸭山', '伊春', '七台河', '黑河', '绥化']
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: '最低温',
type: 'bar',
barGap: 0,
label: labelOption,
showBackground: true,
backgroundStyle: {
color: 'rgba(180, 180, 180, 0.2)'
},
emphasis: {
focus: 'series'
},
data: {{ data_min }}
},
{
name: '最高温',
type: 'bar',
label: labelOption,
showBackground: true,
backgroundStyle: {
color: 'rgba(180, 180, 180, 0.2)'
},
emphasis: {
focus: 'series'
},
data: {{ data_max }}
}
]
};
if (option && typeof option === 'object') {
myChart.setOption(option);
}
echarts.registerMap('哈尔滨', geoJson);
// 初始化echarts实例
var mapChart = echarts.init(document.getElementById('visualMap'));
//测试数据
var temperatureData = [
{name: '哈尔滨市', value: -20, maxTemp: -10, minTemp: -10},
{name: '齐齐哈尔市', value: 24, maxTemp: 29, minTemp: 19},
{name: '牡丹江市', value: 23, maxTemp: 28, minTemp: 18},
{name: '佳木斯市', value: 26, maxTemp: 31, minTemp: 21},
{name: '大庆市', value: 27, maxTemp: 32, minTemp: 22},
{name: '鸡西市', value: 22, maxTemp: 27, minTemp: 17},
{name: '鹤岗市', value: 21, maxTemp: 26, minTemp: 16},
{name: '双鸭山市', value: 22, maxTemp: 27, minTemp: 17},
{name: '伊春市', value: 20, maxTemp: 25, minTemp: 15},
{name: '七台河市', value: 19, maxTemp: 24, minTemp: 14},
{name: '绥化市', value: 24, maxTemp: 29, minTemp: 19},
{name: '黑河市', value: 23, maxTemp: 28, minTemp: 18},
{name: '大兴安岭地区', value: 18, maxTemp: 23, minTemp: 13}
];
// 配置项
var mapOption = {
tooltip: {
trigger: 'item',
formatter: function (params) {
if (params.data) {
return params.name + "<br/>最高温:" + params.data.maxTemp + "°C<br/>最低温:" + params.data.minTemp + "°C";
} else {
return params.name;
}
}
},
visualMap: {
min: -20,
max: 40,
calculable: true,
inRange: {
color: ['#50a3ba', '#eac736', '#d94e5d']
}
},
series: [
{
type: 'map',
map: '哈尔滨', // 地图名称,对应到echarts.registerMap()中的地图名称
data: {{temperatureData|tojson|safe}}, // 各地区温度数据使用引用后端数据,
label: {
show: true
},
}
]
};
// 使用刚指定的配置项和数据显示图表。
mapChart.setOption(mapOption);
window.addEventListener('resize', mapChart.resize);
window.addEventListener('resize', myChart.resize);
</script>
<script src="../static/js/jquery.js"></script>
<script src="../static/js/jquery.easing.1.3.js"></script>
<script src="../static/js/bootstrap.min.js"></script>
<script src="../static/js/jquery.fancybox.pack.js"></script>
<script src="../static/js/jquery.fancybox-media.js"></script>
<script src="../static/js/jquery.flexslider.js"></script>
<script src="../static/js/animate.js"></script>
<!-- Vendor Scripts -->
<script src="../static/js/modernizr.custom.js"></script>
<script src="../static/js/jquery.isotope.min.js"></script>
<script src="../static/js/jquery.magnific-popup.min.js"></script>
<script src="../static/js/animate.js"></script>
<script src="../static/js/custom.js"></script>
</body>
</html>
具体城市页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>天气可视化分析</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content=""/>
<meta name="author" content=""/>
<script src="../static/js/echarts.min.js"></script>
<!-- css -->
<link href="../static/css/bootstrap.min.css" rel="stylesheet"/>
<link href="../static/css/fancybox/jquery.fancybox.css" rel="stylesheet">
<link href="../static/css/flexslider.css" rel="stylesheet"/>
<link href="../static/css/style.css" rel="stylesheet"/>
</head>
<body>
<div id="wrapper" class="home-page">
<!-- 导入header.html -->
{% include 'header.html' %}
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="every_hour" style="width: 1300px;height:600px;margin: 0 auto;"></div>
<br><br>
<div id="shidu_zhiliang" style="width: 1300px;height:600px;margin: 0 auto;"></div>
<br><br>
<p style="text-align: center">{{ city_name }}每小时风力,风向,降水量对比</p>
<table class="table table-striped" style="width: 90%;text-align: center;margin: 0 auto;">
<tr>
<td>时间</td>
<td>风力方向</td>
<td>风级</td>
<td>降水量</td>
</tr>
{% for index in range(0, 24) %}
<tr>
<td>{{ time_1d[index] }}</td>
<td>{{ fangxiang_1d[index] }}</td>
<td>{{ fengji_1d[index] }}</td>
<td>{{ jiangshui_1d[index] }}</td>
</tr>
{% endfor %}
</table>
<br><br>
<div class="container">
<div id="Box">
<!-- 为 ECharts 准备一个定义了宽高的 DOM -->
<div id="main">
</div>
<p style="text-align: center">{{ city_name }}未来14天天气,方向,风级</p>
<div id="main2">
<table class="table table-striped" style="width: 90%;text-align: center;margin: 0 auto;">
<tr>
<td>日期</td>
<td>天气</td>
<td>方向1</td>
<td>风向2</td>
<td>风级</td>
</tr>
{% for index in range(0, 14) %}
<tr>
<td>{{ time_14d[index] }}</td>
<td>{{ tianqi_14d[index] }}</td>
<td>{{ fangxiang1_14d[index] }}</td>
<td>{{ fengxiang2_14d[index] }}</td>
<td>{{ fengji_14d[index] }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
<!-- 导入footer.html -->
{% include 'footer.html' %}
</div>
<a href="#" class="scrollup"><i class="fa fa-angle-up active"></i></a>
<!-- javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script type="application/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('every_hour'));
// 指定图表的配置项和数据
// prettier-ignore
let dataAxis = {{ time_1d }};
// prettier-ignore
let data = {{ temp_1d }};
let yMax = 500;
let dataShadow = [];
for (let i = 0; i < data.length; i++) {
dataShadow.push(yMax);
}
option = {
title: {
text: '{{ city_name }}每小时气温变化',
left: '40%' // 设置标题居中对齐
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
xAxis: {
data: dataAxis,
axisLabel: {
inside: true,
color: '#ff9818'
},
axisTick: {
show: false
},
axisLine: {
show: false
},
z: 10
},
yAxis: {
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
color: '#999'
}
},
dataZoom: [
{
type: 'inside'
}
],
series: [
{
type: 'bar',
showBackground: true,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{offset: 0, color: '#83bff6'},
{offset: 0.5, color: '#188df0'},
{offset: 1, color: '#188df0'}
])
},
emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{offset: 0, color: '#2378f7'},
{offset: 0.7, color: '#2378f7'},
{offset: 1, color: '#83bff6'}
])
}
},
data: data
}
]
};
// Enable data zoom when user click bar.
const zoomSize = 6;
myChart.on('click', function (params) {
console.log(dataAxis[Math.max(params.dataIndex - zoomSize / 2, 0)]);
myChart.dispatchAction({
type: 'dataZoom',
startValue: dataAxis[Math.max(params.dataIndex - zoomSize / 2, 0)],
endValue:
dataAxis[Math.min(params.dataIndex + zoomSize / 2, data.length - 1)]
});
});
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('shidu_zhiliang'));
// 指定图表的配置项和数据
option = {
title: {
text: '{{ city_name }}每小时相对湿度,空气质量可视化分析',
left: '10%' // 设置标题居中对齐
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['相对湿度', '空气质量']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: {{ time_1d }}
},
yAxis: {
type: 'value'
},
series: [
{
name: '相对湿度',
type: 'line',
stack: 'Total',
data: {{ shidu_1d }},
label: {
position: 'right' // 设置参数靠右摆放
}
},
{
name: '空气质量',
type: 'line',
stack: 'Total',
data: {{ air_1d }},
label: {
position: 'right' // 设置参数靠右摆放
}
},
]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
//未来一周气温变化图
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
option = {
title: {
text: '{{ city_name }}未来14天气温变化图',
left: '40%' // 设置标题居中对齐
},
grid: {
left: '5%',
right: '9%'
},
tooltip: {
trigger: 'axis'
},
legend: {
x: 'right',
y: 'top',
padding: [35, 10, 5, 10],
},
toolbox: {
show: true,
feature: {
dataZoom: {
yAxisIndex: 'none'
},
dataView: {readOnly: false},
magicType: {type: ['line', 'bar']},
restore: {},
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: {{ time_14d }}
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value} °C'
}
},
series: [
{
name: '最高温',
type: 'line',
data: {{ temp_max }},
markPoint: {
data: [
{type: 'max', name: 'Max'},
{type: 'min', name: 'Min'}
]
},
markLine: {
data: [{type: 'average', name: 'Avg'}]
}
},
{
name: '最低温',
type: 'line',
data: {{ temp_min }},
markPoint: {
data: [{name: '周最低', value: -2, xAxis: 1, yAxis: -1.5}]
},
markLine: {
data: [
{type: 'average', name: 'Avg'},
[
{
symbol: 'none',
x: '90%',
yAxis: 'max'
},
{
symbol: 'circle',
label: {
position: 'start',
formatter: 'Max'
},
type: 'max',
name: '最高点'
}
]
]
}
}
]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
<script src="../static/js/jquery.js"></script>
<script src="../static/js/jquery.easing.1.3.js"></script>
<script src="../static/js/bootstrap.min.js"></script>
<script src="../static/js/jquery.fancybox.pack.js"></script>
<script src="../static/js/jquery.fancybox-media.js"></script>
<script src="../static/js/jquery.flexslider.js"></script>
<script src="../static/js/animate.js"></script>
<!-- Vendor Scripts -->
<script src="../static/js/modernizr.custom.js"></script>
<script src="../static/js/jquery.isotope.min.js"></script>
<script src="../static/js/jquery.magnific-popup.min.js"></script>
<script src="../static/js/animate.js"></script>
<script src="../static/js/custom.js"></script>
</body>
</html>