關(guān)鍵詞:leaflet; geojson; wkt; 分級設(shè)色; 地圖渲染庐椒;顏色映射颅悉;顏色轉(zhuǎn)換衔统;圖例
案例需求:各省級專題數(shù)據(jù)分級設(shè)色
數(shù)據(jù)準備:1.地圖數(shù)據(jù)geojson格式(https://geo.datav.aliyun.com/areas_v2/bound/100000_full.json)來源:http://datav.aliyun.com/portal/school/atlas/area_selector
2.專題數(shù)據(jù)提针,通過隨機數(shù)生成
示例
<!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>leaflet分層渲染</title>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<link rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/leaflet/1.7.1/leaflet.min.js"></script>
<style>
body{
width: calc(100vw);
height: calc(100vh);
padding: 0;
margin: 0;
}
.map{
width: 100%;
height: 100%;
background-color: #fff;
}
.legend{
position: absolute;
right: 20px;
bottom: 20px;
z-index: 999;
}
.legend ul li{
padding:0;
margin:0;
list-style:none;
display: flex;
align-items: center;
margin-bottom: 5px;
}
.legend ul li i{
display: inline-block;
width: 20px;
height: 20px;
border-radius: 50%;
margin-right: 5px;
}
</style>
</head>
<body onload="init()">
<div id="map" class="map"></div>
<div class="legend"></div>
</body>
<script>
let map;
let separatedColors = ['#DAF7A6', '#FFC300', '#FF5733', '#C70039', '#900C3F', '#581845'];//離散顏色
let minVal = 1;
let maxVal = 100;
function init(){
initMap();
initLegend();
}
function initMap(){
map = L.map('map', {
crs: L.CRS.EPSG4326,
center: [40.83, 113.31],
zoom: 3,
zoomControl: true
});
let vecUrl = 'http://t0.tianditu.gov.cn/DataServer?T=vec_c&X={x}&Y={y}&L={z}&tk=c04e7575a1f250c6f22ba42fa9c8aa63';
let baseLayer = L.tileLayer(vecUrl, {zoomOffset: 1});
map.addLayer(baseLayer)
let url = 'https://geo.datav.aliyun.com/areas_v2/bound/100000_full.json';
axios.get(url).then(res => {
let geojson = res.data;
L.geoJSON(geojson, {
onEachFeature: function(feature, layer){
//生成1-100的隨機整數(shù)藕甩,作為每個要素的某一專題屬性值
feature.properties.value = random(1, 100);
feature.properties.color = getSeparatedColorByVal(minVal, maxVal, separatedColors, feature.properties.value);
layer.setStyle({
stroke: false,//取消邊框
color: feature.properties.color,
fillOpacity: 0.6//默認0.2
});
}
}).addTo(map);
});
}
//初始化圖例
function initLegend(){
let legend = getLegend(minVal, maxVal, separatedColors);
let legendDom = document.getElementsByClassName('legend')[0];
let insertDom = document.createElement('ul');
let str = ``;
for(let i = 0; i < legend.length; i++){
str += `<li><i style="background: ${legend[i].color}"></i>${legend[i].region.join('-')}</li>`;
}
insertDom.innerHTML = str;
legendDom.appendChild(insertDom);
}
//生成指定范圍的隨機整數(shù)
function random(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
//根據(jù)離散顏色及數(shù)據(jù)范圍生成對應(yīng)值的顏色
function getSeparatedColorByVal(minVal, maxVal, colors, val){
let length = colors.length;
let avg = ((maxVal - minVal)/length).toFixed(4);
//生成等分區(qū)間
let regions = [];
for(let i = 0; i < length; i++){
if(i === length -1){
regions.push([(minVal + avg * i), maxVal]);
}else{
regions.push([(minVal + avg * i), (minVal + avg * (i + 1))]);
}
}
//返回對應(yīng)值顏色
for(let i = 0; i < regions.length; i++){
if(val >= regions[i][0] && val <= regions[i][1]){
return colors[i];
}
}
}
//生成圖例
function getLegend(minVal, maxVal, colors){
let length = colors.length;
let avg = ((maxVal - minVal)/length).toFixed(4);
//生成等分區(qū)間
let regions = [];
for(let i = 0; i < length; i++){
if(i === length -1){
regions.push([(minVal + avg * i).toFixed(2), maxVal.toFixed(2)]);
}else{
regions.push([(minVal + avg * i).toFixed(2), (minVal + avg * (i + 1)).toFixed(2)]);
}
}
let legend = [];
for(let i = 0; i< length; i++){
legend.push({
color: colors[i],
region: regions[i]
});
}
return legend;
}
</script>
</html>
效果
渲染效果
以上使用的離散顏色數(shù)組渲染施敢,生成連續(xù)顏色可使用如下方法
//根據(jù)數(shù)值范圍、顏色范圍(16進制類型)狭莱,獲取數(shù)值范圍中某一數(shù)值對應(yīng)顏色范圍中的顏色
//顏色要求:選擇相鄰色系
function getContinuationColorByVal(minVal, maxVal, firstColor, secondColor, val){
let ratio = (val-minVal)/(maxVal - minVal);
let fArr = hex2RgbArr(firstColor);
let sArr = hex2RgbArr(secondColor);
let color = [];
for(let i = 0; i < fArr.length; i++){
let c = (fArr[i]<sArr[i]?fArr[i]:sArr[i]) + Math.abs(((sArr[i]-fArr[i])*ratio).toFixed(0));
color.push(c);
}
return rgbArr2Hex(color);
}
//16進制顏色轉(zhuǎn)rgb顏色數(shù)組
function hex2RgbArr(hex){
// 16進制顏色值的正則
var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
// 把顏色值變成小寫
var color = hex.toLowerCase();
if (reg.test(color)) {
// 如果只有三位的值僵娃,需變成六位,如:#fff => #ffffff
if (color.length === 4) {
var colorNew = '#';
for (var i = 1; i < 4; i += 1) {
colorNew += color.slice(i, i + 1).concat(color.slice(i, i + 1));
}
color = colorNew;
}
// 處理六位的顏色值腋妙,轉(zhuǎn)為RGB
var colorChange = [];
for (var i = 1; i < 7; i += 2) {
colorChange.push(parseInt('0x' + color.slice(i, i + 2)));
}
return colorChange;
}
}
//rgb顏色數(shù)組[255, 255, 255]轉(zhuǎn)16進制顏色#ffffff
function rgbArr2Hex(rgbArr){
let strHex = '#';
// 轉(zhuǎn)成16進制
for (var i = 0; i < rgbArr.length; i++) {
let hex = Number(rgbArr[i]).toString(16);
hex = hex.length == 1 ? '0' + hex : hex;
strHex += hex;
}
return strHex;
}
實際開發(fā)默怨,地圖要素范圍數(shù)據(jù)可能后端返回wkt類型數(shù)據(jù),wkt數(shù)據(jù)轉(zhuǎn)換layer圖層骤素,需用leaflet插件leaflet-omnivore
//wkt轉(zhuǎn)leaflet layer
wkt2Layer(wktShape) {
if(!!wktShape){
var geoJson = omnivore.wkt.parse(wktShape);
let feature = geoJson.getLayers()[0].feature;
return L.GeoJSON.geometryToLayer(feature);
}
}
參考資料:
https://blog.csdn.net/mossbaoo/article/details/93484635
https://htmlcolorcodes.com/zh/yanse-xuanze-qi/
http://datav.aliyun.com/tools/atlas/#&lat=30.37018632615852&lng=106.68898666525287&zoom=3.5
http://www.reibang.com/p/1cbfa0ed2051