本文介绍一下某数值模型计算空气监测站周边工业排放源对其某污染因子浓度的影响程度(贡献度)的前端页面设计。
前端html代码如下:
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<title></title>
<!-- CSS only -->
<link href="/static/lib/bootstrap-5.1.3-dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.tableDiv {
height: 600px;
overflow: scroll;
}
[data-role="toolbar"] {
text-align: center;
}
#map {
min-height: 800px;
}
#bar {
min-height: 450px;
}
thead {
border-width: 1px 1px;
background: #00BC80;
/* background: #BAD3F2;*/
}
th,
td {
text-align: center;
vertical-align: middle;
}
#contributeDiv{
max-height: 350px;
}
th.name,td.name{
max-width: 250px;
}
</style>
<script type="text/template" id="contributeTableTemplate">
<table class="table caption-top">
<caption><%=title%></caption>
<thead>
<tr>
<th scope="col">#</th>
<th scope="col" class='name'>企业名称</th>
<th scope="col">方位</th>
<th scope="col">距离</th>
<th scope="col">贡献率</th>
</tr>
</thead>
<tbody>
<%_.each(data,function(item,index){ %>
<tr>
<th scope="row"><%=index+1%></th>
<td><%=item['name']%></td>
<td><%=item['direction']%></td>
<td><%=item['distance']%>公里</td>
<td><%=(item['value']*100).toFixed(1)%>%</td>
</tr>
<%});%>
</tbody>
</table>
</script>
<script type="text/template" id="optionsTemplate">
<% _.each(rows,function(item){ %>
<% var stations=item['stations'] %>
<optgroup label="<%=item['name']%>">
<% _.each(stations,function(station){ %>
<option value="<%=station['code']%>"><%=station['name']%></option>
<% }) %>
</optgroup>
<% }) %>
</script>
</head>
<body>
<div class="container-fluid">
<div class="row g-3" data-role="toolbar" data-menu="aqi-contribute-sources" style="display: none;">
<div class="col-1 right">
<label for="option_date" class="form-label">起报时间:</label>
</div>
<div class="col-2">
<input type="date" id="option_date" class="form-control" aria-label="Default select example">
</div>
<div class="col-1 right">
<label for="option_station" class="form-label">站点</label>
</div>
<div class="col-2">
<select id="option_station" class="form-select " aria-label="Default select example">
</select>
</div>
<div class="col-1 right">
<label for="option_factor" class="form-label">污染因子</label>
</div>
<div class="col-1">
<select id="option_factor" class="form-select " aria-label="Default select example">
<option value="PM10_24h">PM<sub>10</sub></option>
<option value="PM25_24h">PM<sub>2.5</sub></option>
<option value="SO2_24h">SO<sub>2</sub></option>
<option value="NO2_24h">NO<sub>2</sub></option>
<option value="CO_24h">CO</option>
<option value="O3_8h">O<sub>3</sub></option>
</select>
</div>
<div class="col-1 right">
<label for="option_date2" class="form-label">预报时间</label>
</div>
<div class="col-2">
<input id="option_date2" type="date" class="form-control">
</div>
<div class="col-1">
<button type="submit" class="btn btn-primary mb-3" id="option_submit">查询</button>
</div>
</div>
<div class="row justify-content-start">
<div class="col-7">
<div id="map"></div>
</div>
<div class="col-5">
<div class="row">
<div id="bar"></div>
</div>
<div class="row">
<div id="contributeDiv" class="table-responsive "></div>
</div>
</div>
</div>
</div>
<script src="/static/lib/jquery/jquery-1.11.3.js"></script>
<script src="/static/lib/underscore/underscore.js"></script>
<script src="/static/lib/bootstrap-5.1.3-dist/js/bootstrap.min.js"></script>
<script src="/static/lib/daterangepicker/daterangepicker.js"></script>
<script src="/static/lib/moment/moment.min.js"></script>
<script src="/static/lib/moment/zh-cn.js"></script>
<script src="/static/lib/chartjs/chart.min.js"></script>
<script src="/static/lib/echarts/echarts.min.js"></script>
<script src="/static/lib/d3/d3.v5.min.js"></script>
<script src='/static/lib/turf/turf.min.js'></script>
<script src="/static/js/base.js"></script>
<script src="/static/js/aqi-contribute-pollutes.js"></script>
</body></html>
除了引用公共的base.js文件,前端JavaScript代码aqi-contribute-pollutes.js如下:
$(function () {
var radios = [0.01, 0.02, 0.05, 0.10, 0.20, 0.30];
getRegions().then(function () {
var template = _.template($('#optionsTemplate').html());
var html = template({
rows: citys
});
$('#option_station').html(html);
})
function initMap(data, station) {
var points = data.map(x => x.position.concat([x.value, x.name]));
var lines = data.map(x => {
var colorIndex = _.sortedIndex(radios, x.value);
var color = levelColors[colorIndex];
return {
coords: [x.position, [station.lng, station.lat]],
lineStyle: {
color: color,
}
}
})
var pointsAll = points.concat([[station.lng, station.lat]]);
var chartDom = document.getElementById('map');
var myChart = echarts.init(chartDom);
option = {
toolbox: {
feature: {
restore: {},
saveAsImage: {}
}
},
// backgroundColor: '#013954',
title: {
top: 20,
text: `(${station['name']})周边企业影响`,
subtext: $('#contributeDiv caption').text(),
x: 'center',
textStyle: {
color: '#fff'
},
subtextStyle: {
color: '#fff'
},
},
tooltip: {
trigger: 'item',
showDelay: 0,
hideDelay: 0,
enterable: false,
transitionDuration: 0,
formatter: function (params, ticket, callback) {
if (params.seriesIndex == 0) {
var res = "";
var name = params.value[3];
var value = params.value[2];
res = "<span style='color:#000;'>" + name + "<br/>贡献率:" + (value * 100).toFixed(1) + '%' + "</span>";
return res;
} else {
return false;
}
}
},
geo: {
boundingCoords: [
[Math.min(...pointsAll.map(x => x[0])) - 0.05, Math.min(...pointsAll.map(x => x[1])) - 0.05],
[Math.max(...pointsAll.map(x => x[0])) + 0.05, Math.max(...pointsAll.map(x => x[1])) + 0.05]
],
map: 'henan',
aspectScale: 1, //长宽比
zoom: 1.1,
// center: item.position,
roam: true,
label: {
normal: {
show: true,
textStyle: {
color: '#1DE9B6'
}
},
emphasis: {
textStyle: {
color: 'rgb(183,185,14)'
}
}
},
itemStyle: {
normal: {
borderColor: 'rgb(147, 235, 248)',
borderWidth: 1,
areaColor: {
type: 'radial',
x: 0.5,
y: 0.5,
r: 0.8,
colorStops: [{
offset: 0,
color: '#09132c' // 0% 处的颜色
}, {
offset: 1,
color: '#274d68' // 100% 处的颜色
}],
globalCoord: true // 缺省为 false
},
},
emphasis: {
areaColor: '#013954',
// shadowColor: 'rgb(12,25,50)',
borderWidth: 0.1
}
},
},
series: [{
type: 'effectScatter',
coordinateSystem: 'geo',
showEffectOn: 'render',
zlevel: 1,
rippleEffect: {
period: 15,
scale: 4,
brushType: 'fill'
},
hoverAnimation: false,
itemStyle: {
normal: {
color: function (params) {
var colorIndex = _.sortedIndex(radios, params.data[2]);
return levelColors[colorIndex];
},
shadowBlur: 10,
shadowColor: '#333'
}
},
symbolSize: 12,
data: points
}, //地图线的动画效果
{
type: 'lines',
zlevel: 2,
effect: {
show: true,
period: 4, //箭头指向速度,值越小速度越快
trailLength: 0.4, //特效尾迹长度[0,1]值越大,尾迹越长重
symbol: 'arrow', //箭头图标
symbolSize: 7, //图标大小
},
label: {
show: true,
position: 'middle',
formatter: function (params) {
var value = points[params.dataIndex][2];
return (value * 100).toFixed(1) + '%';
},
color: '#fff'
},
lineStyle: {
normal: {
color: '#1DE9B6',
width: 1, //线条宽度
opacity: 0.1, //尾迹线条透明度
curveness: .3 //尾迹线条曲直度
}
},
data: lines
},
{
type: 'scatter',
coordinateSystem: 'geo',
zlevel: 2,
rippleEffect: {
period: 4,
brushType: 'stroke',
scale: 4
},
label: {
normal: {
show: true,
fontSize: 16,
position: 'right',
//offset:[5, 0],
color: '#0f0',
formatter: '{b}',
textStyle: {
color: "#0f0"
}
},
emphasis: {
show: true,
color: "#f60"
}
},
symbol: 'pin',
symbolSize: 50,
color: 'yellow',
data: [{
name: station.name,
value: [station.lng, station.lat],
}],
}]
};
myChart.setOption(option, true);
}
function initBar(data, station) {
// prettier-ignore
let dataAxis = _.pluck(data, 'name');
// prettier-ignore
let xData = _.map(data, x => {
var colorIndex = _.sortedIndex(radios, x.value);
return {
value: +(x.value * 100).toFixed(1),
itemStyle: {
color: levelColors[colorIndex]
}
}
});
var chartDom = document.getElementById('bar');
var myChart = echarts.init(chartDom);
var stationName = $('#option_station option:selected').text();
option = {
grid: {
height: '90%',
bottom: '0%',
left: 50,
containLabel: true
},
title: {
text: `(${station['name']})周边企业影响`,
subtext: $('#contributeDiv caption').text(),
},
xAxis: {
type: 'category',
data: dataAxis,
axisLabel: {
position: 'outside',
color: '#000',
interval: 0,
rotate: 60,
fontSize: 12,
fontStyle: 'bold',
formatter: function (params) {
return params.slice(0, 8);
},
lineHeight: 100,
},
},
yAxis: {
show: false
},
series: [
{
type: 'bar',
label: {
show: true,
color: '#000',
position: 'top',
formatter: '{c}%'
},
data: xData
}
]
};
myChart.setOption(option, true);
}
getPolygons().then(function () {
refreshAll();
});
$('#option_submit').click(function () {
refreshAll();
})
var angles = [-180, -157.5, -112.5, -67.5, -22.5, 22.5, 67.5, 112.5, 157.5, 180];
var directions = ['南', '南', '西南', '西', '西北', '北', '东北', '东', '东南', '南']
function refreshAll() {
var code = $('#option_station').val();
var station = _(stations).find({
'code': code
});
$.get('/static/mock/pollutes.json', {
station: code,
factor: $('#option_factor').val(),
runAt: $('#option_date').val(),
predictAt: $('#option_date2').val(),
},
function (data) {
var points=mockData3(data,station)
initTable(points,station);
initMap(points, station);
initBar(points, station);
})
}
function mockData3(data,station){
var points = data.map(x => {
return {
position: [x['lng'], x['lat']],
value: +((_.random(100, 2000) / 10000).toFixed(3)),
name: x['name']
}
});
var points_tf = turf.featureCollection(points.map(x => turf.point(x['position'], _.pick(x, ['name', 'value']))));
var radius = _.random(50, 150);
var options = {
steps: 30,
units: 'kilometers',
};
var searchWithin = turf.circle([station['lng'], station['lat']], radius, options);
var points_within = turf.pointsWithinPolygon(points_tf, searchWithin);
var from = turf.point([station['lng'], station['lat']]);
points = points_within.features.slice(0, 10).map(x => {
var to = turf.point(x.geometry.coordinates);
var options = {
units: 'kilometers'
};
var distance = turf.distance(from, to, options);
var bearing = turf.bearing(from, to);
direction = directions[_.sortedIndex(angles, bearing)];
return {
position: x.geometry.coordinates,
value: x.properties['value'],
distance: distance.toFixed(1),
direction: direction,
name: x.properties['name']
}
})
points = _.sortBy(points, 'value').reverse();
return points;
}
function initTable(points) {
var date = moment($('#option_date').val()).format('YYYY年M月D日');
var date2 = moment($('#option_date2').val()).format('YYYY年M月D日');
var factor = $('#option_factor').val();
var title = `(${dictFactor[factor]})(预测日期:${date2})(起报时间:${date})`;
var template = _.template($('#contributeTableTemplate').html());
var html = template({
data: points,
title: title
});
$('#contributeDiv').html(html);
}
})
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。