当前位置:网站首页>High quality coding - air quality map visualization
High quality coding - air quality map visualization
2022-06-23 14:20:00 【MiaoGIS】
Baidu map is usually used api To develop map visualization , Besides using JavaScript API GL To develop map visualization applications . You can also use the... Provided by Baidu maps MapVGL Library to develop . Use JavaScript API GL Time use overlayer(label,marker,line,polygon etc. ) To complete the addition of map overlay layer and realize visualization ,MapVGL Due to the use of layers (layer) To group manage stack layers , So the code is more concise , Development is more efficient .
Baidu Maps JavaScript API GL v1.0 It's a set of JavaScript Application program interface written in language , Can help you build rich features in the site 、 Interactive map applications , Support PC Browser based map application development at mobile and mobile end , And support HTML5 Feature map development .
MapVGL, It's based on WebGL Geographic information visualization library , Can be used to show a large number of 3D Geographic information point, line and surface data . The original intention of the design is mainly to solve the problem of large amount of 3D geographic data display and some cool 3D effects .
Let's use MapVGL To achieve the visualization of the national air quality map .
The following describes the front-end code implementation :
html The code is as follows :
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>MapVGL</title>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<link href="/static/css/loader.css" rel="stylesheet">
<style>
.loader {
width: 200px;
height: 200px;
left: 0;
top: 0;
right: 0;
bottom: 0;
position: fixed;
z-index: 99999;
text-align: revert;
margin: auto;
}
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background: #000;
}
#map_container {
width: 100%;
height: 100%;
margin: 0;
}
.map_grade {
position: fixed;
left: 0;
bottom: 0;
width: 252px;
z-index: 1000;
}
.map_grade .map_shadowColor {
display: inline-block;
width: 100%;
height: 8px;
margin-bottom: -5px;
background-image: linear-gradient(90deg, #43ce17 15%, #e1d72c 22%, #f72d0e 75%, #a7134c 90%);
}
.map_grade .map_leveltip {
color: #fff;
font-size: 12px;
border-collapse: collapse;
border-spacing: 0;
z-index: 1001;
background: rgba(0, 0, 0, .56);
}
.map_grade .map_leveltip td {
display: inline-block;
width: 42px;
height: 44px;
text-align: center;
vertical-align: middle;
line-height: 40px;
}
.map_grade .map_leveltip .map_level {
background: transparent;
}
#mapgroup .radio-button-wrapper {
width: 80px;
padding: 0 !important;
text-align: center;
border: 0 !important;
background: rgba(0, 0, 0, .6) !important;
color: #fff !important;
border-radius: 0 !important;
}
.mapgroup {
position: fixed;
right: 0;
top: 23%;
z-index: 999;
width: 80px;
}
.radio-group {
width: 80px;
display: grid;
cursor: pointer;
}
.white .radio-button,
.radio-button {
background-color: white;
color: #000;
line-height: 40px;
text-align: center;
text-decoration: none;
border: 1px solid black;
border-radius: 10px;
caret-color: transparent;
}
.dark .radio-button {
background-color: black;
color: #fff;
line-height: 40px;
text-align: center;
text-decoration: none;
border: 1px solid white;
border-radius: 10px;
caret-color: transparent;
}
.radio-button-checked,
.white .radio-button-checked,
.dark .radio-button-checked {
background-color: #337ab7;
color: #fff;
caret-color: transparent;
}
.timetip {
position: fixed;
left: 51px;
top: 66px;
z-index: 401;
padding: 3px 10px;
font-size: 15px;
background: rgba(0, 0, 0, .56);
color: #fff;
border-radius: 4px;
}
</style>
<script src="//api.map.baidu.com/api?v=2.0&type=webgl&ak=your baidu map ak"></script>
<script src="../static/js/common.js"></script>
<script src="//mapv.baidu.com/build/mapv.min.js"></script>
<script src="https://code.bdstatic.com/npm/[email protected]/dist/mapvgl.min.js"></script>
</head>
<body>
<div class="loader"></div>
<div id="map_container"></div>
<div id="mapgroup" class="mapgroup" contenteditable="false">
<div class="radio-group"><a class="radio-button radio-button-checked" data-factor="aqi" onclick="void(0);"><span class="radio-button-inner">AQI</span></a><a class="radio-button" data-factor="pm2_5" onclick="void(0);"><span class="radio-button-inner">PM2.5</span></a><a class="radio-button" data-factor="pm10" onclick="void(0);"><span class="radio-button-inner">PM10</span></a> <a class="radio-button" onclick="void(0);" data-factor="so2"><span class="radio-button-inner">SO2</span></a> <a class="radio-button" onclick="void(0);" data-factor="no2"><span class="radio-button-inner">NO2</span></a> <a onclick="void(0);" class="radio-button" data-factor="co"><span class="radio-button-inner">CO</span></a> <a class="radio-button" onclick="void(0);" data-factor="o3"><span class="radio-button-inner">O3</span></a> </div>
<div class="radio-group"><a id="toggleLabel" data-label="name" onclick="void(0);" class="radio-button"><span class="radio-button-inner" style="color: magenta;"> Explicit value </span> </a><a id="toggleStyle" class="radio-button" onclick="void(0);"><span class="radio-button-inner" style="color: orange;"> Dark night system </span> </a> </div>
</div>
<div class="map_grade"><canvas class="map_shadowColor"></canvas>
<table class="map_leveltip">
<tbody>
<tr style="white-space: nowrap;">
<td class="map_level"> optimal </td>
<td class="map_level"> good </td>
<td class="map_level"> light </td>
<td class="map_level"> Moderate </td>
<td class="map_level"> severe </td>
<td class="map_level"> serious </td>
</tr>
</tbody>
</table>
</div>
<div class="timetip">
<div id="timetip"></div>
<div style="display: none;"> The data source has not updated the data yet !</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/moment/moment.min.js"></script>
<script src="/static/lib/moment/zh-cn.js"></script>
<script src="/static/lib/crypto/crypto.js"></script>
<script src="/static/js/mapv.js"></script>
</body></html>
common.js Defines the style of the map and initializes the map function
/**
* Initialize map
*/
/* global BMapGL */
/* global darkStyle */
function initMap(options) {
options = Object.assign({
tilt: 60,
heading: 0
}, options);
var map = new BMapGL.Map('map_container', {
restrictCenter: false,
style: {styleJson: options.style || darkStyle }
});
map.enableKeyboard();
map.enableScrollWheelZoom();
map.enableInertialDragging();
map.enableContinuousZoom();
map.setDisplayOptions(options.displayOptions || {
indoor: false,
poi: true,
skyColors: options.skyColors || [
'rgba(5, 5, 30, 0.01)',
'rgba(5, 5, 30, 1.0)'
]
});
if (options.center && options.zoom) {
map.centerAndZoom(new BMapGL.Point(options.center[0], options.center[1]), options.zoom);
}
map.setTilt(options.tilt);
map.setHeading(options.heading);
return map;
}
var darkStyle = [{
featureType: 'background',
elementType: 'geometry',
stylers: {
color: '#070c17ff'
}
}, ......
];
var whiteStyle = [{
featureType: 'water',
elementType: 'geometry',
stylers: {
visibility: 'on',
color: '#ccd6d7ff'
}
}, ......];
The core js Code mapv.js as follows :
args=_.object(window.location.search.replace('?', '').split('&').map(x => x.split('=')));
var whiteBox=[
// Ground color
'rgba(226, 237, 248, 0)',
// Sky Color
'rgba(186, 211, 252, 1)'
];
function initMapV() {
var options = {
tilt: 56,
heading: 0.3,
center: [113, 34],
zoom: 9,
style:whiteStyle,
skyColors:whiteBox
};
var hour=(new Date).getHours();
if(hour>18||hour<6){
options['style'] = darkStyle;
delete options['skyColors'];
$('body').addClass('dark');
$('#toggleStyle span').text(' Diurnal wind ');
}
if (args['style'] == 'white') {
options['style'] = whiteStyle;
options['skyColors'] = whiteBox;
$('body').removeClass('dark').addClass('white');
$('#toggleStyle span').text(' Dark night wind ');
} else if(args['style'] == 'dark'){
options['style'] = darkStyle;
delete options['skyColors'];
$('body').addClass('dark');
$('#toggleStyle span').text(' Diurnal wind ');
}
map = initMap(options);
points_station = [];
points_city = [];
texts_city = [];
texts_station = [];
citys.filter(x => x['stations']).forEach(x => {
var cityCenter = mapv.utilCityCenter.getCenterByCityName(x['name']);
var point_city = {
geometry: {
type: 'Point',
coordinates: [cityCenter.lng, cityCenter.lat]
},
properties: {
name: x['name']
}
};
var text_city = {
geometry: {
type: 'Point',
coordinates: [cityCenter.lng, cityCenter.lat]
},
properties: {
name: x['name'],
text: x.name,
textColor: '#000',
backgroundColor: '#fff',
},
};
points_city.push(point_city);
texts_city.push(text_city);
x['stations'].forEach(y => {
var point_station = {
geometry: {
type: 'Point',
coordinates: [y.lng, y.lat]
},
properties: {
name: y.name,
}
};
var text_station = {
geometry: {
type: 'Point',
coordinates: [y.lng, y.lat],
},
properties: {
name: y.name,
text: y.name,
textColor: '#000',
backgroundColor: '#fff',
},
};
points_station.push(point_station);
texts_station.push(text_station);
});
});
view = new mapvgl.View({
map: map
});
cityLayer = new mapvgl.PointLayer({
blend: 'lighter',
size: 15,
color: 'rgba(227, 29, 120, 0.6)'
});
view.addLayer(cityLayer);
cityLayer.setData(points_city);
view.hideLayer(cityLayer);
stationLayer = new mapvgl.PointLayer({
blend: 'lighter',
size: 15,
color: 'rgba(102, 0, 204, 0.6)'
});
stationLayer.setData(points_station);
view.addLayer(stationLayer);
stationTextLayer = new mapvgl.LabelLayer({
textAlign: 'center',
borderColor: '#fff',
borderWidth: 0,
padding: [2, 5],
borderRadius: 5,
fontSize: 12,
lineHeight: 16,
collides: true, // Whether to enable collision detection , When the quantity is large, it is recommended to open
enablePicked: true,
onClick: e => {
// Click event
console.log('click', e);
},
});
stationTextLayer.setData(texts_station);
view.addLayer(stationTextLayer);
cityTextLayer = new mapvgl.LabelLayer({
textAlign: 'center',
borderColor: '#fff',
borderWidth: 0,
padding: [2, 5],
borderRadius: 5,
fontSize: 12,
lineHeight: 16,
collides: true, // Whether to enable collision detection , When the quantity is large, it is recommended to open
enablePicked: true,
onClick: e => {
// Click event
console.log('click', e);
},
});
cityTextLayer.setData(texts_city);
view.addLayer(cityTextLayer);
view.hideLayer(cityTextLayer);
map.on('zoomend', function () {
var currentZoom = map.getZoom();
if (currentZoom > toggleZoom) {
view.showLayer(stationLayer);
view.showLayer(stationTextLayer);
view.hideLayer(cityLayer);
view.hideLayer(cityTextLayer);
} else {
view.showLayer(cityLayer);
view.showLayer(cityTextLayer);
view.hideLayer(stationLayer);
view.hideLayer(stationTextLayer);
}
});
}
var b = new Base64();
toggleZoom = 10;
async function loaddata(time) {
toggleZoom = 8;
method = "GETREALTIMEMAP";
var points = [];
var obj = {
type: 'aqi',
};
var param = getParam(method, obj);
return $.ajax({
type: "post",
url: "/api",
data: {
param: param
},
success: function (data) {
}
});
}
loaddata=_.memoize(loaddata);
dictRange = {
'so2': [-1, 0, 150, 500, 650, 800,800,800,800],
'no2': [-1, 0, 100, 200, 700, 1200, 2340, 3090, 3840],
'pm10': [-1, 0, 50, 150, 250, 350, 420, 500, 600],
'co': [-1, 0, 5, 10, 35, 60, 90, 120, 150],
'o3': [-1, 0, 160, 200, 300, 400, 800, 1000, 1200],
'pm2_5': [-1, 0, 35, 75, 115, 150, 250, 350, 500],
'aqi': [-1, 0, 50, 100, 150, 200, 300, 400, 500],
};
_.mapObject(dictRange,(v,k)=>{v.pop();v.pop();v.push(Infinity)});
levelColors = ["#808080aa", "#43ce17aa", "#efdc31aa", "#ffaa00aa", "#ff401aaa", "#d20040aa", "#9c0a4eaa"];
function refreshMapV() {
var mode = $('#toggleLabel').data('label');
var factor = $('.radio-group [data-factor].radio-button-checked').data('factor');
loaddata((new Date).getHours()).then(function (data) {
if(data.search('Warning')>=0){
data = data.split('<br />\n')[4];
}
data = eval('(' + b.decode(decryptData(data)) + ')');
console.info(data);
global_province = data.result.data.province.rows;
global_city = data.result.data.city.rows;
$('#timetip').text(` Data time : ${global_city[0].time.slice(0,-3)}`);
var dict_province = _.object(global_province.map(x => {
return [x['provincename'], x]
}));
var dict_city = _.object(global_city.map(x => {
return [x['cityname'], x]
}));
points_city.map(x => {
var name = x.properties['name'];
var properties = dict_province[name];
var colorIndex = _.sortedIndex(dictRange[factor], +properties[factor]);
var color = levelColors[colorIndex - 1].slice(0, 7);
x['properties'] = {
...properties,
...{
'name': name
},
...{
'color': color,
}
};
});
texts_city.map(x => {
var name = x.properties['name'];
var properties = dict_province[name];
var value = +properties[factor];
var text = (mode == 'value' ? value >> 0 : name).toString();
var colorIndex = _.sortedIndex(dictRange[factor], value);
var color = levelColors[colorIndex - 1].slice(0, 7);
x['properties'] = {
...properties,
...{
'name': name
},
...{
'text': text,
'backgroundColor': color,
'textColor': colorIndex < 5 ? '#000' : '#fff',
}
};
});
points_station.map(x => {
var name = x.properties['name'];
var properties = dict_city[name];
var colorIndex = _.sortedIndex(dictRange[factor], +properties[factor]);
var color = levelColors[colorIndex - 1].slice(0, 7);
x['properties'] = {
...properties,
...{
'name': name
},
...{
'color': color,
}
};
});
texts_station.map(x => {
var name = x.properties['name'];
var properties = dict_city[name];
var value = +properties[factor];
var text = (mode == 'value' ? value >> 0 : name).toString();
var colorIndex = _.sortedIndex(dictRange[factor], value);
var color = levelColors[colorIndex - 1].slice(0, 7);
x['properties'] = {
...properties,
...{
'name': name
},
...{
'text': text,
'backgroundColor': color,
'textColor': colorIndex < 5 ? '#000' : '#fff',
}
};
});
cityLayer.setData(points_city);
cityTextLayer.setData(texts_city);
stationLayer.setData(points_station);
stationTextLayer.setData(texts_station);
if (mode == 'none') {
view.removeLayer(cityTextLayer);
view.removeLayer(stationTextLayer);
} else {
view.addLayer(cityTextLayer);
view.addLayer(stationTextLayer);
}
});
}
$(function () {
$('#toggleStyle').click(function () {
var text=$(this).find('span').text();
location.href =(text == ' Diurnal wind ') ? location.pathname+'?style=white' : location.pathname+'?style=dark';
})
$('#toggleLabel').click(function () {
var labelType = $(this).data('label');
if (labelType == 'none') {
$(this).data('label', 'name');
$(this).find('span').text(' Explicit value ');
}
if (labelType == 'value') {
$(this).data('label', 'none');
$(this).find('span').text(' Show your name ');
}
if (labelType == 'name') {
$(this).data('label', 'value');
$(this).find('span').text(' No label ');
}
refreshMapV();
});
$('.radio-group [data-factor]').click(function () {
$('.radio-group [data-factor]').removeClass('radio-button-checked');
$(this).addClass('radio-button-checked');
refreshMapV();
})
loaddata((new Date).getHours()).then(function (data) {
if(data.search('Warning')>=0){
data = data.split('<br />\n')[4];
}
data = eval('(' + b.decode(decryptData(data)) + ')');
console.info(data);
data = data.result.data;
citys = _.chain(data.city.rows).groupBy('provincename').map((x, i) => {
return {
'code': i,
'name': i,
'stations': x.map(y => {
return {
'code': y['cityname'],
'name': y['cityname'],
'lng': y['longitude'],
'lat': y['latitude']
}
})
}
}).value()
initMapV();
refreshMapV();
$('.loader').remove();
setInterval(refreshMapV,1000*60*10);
})
})
边栏推荐
- 如何正确计算导入Excel的行数(POI/NPOI)
- Tinder security cooperates with Intel vPro platform to build a new pattern of software and hardware collaborative security
- What does it mean for AI developers after 2022
- Test article
- 微信小程序之从底部弹出可选菜单
- ICML 2022 𞓜 context integrated transformer based auction design neural network
- [deeply understand tcapulusdb technology] tmonitor module architecture
- Technology creates value and teaches you how to collect wool
- Use openvinotm preprocessing API to further improve the reasoning performance of yolov5
- 微信小程序之在wx:for中绑定事件
猜你喜欢

微信小程序之input调整

The company has only one test, but the leader asked me to operate 1000 mobile numbers at the same time

In depth analysis of mobilenet and its variants

As a software testing practitioner, do you understand your development direction?

The first public available pytorch version alphafold2 is reproduced, and Columbia University is open source openfold, with more than 1000 stars

爱思唯尔-Elsevier期刊的校稿流程记录(Proofs)(海王星Neptune)(遇到问题:latex去掉章节序号)

How do I turn on / off the timestamp when debugging the chrome console?

微信小程序之input前加图标

Technology sharing | do you understand the requirements of the tested project?

【深入理解TcaplusDB技术】TcaplusDB构造数据
随机推荐
微信小程序之获取php后台数据库转化的json
渗透测试-提权专题
Is flush a stock? Is it safe to open an account online now?
Detailed description of Modelsim installation steps
【无标题】
微信小程序之下拉菜单场景
微信小程序之从底部弹出可选菜单
How deci and Intel can achieve up to 16.8x throughput improvement and +1.74% accuracy improvement on mlperf
When did the redo log under InnoDB in mysql start to perform check point disk dropping?
Multi-Camera Detection of Social Distancing Reference Implementation
From the establishment to the actual combat of the robotframework framework, I won't just read this learning note
How to install the DTS component of SQL server2008r2 on win10 64 bit systems?
爱思唯尔-Elsevier期刊的校稿流程记录(Proofs)(海王星Neptune)(遇到问题:latex去掉章节序号)
Test article
微信小程序之flex属性
ts封装请求
Basic use of stacks and queues
【深入理解TcaplusDB技術】TcaplusDB構造數據
Flex attribute of wechat applet
Drop down menu scenario of wechat applet