当前位置:网站首页>maptalks:数据归一化处理与分层设色图层加载
maptalks:数据归一化处理与分层设色图层加载
2022-06-24 19:03:00 【似曾不相识】
功能需求
在地图功能开发过程中,有根据区划统计数值,实现分层设色的需求。如:有以下人口总数统计数据(其中AREA表示行政区划编码,POPDENSITY表示人口总数数值),现在需要根据人口总数,实现分层设色,来对人口空间分布特征进行可视化展示。
{
"msg": "返回成功",
"data": [
{
"AREA": "310101", "POPDENSITY": 32295 },
{
"AREA": "310104", "POPDENSITY": 20177 },
{
"AREA": "310105", "POPDENSITY": 18651 },
{
"AREA": "310106", "POPDENSITY": 26533 },
{
"AREA": "310107", "POPDENSITY": 22325 },
{
"AREA": "310109", "POPDENSITY": 32387 },
{
"AREA": "310110", "POPDENSITY": 20517 },
{
"AREA": "310112", "POPDENSITY": 7115 },
{
"AREA": "310113", "POPDENSITY": 7407 },
{
"AREA": "310114", "POPDENSITY": 3960 },
{
"AREA": "310115", "POPDENSITY": 4071 },
{
"AREA": "310116", "POPDENSITY": 1356 },
{
"AREA": "310117", "POPDENSITY": 3158 },
{
"AREA": "310118", "POPDENSITY": 1902 },
{
"AREA": "310120", "POPDENSITY": 1597 },
{
"AREA": "310151", "POPDENSITY": 470 }
]
}
实现思路
色带选取
分层设色,实质上就是根据不同的权重值,来选择不同轻重程度的数量值,通过颜色的变化,来反映数值的变化。映射到地理空间,就是为了展示数值在空间分布上的变化情况。色带如何选择?可以点击此处,通过Color Blender在线工具生成。以下是我设计的色带,对应的颜色代码数组如下,长度为10,
const colortable_3 = [
"#FFFFCC",
"#FFF1B9",
"#FFE3A7",
"#FFD594",
"#FFC782",
"#FFB96F",
"#FFAC5D",
"#FF9E4A",
"#FF9038",
"#FF8225",
"#FF7413",
"#FF6600"
]

数据处理
如何将统计数据映射到色彩空间呢?由于色带数组长度为10,所以,可以先将原始数据做归一化处理,再将处理结果乘以10,向下取整,将计算结果作为colortable_3 数组的下标索引值,取到对应的16进制颜色代码。
通过上述先归一化、再缩放的处理方式,即可将原始数据的变化映射到色彩空间的颜色变化。
计算公式如下,
核心代码
对应的核心计算代码,实现如下,
/** * 加载上海市行政区划图-人口密度分层设色图 * */
function loadSH_map(_map, _layerName, _dataSource, _boundValue, _colorTable = colortable_1) {
let collection = new Array();
// 遍历_dataSource数据源-重新设置symbol属性值
_dataSource.some(function(value, index, array) {
//获取行政区划编码
let code = value.properties.adcode;
//根据code获取对应的NUM值
let curValue = getValueByAreaCode(code, _boundValue);
//计算归一化值-整型数值
let normalizationValue = Math.floor((curValue.POPDENSITY - _boundValue.min.POPDENSITY) / (_boundValue.max.POPDENSITY - _boundValue.min.POPDENSITY) * (_colorTable.length - 1));
console.log(normalizationValue)
//获取颜色表取值
let fillColor = _colorTable[normalizationValue];
//获取坐标数组
let coordinates = value.geometry.coordinates;
console.log(coordinates)
//构造polygon多边形对象
let polygon = new maptalks.MultiPolygon(coordinates, {
visible: true,
editable: true,
cursor: 'pointer',
shadowBlur: 0,
shadowColor: 'black',
draggable: false,
dragShadow: false, // display a shadow during dragging
drawOnAxis: null, // force dragging stick on a axis, can be: x, y
symbol: {
'lineColor': '#34495e',
'lineWidth': 2,
'polygonFill': fillColor,
'polygonOpacity': 1
}
});
collection.push(polygon);
})
new maptalks.VectorLayer('vector', new maptalks.GeometryCollection(collection))
.addTo(_map);
}
/** * 根据行政区划编码获取对应的NUM值 * */
function getValueByAreaCode(_code, _boundValue) {
let result = boundValue.min;
for (let i = 0; i < polulation.length; i++)
if (polulation[i].AREA == _code) {
result = polulation[i];
break;
}
return result;
}
完整示例代码
以下为完整代码实现,如何对地理空间进行可视化呢?在此,选用maptalks二三维一体可视化平台,示例代码如下,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>上海市分层设色</title>
<!-- style内联样式 -->
<style type="text/css">
html,
body {
margin: 0px;
height: 100%;
width: 100%
}
.container {
width: 100%;
height: 100%;
}
/* 隐藏maptalks底部文字属性 */
.maptalks-attribution {
display: none;
}
</style>
<!-- 引入maptalks资源 -->
<link href="./plugins/maptalks.css" />
<script src="./plugins/maptalks.js"></script>
<!-- jquery -->
<script src="./plugins/jquery-3.2.1.min.js"></script>
<!-- 引入arcgis开发包 -->
<script src="./plugins/arcgis/maptalks.arcgis.min.js"></script>
</head>
<body>
<div id="map" class="container"></div>
</body>
<script>
//创建基础图层
let baseLayer = new maptalks.TileLayer('base', {
urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
subdomains: ['a', 'b', 'c', 'd'],
// attribution: '© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>',
// css filter
cssFilter: 'sepia(100%) invert(90%)',
opacity: 0.95, // TileLayer's opacity, 0-1
})
//初始化maptalks
var map = new maptalks.Map('map', {
center: [121.467, 31.0334],
zoom: 10,
minZoom: 1, // set map's min zoom to 14
maxZoom: 14, // set map's max zoom to 14
// 拖动倾斜旋转参数
//allow map to drag pitching, true by default
dragPitch: true, //禁用抬起/相机pitch角度切换
//allow map to drag rotating, true by default
dragRotate: true, //false-禁用旋转
//enable map to drag pitching and rotating at the same time, false by default
dragRotatePitch: true, //
doubleClickZoom: false, //取消鼠标双击放大效果
baseLayer: baseLayer,
});
//挂载图层
map.configLayers = {
base_layer: baseLayer, //基础底图图层
sh_layer: undefined, //基础矢量图层
hhypsometric_layer: undefined, //热力图图层
};
//颜色表
const colortable_3 = [
"#FFFFCC",
"#FFF1B9",
"#FFE3A7",
"#FFD594",
"#FFC782",
"#FFB96F",
"#FFAC5D",
"#FF9E4A",
"#FF9038",
"#FF8225",
"#FF7413",
"#FF6600"
]
//获取人口数据+上海行政区划数据
let polulation = getDataSource("people_num").data;
let sh_dataSource = getDataSource("shanghai").features
let sh_textSource = getDataSource("shanghai");
//获取人口边界数据
let boundValue = deal_populationData(polulation)
//加载sh行政区划数据
loadSH_map(map, "sh_layer", sh_dataSource, boundValue, colortable_3);
//文字注记
initMarker(map, sh_textSource);
/** * 初始化中心标记点 * */
function initMarker(_map, _dataSource) {
//json转为geometry
let geometries = maptalks.GeoJSON.toGeometry(_dataSource);
let shptArray = new Array();
//遍历geometries-添加中心标记点
geometries.some(function(value, index, array) {
let properties = value.properties; //获取属性数据
shptArray.push(
new maptalks.Marker(properties.center, {
id: properties.name,
visible: true,
editable: true,
cursor: 'pointer',
shadowBlur: 0,
shadowColor: 'black',
draggable: false,
dragShadow: false, // display a shadow during dragging
drawOnAxis: null, // force dragging stick on a axis, can be: x, y
symbol: {
'textFaceName': 'sans-serif',
'textName': properties.name,
'textFill': '#fffff',
'textHorizontalAlignment': 'right',
'textSize': 16
},
properties: {
altitude: 2500,
properties: properties
}
})
)
})
//创建geometryCollection集合
//添加marker集合到VectorLayer中
new maptalks.VectorLayer('vector_Marker', new maptalks.GeometryCollection(shptArray, {
})).addTo(_map);
}
/** * 加载上海市行政区划图-人口密度分层设色图 * */
function loadSH_map(_map, _layerName, _dataSource, _boundValue, _colorTable = colortable_1) {
let collection = new Array();
// 遍历_dataSource数据源-重新设置symbol属性值
_dataSource.some(function(value, index, array) {
//获取行政区划编码
let code = value.properties.adcode;
//根据code获取对应的NUM值
let curValue = getValueByAreaCode(code, _boundValue);
//计算归一化值-整型数值
let normalizationValue = Math.floor((curValue.POPDENSITY - _boundValue.min.POPDENSITY) / (_boundValue.max.POPDENSITY - _boundValue.min.POPDENSITY) * (_colorTable.length - 1));
console.log(normalizationValue)
//获取颜色表取值
let fillColor = _colorTable[normalizationValue];
//获取坐标数组
let coordinates = value.geometry.coordinates;
console.log(coordinates)
//构造polygon多边形对象
let polygon = new maptalks.MultiPolygon(coordinates, {
visible: true,
editable: true,
cursor: 'pointer',
shadowBlur: 0,
shadowColor: 'black',
draggable: false,
dragShadow: false, // display a shadow during dragging
drawOnAxis: null, // force dragging stick on a axis, can be: x, y
symbol: {
'lineColor': '#34495e',
'lineWidth': 2,
'polygonFill': fillColor,
'polygonOpacity': 1
}
});
collection.push(polygon);
})
new maptalks.VectorLayer('vector', new maptalks.GeometryCollection(collection))
.addTo(_map);
}
/** * 根据行政区划编码获取对应的NUM值 * */
function getValueByAreaCode(_code, _boundValue) {
let result = boundValue.min;
for (let i = 0; i < polulation.length; i++)
if (polulation[i].AREA == _code) {
result = polulation[i];
break;
}
return result;
}
//人口数据处理
function deal_populationData(_population) {
let boundValue = {
};
let minTemp = _population[0],
maxTemp = _population[0];
//计算最大最小值
_population.some(function(value, index, array) {
minTemp.POPDENSITY > value.POPDENSITY ? minTemp = value : "";
maxTemp.POPDENSITY < value.POPDENSITY ? maxTemp = value : "";
})
return boundValue = {
min: minTemp,
max: maxTemp
}
}
/** * 获取数据源 * */
function getDataSource(_dataSource) {
let dataSource = undefined;
$.ajax({
url: "./data/" + _dataSource + ".json",
method: "GET",
async: false,
success: function(result, text, xhr) {
//GeoJSON utilities-Convert one or more GeoJSON objects to geometry
dataSource = result;
}
});
return dataSource;
}
</script>
</html>
最终效果
最终显示效果如下,
边栏推荐
- Using dynamic time warping (DTW) to solve the similarity measurement of time series and the similarity identification analysis of pollution concentration in upstream and downstream rivers
- redis数据结构之压缩列表
- 科技抗疫: 运营商网络洞察和实践白皮书 | 云享书库NO.20推荐
- Database index can improve query efficiency. Ask what will improve, what is the difference between inapplicable index and index use, and what will happen.
- Two fellow countrymen from Hunan have jointly launched a 10 billion yuan IPO
- 图像PANR
- Ribbon源码分析之@LoadBalanced与LoadBalancerClient
- 2022年最新四川建筑八大员(电气施工员)模拟题库及答案
- Docker installing Oracle
- 开放可编程基础设施(OPI)项目,重新定义DPU/IPU
猜你喜欢

Nodered has no return value after successfully inserting into the database (the request cannot be ended)

Install the custom module into the system and use find in the independent project_ Package found

Two fellow countrymen from Hunan have jointly launched a 10 billion yuan IPO

苹果、微软、谷歌不再掐架,今年要合力干一件大事

Basic operation of sequence table

The latest simulated question bank and answers of the eight members (Electrical constructors) of Sichuan architecture in 2022

Win7 10 tips for installing Office2010 five solutions for installing MSXML components

Audio and video 2020 2021 2022 basic operation and parameter setting graphic tutorial

Otaku can't save yuan universe

实现基于Socket自定义的redis简单客户端
随机推荐
Install the custom module into the system and use find in the independent project_ Package found
Two solutions to the problem of 0xv0000225 unable to start the computer
C语言实现扫雷(简易版)
二叉树的基本性质与遍历
天天鉴宝暴雷背后:拖欠数千万、APP停摆,创始人预谋跑路?
Showcase是什么?Showcase需要注意什么?
Microsoft Office Excel 2013 2016 graphic tutorial on how to enable macro function
基于QT+MySQL的相机租赁管理系统
It is said that Tencent officially announced the establishment of "XR" department to bet on yuanuniverse; Former CEO of Google: the United States is about to lose the chip competition. We should let T
Stop using system Currenttimemillis() takes too long to count. It's too low. Stopwatch is easy to use!
Bytebase rejoint la communauté de base de données open source d'alicloud polardb
OpenVINO2022 Dev Tools安装与使用
Bytebase加入阿里云PolarDB开源数据库社区
Uninstall tool v3.5.10.5670 single file portable official version
[suggested collection] time series prediction application and paper summary
网络安全审查办公室对知网启动网络安全审查,称其“掌握大量重要数据及敏感信息”
Internet of things? Come and see Arduino on the cloud
Docker installing Oracle
首个大众可用PyTorch版AlphaFold2复现,哥大开源OpenFold,star量破千
C language to realize mine sweeping (simple version)