1. 在可视化地图上绘画图形
基于某些功能要求,用户可能希望在可视化地图上绘画不同的polygon来整合和规划不同的地区,因此mapbox官方提供了mapbox-gl-draw来帮助用户对地图进行自定义绘画。今天,我们将介绍如何在vue.js项目中配置绘画区域以及实现提取绘画图形的geojson地理信息
2. 配置绘画区域
首先,基于上篇文章的基础上。我们需要在terminal或者cmd中运行下面的命令,在项目中下载mapbox-gl-draw所需要的module。
npm install mapbox-gl-draw
下载成功之后,我们需要在App.vue的
import MapboxDraw from 'mapbox-gl-draw'
之后,我们在原来代码的基础上,在初始化init()方法中定义绘画区域以及定义相应的方法
var draw = new MapboxDraw({
displayControlsDefault: false,
controls:{
polygon:true,
trash:true
}
});
map.addControl(draw);
定义完绘画区域之后,我们项目中所显示的地图右侧上方会多出两个按钮,当用户需要绘画时,必须先点击第一个按钮进入绘画模式,之后通过两点的方式绘画polygon。如果用户希望重置绘画区域,可以点击第二个删除按钮,清空所画的图形
不仅上述所说的两种点击事件,当用户点击地图进行绘画时,地图也会进行相应的update事件,所以api一共提供了我们三个地图点击事件。由此,我们又可以自行定义不同的回调方法分别和这三个事件进行绑定以实现不同的功能效果。为了测试图形效果,我们引进了turf.js来可视化地图上保存所绘制的图形,并计算相应的面积大小。配置方法和mapbox-gl-draw一样,先在项目的terminal中运行下面的命令下载turf.js的module,之后在script中进行引用。
npm install turf
map.on('draw.create', updateArea);
map.on('draw.delete', updateArea);
map.on('draw.update', updateArea);
function updateArea(e){
var data = draw.getAll();
var answer = document.getElementById('calculated-area');
if(data.features.length > 0){
var area = turf.area(data);
// restrict to area to 2 decimal points
var rounded_area = Math.round(area * 100) / 100;
answer.innerHTML = '<p><strong>' + rounded_area + '</strong></p><p>square meters</p>';
}else{
answer.innerHTML = '';
if (e.type !== 'draw.delete')
alert('Use the draw tools to draw a polygon')
}
}
3. 提取所绘画的geojson地理信息
为了保存用户在mapbox可视化地图上绘画的polygon信息,我们可以导出相应的geojson地理数据信息并做相应的存储。
首先我们在中定义一个button,然后在
document.getElementById('export').onclick = function(e){
// extract GeoJson from featureGroup
var data = draw.getAll();
if(data.features.length > 0){
// Stringify the GeoJson
var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data))
// create export
document.getElementById('export').setAttribute('href', 'data:' + convertedData);
document.getElementById('export').setAttribute('download', 'data.geojson')
}
else{
alert("Wouldn't you like to draw some data")
}
}
用户可以绘画多个polygon之后,点击export按钮,把所有polygon的geojson信息提取出来,并下载。
4. 代码测试使用
完整代码
<template>
<div id="app">
<div style="height:500px;width:50%;text-align:left;">
<div ref="mapbox" style="height:500px;width:100%;"></div>
<pre id='info'></pre>
<!-- <pre id='coordinates' class='coordinates'></pre> -->
</div>
<div class="calculation-box">
<p>Draw a polygon using the draw tools.</p>
<a ref="#" id="export">export</a>
<div id="calculated-area"></div>
</div>
</div>
</template>
<script>
import mapboxgl from 'mapbox-gl'
import MapboxDraw from 'mapbox-gl-draw'
import turf from 'turf'
export default {
data () {
return {
}
},
mounted () {
this.init()
},
methods: {
// 初始化
init () {
// access key from mapbox
mapboxgl.accessToken = 'pk.eyJ1IjoicGVhcnBsdXMiLCJhIjoiY2thaDR4cm5kMDFibzJxcHlmNjgxYTJrayJ9.LZ0Fn5iA6SobVFv4R4gByw'
var coordinates = document.getElementById('coordinates');
// initialize map
const map = new mapboxgl.Map({
// refs tag for accessing the DOM element in the code
container: this.$refs.mapbox,
style: 'mapbox://styles/mapbox/streets-v9',
center: [12.550343, 55.665957], // 设置地图中心
zoom: 8, // 设置地图比例
})
// drawable area
var draw = new MapboxDraw({
displayControlsDefault: false,
controls:{
polygon:true,
trash:true
}
});
map.addControl(draw);
map.on('draw.create', updateArea);
map.on('draw.delete', updateArea);
map.on('draw.update', updateArea);
function updateArea(e){
console.log(e.type)
var data = draw.getAll();
var answer = document.getElementById('calculated-area');
if(data.features.length > 0){
var area = turf.area(data);
// restrict to area to 2 decimal points
var rounded_area = Math.round(area * 100) / 100;
answer.innerHTML = '<p><strong>' + rounded_area + '</strong></p><p>square meters</p>';
}else{
answer.innerHTML = '';
if (e.type !== 'draw.delete')
alert('Use the draw tools to draw a polygon')
}
}
document.getElementById('export').onclick = function(e){
// extract GeoJson from featureGroup
var data = draw.getAll();
if(data.features.length > 0){
// Stringify the GeoJson
var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data))
// create export
document.getElementById('export').setAttribute('href', 'data:' + convertedData);
document.getElementById('export').setAttribute('download', 'data.geojson')
}
else{
alert("Wouldn't you like to draw some data")
}
}
// create a draggable maker
var marker = new mapboxgl.Marker({
draggable: true
}).setLngLat([12.550343, 55.665957])
.addTo(map);
// defend a method for dragging the marker
function onDragEnd() {
console.log("test11")
var lngLat = marker.getLngLat();
coordinates.style.display = 'block';
coordinates.innerHTML = 'Longitude: ' + lngLat.lng + '<br />Latitude: ' + lngLat.lat;
}
// bind the onDragEnd method with the marker
marker.on('dragend', onDragEnd);
// 使用定位模块
map.addControl(new mapboxgl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
trackUserLocation: true,
showUserLocation: true,
zoom: 14,
}))
// // 建立一个标记点
// var marker = new mapboxgl.Marker({
// draggable: true
// })
//
// function onDragEnd() {
// var lngLat = marker.getLngLat();
// coordinates.style.display = 'block';
// coordinates.innerHTML = 'Longitude: ' + lngLat.lng + '<br />Latitude: ' + lngLat.lat;
// }
// marker.on('dragend', onDragEnd);
map.addControl(new mapboxgl.MapboxGeocoder({
accessToken: mapboxgl.accessToken
}));
}
},
computed: {
},
}
</script>
<style>
@import "https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.1/mapbox-gl.css";
@import "https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.0.9/mapbox-gl-draw.css";
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.coordinates {
background: rgba(0,0,0,0.5);
color: #fff;
position: absolute;
bottom: 10px;
left: 10px;
padding:5px 10px;
margin: 0;
font-size: 11px;
line-height: 18px;
border-radius: 3px;
display: none;
}
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
.calculation-box {
height: 75px;
width: 150px;
position: absolute;
bottom: 40px;
left: 10px;
background-color: rgba(255, 255, 255, .9);
padding: 15px;
text-align: center;
}
p {
font-family: 'Open Sans';
margin: 0;
font-size: 13px;
}
#export {
background-color: black;
color: white;
padding: 6px;
border-radius: 4px;
cursor:pointer;
font-size:12px;
height:20px;
width:20px;
}
</style>
参考文档
- mapbox 官方文档
- turf.js 官方文档
- Save GeoJSON from Mapbox GL Draw — Dan Swick