deck.gl渲染HexagonLayer六边形图层
目录
效果图
在线地址
功能说明
本实例实现了deck.gl加载底图,通过d3js加载csv格式的热力点数据,并使用HexagonLayer渲染数据。并支持通过调整半径、覆盖率、垂直比例动态调整渲染效果
代码解析
- 此部分是引入在线deck.gl包,因为要用到mapboxgl的底图数据,同时引入了mapboxgl包;加载解析csv数据依赖引入了d3js库,还设置了基本的css样式
<html>
<head>
<title>deck.gl HexagonLayer Example</title>
<script src="https://unpkg.com/deck.gl@^8.8.0/dist.min.js"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.13.0/mapbox-gl.js"></script>
<style type="text/css">
body {
font-family: Helvetica, Arial, sans-serif;
width: 100vw;
height: 100vh;
margin: 0;
}
#control-panel {
position: absolute;
top: 0;
left: 0;
margin: 12px;
padding: 20px;
font-size: 12px;
line-height: 1.5;
z-index: 1;
background: #fff;
font-family: Helvetica, Arial, sans-serif;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.15);
}
label {
display: inline-block;
width: 140px;
}
</style>
</head>
- 这部分是es6写法,引入需要的模块DeckGL、GeoJsonLayer,并定义颜色常量,并初始化DeckGL(GeoJsonLayer已经有过解释可参照deck.gl渲染GeoJsonLayer)
const {DeckGL, GeoJsonLayer} = deck;
const COLOR_SCALE = [
// negative
[65, 182, 196],
[127, 205, 187],
[199, 233, 180],
[237, 248, 177],
// positive
[255, 255, 204],
[255, 237, 160],
[254, 217, 118],
[254, 178, 76],
[253, 141, 60],
[252, 78, 42],
[227, 26, 28],
[189, 0, 38],
[128, 0, 38]
];
const deckgl = new DeckGL({
mapStyle: 'https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json',
initialViewState: {
longitude: -1.4157,
latitude: 52.2324,
zoom: 6,
minZoom: 5,
maxZoom: 15,
pitch: 40.5
},
controller: true
});
- 动态读取界面radius、coverage、upperPercentile参数,初始化HexagonLayer图层
const OPTIONS = ['radius', 'coverage', 'upperPercentile'];
const COLOR_RANGE = [
[1, 152, 189],
[73, 227, 206],
[216, 254, 181],
[254, 237, 177],
[254, 173, 84],
[209, 55, 78]
];
OPTIONS.forEach(key => {
document.getElementById(key).oninput = renderLayer;
});
function renderLayer () {
const options = {};
OPTIONS.forEach(key => {
const value = document.getElementById(key).value;
document.getElementById(key + '-value').innerHTML = value;
options[key] = Number(value);
});
const hexagonLayer = new HexagonLayer({
id: 'heatmap',
colorRange: COLOR_RANGE, //渲染颜色色带
data, // 指定数据
elevationRange: [0, 1000], // 高程范围
elevationScale: 250, // 高程倍数
extruded: true, // 是否拉高
getPosition: d => d, // 设置渲染位置
...options // 动态参数 radius、coverage、upperPercentile
});
//deck.gl指定图层属性进行渲染
deckgl.setProps({
layers: [hexagonLayer]
});
}
5.d3js异步读取csv文件数据并解析后,执行renderLayer渲染数据
d3.csv('https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv')
.then(response => {
data = response.map(d => [Number(d.lng), Number(d.lat)]);
renderLayer();
});
源代码
拷贝到html文件中可直接用浏览器打开
<html>
<head>
<title>deck.gl HexagonLayer Example</title>
<script src="https://unpkg.com/deck.gl@^8.8.0/dist.min.js"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.13.0/mapbox-gl.js"></script>
<style type="text/css">
body {
font-family: Helvetica, Arial, sans-serif;
width: 100vw;
height: 100vh;
margin: 0;
}
#control-panel {
position: absolute;
top: 0;
left: 0;
margin: 12px;
padding: 20px;
font-size: 12px;
line-height: 1.5;
z-index: 1;
background: #fff;
font-family: Helvetica, Arial, sans-serif;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.15);
}
label {
display: inline-block;
width: 140px;
}
</style>
</head>
<body>
<div id="control-panel">
<div>
<label>Radius</label>
<input id="radius" type="range" min="1000" max="20000" step="1000" value="1000"></input>
<span id="radius-value"></span>
</div>
<div>
<label>Coverage</label>
<input id="coverage" type="range" min="0" max="1" step="0.1" value="1"></input>
<span id="coverage-value"></span>
</div>
<div>
<label>Upper Percentile</label>
<input id="upperPercentile" type="range" min="90" max="100" step="1" value="100"></input>
<span id="upperPercentile-value"></span>
</div>
</div>
</body>
<script type="text/javascript">
const {DeckGL, HexagonLayer} = deck;
const deckgl = new DeckGL({
mapStyle: 'https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json',
initialViewState: {
longitude: -1.4157,
latitude: 52.2324,
zoom: 6,
minZoom: 5,
maxZoom: 15,
pitch: 40.5
},
controller: true
});
let data = null;
const OPTIONS = ['radius', 'coverage', 'upperPercentile'];
const COLOR_RANGE = [
[1, 152, 189],
[73, 227, 206],
[216, 254, 181],
[254, 237, 177],
[254, 173, 84],
[209, 55, 78]
];
OPTIONS.forEach(key => {
document.getElementById(key).oninput = renderLayer;
});
function renderLayer () {
const options = {};
OPTIONS.forEach(key => {
const value = document.getElementById(key).value;
document.getElementById(key + '-value').innerHTML = value;
options[key] = Number(value);
});
const hexagonLayer = new HexagonLayer({
id: 'heatmap',
colorRange: COLOR_RANGE,
data,
elevationRange: [0, 1000],
elevationScale: 250,
extruded: true,
getPosition: d => d,
...options
});
deckgl.setProps({
layers: [hexagonLayer]
});
}
d3.csv('https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv')
.then(response => {
data = response.map(d => [Number(d.lng), Number(d.lat)]);
renderLayer();
});
</script>
</html>