- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
这是一篇由浅入深的AntV L7的学习笔记总结,记述了从了解到使用的一些过程 。
本文所使用的数据(包括数据处理过程)和代码均有详细描述,所有案例均可复现,甚至大部分代码可直接使用 。
如果喜欢分页阅读,可以参考下列目录:
因笔者水平有限,如有错误,敬请指正 。
L7 地理空间数据可视分析引擎是一种基于 WebGL 技术的地理空间数据可视化引擎,可以用于实现各种地理空间数据可视化应用。L7 引擎支持多种数据源和数据格式,包括 GeoJSON、CSV等,可以快速加载和渲染大规模地理空间数据。L7 引擎还提供了丰富的可视化效果和交互功能,包括热力图、等高线图、鼠标交互等,可以帮助用户更好地理解和分析地理空间数据 。
L7 官网: 蚂蚁地理空间数据可视化 | AntV (antgroup.com) 。
L7 GitHub 仓库: antvis/L7: 🌎 Large-scale WebGL-powered Geospatial Data Visualization analysis engine (github.com) 。
L7 官方教程: 简介 | L7 (antgroup.com) 。
L7 官方示例: 所有图表 | L7 (antgroup.com) 。
L7 API文档: 场景 Scene | L7 (antgroup.com) 。
L7的主要特点是使用WebGL绘制地图数据,此处主要描述的是L7作为前端GIS库基础功能使用 。
通过CDN的方式可以快速引入L7:
<script src = 'https://unpkg.com/@antv/l7'></script>
通过NPM的方式引入L7可参考:
npm install @antv/l7
简单起见,下面使用CDN方式引入 。
加载地图:
<!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>Document</title>
<script src='https://unpkg.com/@antv/l7'></script>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.GaodeMap({
style: 'dark',
center: [110.770672, 34.159869]
}),
});
</script>
</body>
</html>
结果如下:
L7内置了高德底图API,测试环境下可以直接使用 。
通常,使用栅格瓦片作为底图, L7 的栅格图层支持加载 TMS 、 WMS 、 WMTS 等多种格式的图片瓦片 。
<!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>Document</title>
<script src='https://unpkg.com/@antv/l7'></script>
<style>
body,
#map {
height: 100vh;
width: 100vw;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.Map({
center: [110.770672, 34.159869],
zoom: 4
}),
});
const url1 =
'https://t0.tianditu.gov.cn/img_w/wmts?tk=b72aa81ac2b3cae941d1eb213499e15e&';
const layer1 = new L7.RasterLayer({
zIndex: 1,
}).source(url1, {
parser: {
type: 'rasterTile',
tileSize: 256,
wmtsOptions: {
layer: 'img',
tileMatrixset: 'w',
format: 'tiles',
},
},
});
scene.on('loaded', () => {
scene.addLayer(layer1);
});
</script>
</body>
</html>
结果如下:
L7支持 GeoJSON 数据 。
<!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>Document</title>
<script src='https://unpkg.com/@antv/l7'></script>
<style>
body,
#map {
height: 100vh;
width: 100vw;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.GaodeMap({
center: [116.3956, 39.9392],
zoom: 10,
style: 'dark'
})
});
scene.on('loaded', () => {
fetch(
'https://gw.alipayobjects.com/os/basement_prod/0d2f0113-f48b-4db9-8adc-a3937243d5a3.json'
)
.then(res => res.json())
.then(data => {
const layer = new L7.LineLayer({})
.source(data)
scene.addLayer(layer);
});
});
</script>
</body>
</html>
结果如下:
Marker标注是地图上用来标记信息的常用组件 。
<!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>Document</title>
<script src='https://unpkg.com/@antv/l7'></script>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.GaodeMap({
style: 'light',
center: [110.770672, 34.159869]
}),
});
const marker = new L7.Marker({
color: '#f00'
}).setLnglat([110.770672, 34.159869]);
scene.addMarker(marker);
</script>
</body>
</html>
结果如下:
Popup弹窗是地图上用来显示信息的常用组件 。
<!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>Document</title>
<script src='https://unpkg.com/@antv/l7'></script>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.GaodeMap({
style: 'light',
center: [110.770672, 34.159869]
}),
});
const popup = new L7.Popup({
title: '自定义标题',
html: '<p>Popup 示例的自定义内容</p>',
lngLat: {
lng: 110.770672,
lat: 34.159869,
},
});
scene.addPopup(popup);
</script>
</body>
</html>
结果如下:
L7支持事件鼠标点击、双击等事件监听 。
<!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>Document</title>
<script src='https://unpkg.com/@antv/l7'></script>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.GaodeMap({
style: 'light',
center: [110.770672, 34.159869]
}),
});
setTimeout(() => {
scene.on('click', (e) => {
console.log(e) // 鼠标左键点击事件
const marker = new L7.Marker({
color: '#f00'
}).setLnglat([e.lnglat.lng, e.lnglat.lat]);
scene.addMarker(marker);
});
}, 1000);
// scene.on('click', (e) => {console.log(e)}); // 直接监听click事件会报错
</script>
</body>
</html>
结果如下:
在使用地图时,常常需要使用缩放、比例尺等控件 。
<!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>Document</title>
<script src='https://unpkg.com/@antv/l7'></script>
<style>
body,
#map {
height: 100vh;
width: 100vw;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.GaodeMap({
center: [116.3956, 39.9392],
zoom: 10,
style: 'light'
})
});
scene.on('loaded', () => {
const zoom = new L7.Zoom();
scene.addControl(zoom);
const scale = new L7.Scale();
scene.addControl(scale);
});
</script>
</body>
</html>
结果如下:
综上基础功能案例,不难发现L7满足GIS前端库的基本要求,和经典的GIS前端库(如,Leaflet等)相比,还具有开箱即用、API友好、绘制效果好等优势 。
L7的整体架构大致总结如下:
Vue是常用的前端框架,TypeScript(简称TS) 是 JavaScript 的超集,可以提高代码的可维护性和可读性 。
下面记述基于Vite、Vue3和TypeScript搭建L7开发环境并示例 。
这里使用Vue 官方的项目脚手架工具创建Vue开发环境(其他方式也可,如直接使用Vite创建) 。
在CMD(或Shell)中,切换到存放代码的目录,并执行:
npm init vue@latest
接着选择一系列创建选项,通常默认即可:
Need to install the following packages:
create-vue@3.6.4
Ok to proceed? (y) y
Vue.js - The Progressive JavaScript Framework
√ Project name: ... L7Test
√ Package name: ... l7test
√ Add TypeScript? ... No / Yes
√ Add JSX Support? ... No / Yes
√ Add Vue Router for Single Page Application development? ... No / Yes
√ Add Pinia for state management? ... No / Yes
√ Add Vitest for Unit Testing? ... No / Yes
√ Add an End-to-End Testing Solution? » No
√ Add ESLint for code quality? ... No / Yes
Scaffolding project in E:\Code\test\L7Test...
Done. Now run:
cd L7Test
npm install
npm run dev
然后根据提示依次执行命令:
cd L7Test
npm install
npm run dev
一个Vue模板就搭建完成:
使用VS Code(其他也可)打开刚刚创建的项目,删除掉 src/components 下的默认文件,并清除 App.vue 的默认内容:
在Terminal(CMD或Shell也可)中安装L7:
npm install @antv/l7
在 App.vue 中编写代码加载L7地图:
<script setup lang="ts">
import { Scene } from "@antv/l7";
import { GaodeMap } from "@antv/l7-maps";
const scene = new Scene({
id: "map",
map: new GaodeMap({
center: [120.19382669582967, 30.258134],
pitch: 0,
style: "dark",
zoom: 10,
}),
});
</script>
<template>
<div id="map"></div>
</template>
<style scoped>
#map {
height: 100%;
width: 100%;
}
</style>
结果如下:
至此环境安装完成 。
官方示例: 所有图表 | L7 (antgroup.com) ,基本演示了绝大部分的图表,并且示例代码和上述 App.vue 中的 script 标签下差不多,可以直接复制使用,如下图所示:
直接将示例中的代码复制到 App.vue 的 script 中即可运行:
<script setup lang="ts">
import { Scene, PointLayer } from '@antv/l7';
import { GaodeMap } from '@antv/l7-maps';
const scene = new Scene({
id: 'map',
map: new GaodeMap({
style: 'dark',
center: [ 121.417463, 31.215175 ],
zoom: 11
})
});
scene.on('loaded', () => {
fetch('https://gw.alipayobjects.com/os/rmsportal/BElVQFEFvpAKzddxFZxJ.txt')
.then(res => res.text())
.then(data => {
const pointLayer = new PointLayer({})
.source(data, {
parser: {
type: 'csv',
y: 'lat',
x: 'lng'
}
})
.size(0.5)
.color('#080298');
scene.addLayer(pointLayer);
});
});
</script>
<template>
<div id="map"></div>
</template>
<style scoped>
#map {
height: 100%;
width: 100%;
}
</style>
结果如下:
具体函数API的使用,可以查阅API手册: 场景 Scene | L7 (antgroup.com) 。
官网示例图表,均可用上述方式移植到项目中使用 。
下面记述使用L7对全球AQI数据进行可视化 。
全球AQI数据可从这个网站获取: World's Air Pollution: Real-time Air Quality Index (waqi.info) 。
进入这个网站后打开控制台,刷新网页重新加载,找到 000.json 。
在 000.json 上右键并 在新标签页中打开 :
在新标签页中右键并 另存为 :
即可获得JSON数据 。
可参考官方散点图样例: 简单点 | L7 (antgroup.com) 。
加载高德地图 。
<!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>Document</title>
<script src='https://unpkg.com/@antv/l7'></script>
<style>
body,
#map {
height: 100vh;
width: 100vw;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.GaodeMap({
center: [116.3956, 39.9392],
zoom: 2,
style: 'light'
})
});
</script>
</body>
</html>
根据数据内容,将经纬度数组转置以符合L7的数据格式:
scene.on('loaded', () => {
fetch('./000.json')
.then(res => res.json())
.then(data => {
data = data.stations
data.forEach(item => {
item.g.reverse()
})
console.log(data);
})
});
绘制点图层,并设置样式:
const layer = new L7.PointLayer()
.source(data, {
parser: {
type: 'json',
coordinates: 'g'
}
})
.shape('circle')
.color('a', (value) => {
// 大于0小于50的绿色
if (value > 0 && value < 50) {
return '#00ff00'
} else if (value > 50 && value < 100) {
// 大于50小于100的蓝色
return '#0000ff'
} else if (value > 100) {
// 大于100的红色
return '#ff0000'
}
})
.size('a', (value) => {
// 根据value值设置点的大小
let a = value / 100 + 2;
return a;
})
.active(true);
scene.addLayer(layer);
完整代码如下:
<!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>Document</title>
<script src='https://unpkg.com/@antv/l7'></script>
<style>
body,
#map {
height: 100vh;
width: 100vw;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.GaodeMap({
center: [116.3956, 39.9392],
zoom: 2,
style: 'light'
})
});
scene.on('loaded', () => {
fetch('./000.json')
.then(res => res.json())
.then(data => {
data = data.stations
data.forEach(item => {
item.g.reverse()
})
// console.log(data);
const layer = new L7.PointLayer()
.source(data, {
parser: {
type: 'json',
coordinates: 'g'
}
})
.shape('circle')
.color('a', (value) => {
// 大于0小于50的绿色
if (value > 0 && value < 50) {
return '#00ff00'
} else if (value > 50 && value < 100) {
// 大于50小于100的蓝色
return '#0000ff'
} else if (value > 100) {
// 大于100的红色
return '#ff0000'
}
})
.size('a', (value) => {
// 根据value值设置点的大小
let a = value / 100 + 2;
return a;
})
.active(true);
scene.addLayer(layer);
});
});
</script>
</body>
</html>
下面记述使用L7对路网数据进行可视化 。
路网数据可以从以下网站下载,数据来源自OSM: Index of /extracts (openstreetmap.fr) 。
其中,中国的路网数据可以从这个下载: Index of /extracts/asia/china (openstreetmap.fr) 。
笔者这里下载上海的数据: http://download.openstreetmap.fr/extracts/asia/china/shanghai.osm.pbf 。
下载好以后可以直接拖入QGIS中:
Lines
,数据量较大,绘制卡顿。且路网质量也欠佳 在图层上右键选择 导出 :
导出为 GeoJSON :
导出的数据尺寸为84 MB,至此数据获取完成 。
可参考官方路网图样例: 路径地图 | L7 (antgroup.com) 。
加载高德地图 。
<!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>Document</title>
<script src='https://unpkg.com/@antv/l7'></script>
<style>
body,
#map {
height: 100vh;
width: 100vw;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.GaodeMap({
center: [116.3956, 39.9392],
zoom: 2,
style: 'light'
})
});
</script>
</body>
</html>
加载数据,L7对于GeoJSON无需额外设置解析器:
scene.on('loaded', () => {
fetch('./lines.geojson')
.then(res => res.json())
.then(data => {
console.log(data);
})
});
绘制线图层,并设置样式:
const layer = new L7.LineLayer({
zIndex: 2,
})
.source(data)
.size(0.5)
.active(true)
.color('highway', (type) => {
switch (type) {
case "bridleway" :
return '#c81841';
case "bus_guideway" :
return '#39a0cc';
case "bus_stop" :
return '#0d70cc';
case "busway" :
return '#d385dd';
case "construction" :
return '#30e5dc';
case "corridor" :
return '#ca6166';
case "cycleway" :
return '#c94534';
case "elevator" :
return '#c3ee79';
case "footway" :
return '#df7f53';
case "living_street" :
return '#0d2dce';
case "motorway" :
return '#c8659f';
case "motorway_link" :
return '#15d066';
case "path" :
return '#cab646';
case "pedestrian" :
return '#2ddb95';
case "planned" :
return '#36cd25';
case "platform" :
return '#d99b1f';
case "primary" :
return '#75cc53';
case "primary_link" :
return '#e31eb2';
case "proposed" :
return '#4e2bec';
case "raceway" :
return '#c8721c';
case "residential" :
return '#6ced77';
case "road" :
return '#57e079';
case "secondary" :
return '#2063e9';
case "secondary_link" :
return '#7aec1d';
case "service" :
return '#58d9ed';
case "services" :
return '#1fe3b9';
case "steps" :
return '#e010d2';
case "tertiary" :
return '#adca37';
case "tertiary_link" :
return '#d0d32e';
case "track" :
return '#e04684';
case "trunk" :
return '#b232e4';
case "trunk_link" :
return '#822dcd';
case "unclassified" :
return '#a686de';
case "null" :
return '#1f1bef';
case "" :
return '#beb297';
default:
return '#beb297';
}
});
scene.addLayer(layer);
});
完整代码如下:
<!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>Document</title>
<script src='https://unpkg.com/@antv/l7'></script>
<style>
body,
#map {
height: 100vh;
width: 100vw;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.GaodeMap({
center: [116.3956, 39.9392],
zoom: 2,
style: 'dark'
})
});
scene.on('loaded', () => {
fetch('./lines.geojson')
.then(res => res.json())
.then(data => {
const layer = new L7.LineLayer({
zIndex: 2,
})
.source(data)
.size(0.5)
.active(true)
.color('highway', (type) => {
switch (type) {
case "bridleway" :
return '#c81841';
case "bus_guideway" :
return '#39a0cc';
case "bus_stop" :
return '#0d70cc';
case "busway" :
return '#d385dd';
case "construction" :
return '#30e5dc';
case "corridor" :
return '#ca6166';
case "cycleway" :
return '#c94534';
case "elevator" :
return '#c3ee79';
case "footway" :
return '#df7f53';
case "living_street" :
return '#0d2dce';
case "motorway" :
return '#c8659f';
case "motorway_link" :
return '#15d066';
case "path" :
return '#cab646';
case "pedestrian" :
return '#2ddb95';
case "planned" :
return '#36cd25';
case "platform" :
return '#d99b1f';
case "primary" :
return '#75cc53';
case "primary_link" :
return '#e31eb2';
case "proposed" :
return '#4e2bec';
case "raceway" :
return '#c8721c';
case "residential" :
return '#6ced77';
case "road" :
return '#57e079';
case "secondary" :
return '#2063e9';
case "secondary_link" :
return '#7aec1d';
case "service" :
return '#58d9ed';
case "services" :
return '#1fe3b9';
case "steps" :
return '#e010d2';
case "tertiary" :
return '#adca37';
case "tertiary_link" :
return '#d0d32e';
case "track" :
return '#e04684';
case "trunk" :
return '#b232e4';
case "trunk_link" :
return '#822dcd';
case "unclassified" :
return '#a686de';
case "null" :
return '#1f1bef';
case "" :
return '#beb297';
default:
return '#beb297';
}
});
scene.addLayer(layer);
});
});
</script>
</body>
</html>
下面记述使用L7对长沙岳麓山景点游客轨迹数据进行可视化并构建三维路网的综合案例 。
路网数据可以从以下网站下载,数据来源自六只脚: 六只脚_GPS轨迹记录_户外自助游_自助游线路 (foooooot.com) 。
具体的轨迹获取教程可以参考: GPS地图生成03之数据获取 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com) 。
下载好以后可以在QGIS中利用加载XY文件的方式加载all.csv文件,并设置OSM底图,预览GPS轨迹:
数据文件尺寸为47.2 M,有892152条轨迹数据,至此数据获取完成 。
数据文件内容示例为:
id,lng,lat,ele,track,time
0,112.938652777778,28.1828777777778,52.5862003780718,1448263,1511330079
1,112.936425,28.1837833333333,63.8200589970501,1448263,1511330738
2,112.936280555556,28.1837833333333,64.1105651105651,1448263,1511330800
3,112.93595,28.18385,65.3336643495531,1448263,1511331332
4,112.935691666667,28.1839333333333,66.9243986254296,1448263,1511331794
5,112.932275,28.1840388888889,80.1450980392157,1448263,1511335690
6,112.929519444444,28.1849583333333,179.382636655949,1448263,1511336583
7,112.929244444444,28.1849777777778,185.630363036304,1448263,1511336714
8,112.928458333333,28.1860111111111,228.579710144928,1448263,1511337087
9,112.931161111111,28.1911555555556,285.57196969697,1448263,1511339434
10,112.931288888889,28.1910944444444,288.503448275862,1448263,1511339460
......
可参考官方亮度图样例: 亮度图 | L7 (antgroup.com) 。
加载Mapbox地图 。
<!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>Document</title>
<script src='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css' rel='stylesheet' />
<script src='https://unpkg.com/@antv/l7'></script>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.Mapbox({
style: 'dark',
center: [112.9448, 28.1708],
zoom: 12,
token: 'pk.eyJ1IjoieWFuZ2ppYW4iLCJhIjoiY2phaG1neno0MXFkNDMzbWhwNWw0bWM4aiJ9.CFmrh0LVWAbmVeed-Xr7wA'
}),
});
</script>
</body>
</html>
加载数据,L7内置CSV格式解析器,只需指定字段名即可:
scene.on('loaded', () => {
fetch('./all.csv')
.then(res => res.text())
.then(data => {
const pointLayer = new L7.PointLayer({})
.source(data, {
parser: {
type: 'csv',
y: 'lat',
x: 'lng'
}
})
scene.addLayer(pointLayer);
});
});
绘制点图层,并设置样式:
scene.on('loaded', () => {
fetch('./all.csv')
.then(res => res.text())
.then(data => {
const pointLayer = new L7.PointLayer({})
.source(data, {
parser: {
type: 'csv',
y: 'lat',
x: 'lng'
}
})
.size(0.5)
.color('#080298');
scene.addLayer(pointLayer);
});
});
从图中可以看出主要的路线,即高亮部分 。
以下对景点及附近的路网数据可视化 。
路网数据获取与可视化步骤可参考: 「AntV」路网数据获取与L7可视化 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com) 。
叠加图层:
可以看到,在景区的轨迹信息比路网信息更为完善和直观 。
从上图不难看出,虽然有的地方在路网上不显示,这些道路可能只是景区小道,但它确实也是一种特殊的道路,尤其是对于行人、旅行者而言 。
当足够数量的轨迹点显示在一起时,这些亮度图似乎就是路网图,更进一步的,可以从这些轨迹数据中提取去路网 。
这里不做具体研究阐述,可以参考下列文章:
这里使用的是《Map Inference in the Face of Noise and Disparity》中所提出的算法进行提取路网,并提取GPS轨迹数据中的三维信息,构建为三维路网 。
《Map Inference in the Face of Noise and Disparity》中所提出的算法源码可以在以下地址下载:
另外,还有多种路网提取算法,可以在下列网站中查看并使用:
经过一系列的数据预处理、路网提取、数据后处理,从上述的轨迹数据得到了以下路网数据:
其中,海拔渐变色带由低到高为:
由图中可以看出岳麓山景点路网数据的相对高度 。
绘制的代码如下:
<!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>Document</title>
<script src='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css' rel='stylesheet' />
<script src='https://unpkg.com/@antv/l7'></script>
<style>
body,
#map {
height: 100vh;
width: 100vw;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.Mapbox({
style: 'dark',
center: [112.9448, 28.1708],
zoom: 12,
token: 'pk.eyJ1IjoieWFuZ2ppYW4iLCJhIjoiY2phaG1neno0MXFkNDMzbWhwNWw0bWM4aiJ9.CFmrh0LVWAbmVeed-Xr7wA'
})
});
scene.on('loaded', () => {
fetch('./Yuelushan.geojson')
.then(res => res.json())
.then(data => {
const layer = new L7.LineLayer({
zIndex: 2,
})
.source(data)
.size(0.5)
.active(true)
.color('z1', ['#0b8040', '#f2b90c', '#751304', '#8c644c', '#b8b8b8']);
scene.addLayer(layer);
});
});
</script>
</body>
路网数据的格式如下:
{
"type": "FeatureCollection",
"name": "Yuelushan",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"features": [
{
"type": "Feature",
"properties": {
"id": 0,
"z1": 74.72296906,
"z2": 74.72296906
},
"geometry": {
"type": "MultiLineString",
"coordinates": [
[
[
112.918952568856085,
28.182139289691705,
74.72296906
],
[
112.918964283127451,
28.182139382193309,
74.72296906
]
]
]
}
},
......
由示例数据可知,每个点坐标是由经纬度和高程组成,而L7默认支持路网数据高程显示:
利用高程信息,可以制作出坡度信息图 。
利用坡度信息,可以帮助行人选择道路,实现代码如下:
<!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>Document</title>
<script src='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css' rel='stylesheet' />
<script src='https://unpkg.com/@antv/l7'></script>
<style>
body,
#map {
height: 100vh;
width: 100vw;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const scene = new L7.Scene({
id: 'map',
map: new L7.Mapbox({
style: 'dark',
center: [112.9448, 28.1708],
zoom: 12,
token: 'pk.eyJ1IjoieWFuZ2ppYW4iLCJhIjoiY2phaG1neno0MXFkNDMzbWhwNWw0bWM4aiJ9.CFmrh0LVWAbmVeed-Xr7wA'
})
});
scene.on('loaded', () => {
fetch('./Yuelushan.geojson')
.then(res => res.json())
.then(data => {
data.features.forEach(element => {
element.properties.slope = Math.abs(element.properties.z1 - element.properties.z2);
});
const layer = new L7.LineLayer({
zIndex: 2,
})
.source(data)
.size(1)
.active(true)
.color('slope', ['#0b8040', '#f2b90c', '#751304', '#8c644c', '#b8b8b8']);
scene.addLayer(layer);
});
});
</script>
</body>
注:此处坡度计算并不准确,只是大致示意 。
笔者使用过多个Web端的GIS开源库,包括OpenLayers、Leaflet、Mapbox、Cesium等,也使用过ECharts等图表库,相较而言,L7开箱即用的特点十分突出,基于WebGL的渲染方式在面对地理大数据时也能获得不错的体验,甚至在上述的案例中,绘制轨迹数据的流畅感比C++写的桌面端软件的QGIS更好 。
不足之处是,和老牌的GIS开源库相比,专业性和可配置性还是有所欠缺,三维方面也有待完善。当然,目前看来,L7的主要应用场景的地理数据可视化,如果是侧重地理可视化的项目与应用场景,L7是个非常不错的选择 。
[1] 简介 | L7 (antgroup.com) 。
[2] 所有图表 | L7 (antgroup.com) 。
[3] 场景 Scene | L7 (antgroup.com) 。
[4] Map Inference in the Face of Noise and Disparity 。
[5] haidaoxiaofei/mapinference-gis12-upgrade (github.com) 。
最后此篇关于「AntV」L7地理可视化:从入门到实践的文章就讲到这里了,如果你想了解更多关于「AntV」L7地理可视化:从入门到实践的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。
目录 内置的高亮节点 自定义高亮 自定义高亮时保持原始颜色 总结 案例完整代码 通过官方文档,可知高
目录 32.go.Palette 一排放两个 33.go.Palette 基本用法 34.创建自己指向自己的连线 35.设置不同的 groupTemplate 和
目录 41.监听连线拖拽结束后的事件 42.监听画布的修改事件 43.监听节点被 del 删除后回调事件(用于实现调用接口做一些真实的删除操作) 44.监听节点鼠标
织梦初秋 那是一个宜人的初秋午后,阳光透过窗户洒在书桌上,我轻轻地拂去被阳光映照出的尘屑,伸了个懒腰。哎呀,这个世界真是奇妙啊,想到什么就能用代码实现,就像笔尖上点燃的火花。 思索的起点 我一直对天气
曲径通幽,古木参天 时光匆匆,不经意间已是2023年的秋季。我身处在这个充满朝气和变革的时代,每天都充满了新的科技突破和创新。而当我想起曾经努力学习的Python编程语言时,心中涌动着一股热情,渴望将
我有一个堆积条形图,由一个 bool 字段分割。这会导致图例显示为两种颜色(很酷!)但图例具有以下值:true 和 false。对于读者来说,什么是真或假意味着什么是没有上下文的。 在这种情况下,字段
我想在 R 中做一个简单的一阶马尔可夫链。我知道有像 MCMC 这样的包,但找不到一个以图形方式显示它的包。这甚至可能吗?如果给定一个转换矩阵和一个初始状态,那将会很好,人们可以直观地看到通过马尔可夫
我是 tableau 的新手,我有以下可视化,这是链接: My visualization 我的问题是我不知道如何在一个仪表板中添加多个仪表板作为选项卡。在我的可视化中,有三个仪表板“Nota tot
我建立类似自动VJ程序的东西。我有2个网络摄像头发出的2个incomig视频信号和一些可视化效果(目前2个,但我想要更多)。我有一个以dB为单位的传入音频信号音量,以bpm为单位。我需要的是视频输出的
我需要可视化的东西,并想要求一些提示和教程。或者使用哪种技术(Cocos2D、OpenGL、Quartz,...) 这里有人在 iOS 设备上做过可视化吗? 它是关于移动物体、褪色、粒子等等…… 任何
我对 Graphviz 越来越熟悉,想知道是否可以生成如下所示的图表/图表(不确定你叫它什么)。如果没有,有人知道什么是好的开源框架吗? (首选,C++,Java 或 Python)。 最佳答案 根据
问题很简单——我真的很喜欢用 UIStackView 来组织 UI。但是,我在测试应用程序中看不到 UIStackView 边界。当 UI 元素不是预期的时候,我需要花很多时间来调试。在网上搜索,我找
例如,我可以通过以下方式分配内存时的情况: Position* arr1 = new Position[5]; Position 是我程序中的一个类,它描述了具有 x 和 y 值的位置点。 堆栈上会有
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 5 年前。
我最近一直在处理许多半复杂的 XSD,我想知道:有哪些更好的工具可以处理 XML 模式?有没有图形工具? 独立的或基于 Eclipse 的是理想的选择,因为我们不是 .net 商店。 最佳答案 我找到
通过一段时间的使用和学习,对G6有了更一步的经验,这篇博文主要从以下几个小功能着手介绍,文章最后会给出完整的demo代码。 目录 1. 树图的基本布局和
三维数据的获取方式 RGBD相机和深度图 代码展示:在pcl中,把点云转为深度图,并保存和可视化 三维数据的获取方式 在计算机视觉和遥感领域,点云可以通过四种主要的技术获得, (1)根据图像衍生而得,
代码 library(igraph) g <- graph.tree(n = 2 ^ 3 - 1, children = 2) node_labels <- c("", "Group A", "Gro
我正在关注 this tutorial并创建了一个这样的图表: from dask.threaded import get from operator import add dsk = { 'x
我是一名优秀的程序员,十分优秀!