关于使用MapBox GL进行图形绘制,很多人都在使用mapbox-gl-draw。但是它只是封装了一些简单的点、线、面的绘制功能。最近的一个项目提出了要求在手机上用手指拖动实现多边形涂鸦绘制,要求实时记录点。开始一直使用mapbox-gl-draw来做,但是始终无法实现手指拖动绘制的功能。最后,通过监听touch事件,实时改变source实现了这个效果。效果如下图:
代码如下:
注意,这里使用的监听事件,仅适合移动端使用,或者将Chrome调成移动端模式
<template>
<div style="width: 100%; height: 100%; overflow:hidden">
<div
id="map"
style="width: 100%; height: 100vh;position: absolute;top: 0;left: 0; z-index: 1;"
></div>
</div>
</template>
<script>
import mapboxgl from "mapbox-gl";
export default {
name: "HelloWorld",
data() {
return {
map: null,
coordinates:[]
};
},
async mounted() {
this.initMap();
},
methods: {
//取消涂鸦
cancleClick() {
this.removeDrawLayer();
this.map.dragPan.enable();
this.map.off('touchstart', this.touchstart);
this.map.off('touchmove', this.touchmove);
this.map.off('touchend', this.touchend);
this.coordinates=[];
},
touchstart(e){
this.coordinates=[];
console.log("拖动结束")
console.log(e)
this.addDrawLayer();
},
touchmove(e){
this.coordinates.push([e.lngLat.lng,e.lngLat.lat])
this.updateDrawLayer();
},
touchend(e){
this.coordinates.push(this.coordinates[0])
this.updateDrawLayer();
},
initMap() {
mapboxgl.accessToken =
'pk.eyJ1IjoiaGFtYnVnZXJkZXZlbG9wIiwiYSI6ImNqNXJtZjF4ZzB3em4yd21pZmVqbHlleDAifQ.I9eqVjtotz7jaU7XcJm9pQ';
let map = new mapboxgl.Map({
container: "map",
style: "mapbox://styles/mapbox/streets-v11",
maxZoom: 17.99,
zoom: 14,
center: [111.929173, 32.67442],
dragRotate: false,
pitchWithRotate: false,
touchZoomRotate: true,
refreshExpiredTiles: true,
});
this.map = map;
//解决canvas渲染不正确
map.on("styledata", function() {
map.resize();
});
map.on("load", e => {
// //禁止拖拽地图
this.map.dragPan.disable();
// //禁止通过捏合屏幕进行缩放
this.map.touchZoomRotate.disable();
// //禁止双击缩放
this.map.doubleClickZoom.disable();
this.coordinates=[];
this.map.on('touchstart', this.touchstart);
this.map.on('touchmove', this.touchmove);
this.map.on('touchend', this.touchend);
});
},
/**
* 移除绘制图层
*/
removeDrawLayer(){
if(this.map.getLayer("draw")){
this.map.removeLayer("draw")
this.map.removeLayer("draw_line")
}
if(this.map.getSource("draw")){
this.map.removeSource("draw")
}
},
updateDrawLayer(){
this.map.getSource('draw').setData({
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": { },
"geometry": {
"type": "Polygon",
"coordinates": [this.coordinates]
}
}]
});
},
/**
* 添加绘制图层
*/
addDrawLayer(){
if(this.map.getLayer("draw")){
return ;
}
let geoJosn={
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
92.98828125,
58.90464570302001
],
[
122.16796875,
56.46249048388979
],
[
133.06640625,
66.58321725728175
],
[
117.42187500000001,
69.96043926902489
]
]
]
}
}
]
}
this.map.addSource("draw", {
type: "geojson",
data: geoJosn});
this.map.addLayer({
id: "draw",
type: "fill",
source: "draw",
layout: {},
paint: {
"fill-color": "#F00",
"fill-opacity":0.3
}
});
this.map.addLayer({
id: "draw_line",
type: "line",
source: "draw",
layout: {},
paint: {
"line-color": "#F00",
"line-width": 5
}
});
}
}
};
</script>
代码可能缺失vue中引入mapbox的东西,自己想办法实现吧