需求
希望热力图的效果,能以3d柱子的方式立在地图上
参考资料
核心插件deck.gl ,官网地址
插件demo源码地址:点击查看
插件效果预览地址:点击查看
在线编辑器预览地址:点击查看
博客案例参考地址: 点击查看
图层数据源
使用官方提供的数据源进行调试,线上地址。由于是csv格式,前端使用d3插件,处理资源转成图层需要的格式(二位数组,经纬度坐标集合),数据格式如下:
[ [-0.198465, 51.505538]
[-0.178838, 51.491836]
[-0.20559, 51.51491]
[-0.208327, 51.514952]
[-0.206022, 51.496572]
[-0.19361, 51.500788]
[-0.173519, 51.495171]
]
截图:
该数据用于渲染热力图,相当于每个点位的权重都是1,越密集柱子颜色越深。
实现源码(vue2)
实现方式一
(MapboxOverlay),图层缩放存在抖动,不推荐使用,请使用方式二开发
<template>
<div>
<div id="map" ref="map"></div>
<div id="info"></div> <!-- 坐标提示框 -->
</div>
</template>
<script>
// 3d立体图层效果
import mapboxgl from "mapbox-gl";
import { AmbientLight, PointLight, LightingEffect } from '@deck.gl/core';
import { HexagonLayer } from '@deck.gl/aggregation-layers';
import { MapboxOverlay } from '@deck.gl/mapbox';
import * as d3 from 'd3';
export default {
name: "Home",
data() {
return {
map: "", //地图
time: 0, //时间
loopLength: 1800, // 线圈长度
animationSpeed: 1, //动画速度
};
},
mounted() {
this.initMap();
},
methods: {
// 用mapbox的方式初始化底层地图
initMap() {
this.map = new mapboxgl.Map({
accessToken: "your-token",
container: this.$refs.map,
style: "https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json",
center: [-0.198465,51.505538],
zoom: 5,
pitch: 45,
bearing: 0,
// antialias: true, // 平滑曲线
});
// 添加图层
this.addLayers();
},
// 添加图层
async addLayers() {
const ambientLight = new AmbientLight({
color: [255, 255, 255],
intensity: 1.0
});
const pointLight1 = new PointLight({
color: [255, 255, 255],
intensity: 0.8,
position: [-0.144528, 49.739968, 80000]
});
const pointLight2 = new PointLight({
color: [255, 255, 255],
intensity: 0.8,
position: [-3.807751, 54.104682, 8000]
});
const lightingEffect = new LightingEffect({ ambientLight, pointLight1, pointLight2 });
const material = {
ambient: 0.64,
diffuse: 0.6,
shininess: 32,
specularColor: [51, 51, 51]
};
const INITIAL_VIEW_STATE = {
longitude: -1.415727,
latitude: 52.232395,
zoom: 6.6,
minZoom: 5,
maxZoom: 15,
pitch: 40.5,
bearing: -27
};
const colorRange = [
[1, 152, 189],
[73, 227, 206],
[216, 254, 181],
[254, 237, 177],
[254, 173, 84],
[209, 55, 78]
];
const radius = 1000,
upperPercentile = 100,
coverage = 1;
const url = "https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv"
let data = []
await d3.csv(url, (response, index) => {
// console.log("解析在线文件得到数据: ", response, index,response.lng,response.lat);
data.push([Number(response.lng), Number(response.lat)])
});
console.log("最终的data: ", data);
let hexagonLayer = new HexagonLayer({
id: 'heatmap',
colorRange,
coverage,
data,
elevationRange: [0, 3000],
elevationScale: data && data.length ? 50 : 0,
extruded: true,
getPosition: d => d,
pickable: true,
radius,
upperPercentile,
material,
transitions: {
elevationScale: 3000
}
})
const mapboxOverlay = new MapboxOverlay({
layers: [
hexagonLayer
],
})
this.map.addControl(mapboxOverlay); //将deckGL的Layers作为mapbox的control添加到mapbox上
this.map.addControl(new mapboxgl.NavigationControl());
},
},
};
</script>
<style scoped lang="scss">
#map {
width: 100%;
height: 800px;
background: #e5e9ec;
}
</style>
实现方式二【推荐】
(MapboxLayer)
<template>
<div>
<div id="map" ref="map"></div>
<div id="info"></div> <!-- 坐标提示框 -->
</div>
</template>
<script>
// 3d立体图层效果
import mapboxgl from "mapbox-gl";
import { AmbientLight, PointLight, LightingEffect } from '@deck.gl/core';
import { HexagonLayer } from '@deck.gl/aggregation-layers';
import { MapboxLayer } from '@deck.gl/mapbox';
import * as d3 from 'd3';
export default {
name: "Home",
data() {
return {
map: "", //地图
};
},
mounted() {
this.initMap();
},
methods: {
initMap() {
this.map = new mapboxgl.Map({
accessToken: "your-token",
container: this.$refs.map,
style: "https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json",
center: [-1.415727, 52.232395],
zoom: 5,
pitch: 45,
bearing: 0,
antialias: true, // 平滑曲线
});
// 添加图层
this.addLayers();
},
// 添加图层
async addLayers() {
// const ambientLight = new AmbientLight({
// color: [255, 255, 255],
// intensity: 1.0
// });
// const pointLight1 = new PointLight({
// color: [255, 255, 255],
// intensity: 0.8,
// position: [-0.144528, 49.739968, 80000]
// });
// const pointLight2 = new PointLight({
// color: [255, 255, 255],
// intensity: 0.8,
// position: [-3.807751, 54.104682, 8000]
// });
// const lightingEffect = new LightingEffect({ ambientLight, pointLight1, pointLight2 });
const material = {
ambient: 0.64,
diffuse: 0.6,
shininess: 32,
specularColor: [51, 51, 51]
};
// const INITIAL_VIEW_STATE = {
// longitude: -1.415727,
// latitude: 52.232395,
// zoom: 6.6,
// minZoom: 5,
// maxZoom: 15,
// pitch: 40.5,
// bearing: -27
// };
const colorRange = [
[1, 152, 189],
[73, 227, 206],
[216, 254, 181],
[254, 237, 177],
[254, 173, 84],
[209, 55, 78]
];
const radius = 1000,
upperPercentile = 100,
coverage = 1;
const url = "https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/3d-heatmap/heatmap-data.csv"
let data = []
await d3.csv(url, (response, index) => {
// console.log("解析在线文件得到数据: ", response, index,response.lng,response.lat);
data.push([Number(response.lng), Number(response.lat)])
});
console.log("最终的data: ", data);
let hexagonLayer = new MapboxLayer({
id: 'heatmap',
type: HexagonLayer,
colorRange,
coverage,
data,
elevationRange: [0, 3000],
elevationScale: data && data.length ? 50 : 0,
extruded: true,
getPosition: d => d,
pickable: true,
radius,
upperPercentile,
material,
transitions: {
elevationScale: 3000
}
});
this.map.on('load', () => {
this.map.addLayer(hexagonLayer);
});
},
},
};
</script>
<style scoped lang="scss">
#map {
width: 100%;
height: 800px;
background: #e5e9ec;
}
</style>