从零开始Vue项目中使用MapboxGL开发三维地图教程(五)实现框选要素功能、可拖动点展示坐标以及地图上实时更新要素

文章目录

      • 1、实现框选要素功能
          • 1.1、添加点数据的图层:
          • 1.2、增加绘图插件(mapbox-draw)
          • 1.3、实现框选并让选择的目标数据高亮
      • 2、实现地图上可拖动点
          • 2.1、实现功能:
          • 2.2、实现思路:
          • 2.3、代码示例:
      • 3、实时更新要素功能

1、实现框选要素功能

1.1、添加点数据的图层:

数据源名称为earthquakes,点图层id为clusters

map.addSource('earthquakes', {
            type: 'geojson',
            data: 'https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson',
            cluster: true,
            clusterMaxZoom: 14, // Max zoom to cluster points on
            clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)
          });

          map.addLayer({
            id: 'clusters',
            type: 'circle',
            source: 'earthquakes',
            filter: ['has', 'point_count'],
            paint: {
              'circle-color': [
                'step',
                ['get', 'point_count'],
                '#51bbd6',
                100,
                '#f1f075',
                750,
                '#f28cb1'
              ],
              'circle-radius': [
                'step',
                ['get', 'point_count'],
                20,
                100,
                30,
                750,
                40
              ]
            }
          });
1.2、增加绘图插件(mapbox-draw)
    // 绘图插件
      let draw = new mapboxdraw({
        displayControlsDefault: false,
        controls: {
          polygon: true,
          trash: true
        }
      });
      map.addControl(draw);
    map.on('draw.create', function (e) {
        var features = draw.getAll();
    })
 
    map.on('draw.delete', function (e) {
        map.removeLayer('selected')
    });
1.3、实现框选并让选择的目标数据高亮

基本思路是:通过turf来计算出在框选区域内的所有点(数据),将这些数据构成一个新的图层,置放于最上层,用不同的颜色来表示。

核心代码:

 map.on('draw.create', createArea);

createArea方法:

        function createArea(e) {
          const data = draw.getAll();
          const answer = document.getElementById('calculated-area');

          const drawCoordinatesvalue = data.features[0].geometry.coordinates
          var features_Layer = map.queryRenderedFeatures(e.point, {
            layers: ['clusters']
          });
          var selectedFeatures = []
          drawCoordinatesvalue.forEach(coordinate => {
            features_Layer.forEach(feature => {
              const point = turf.point(feature.geometry.coordinates) // 将要素转为 Turf.js 中的 Point 对象
              if (turf.booleanPointInPolygon(point, turf.polygon([coordinate]))) { // 判断要素是否在绘制的区域内
                selectedFeatures.push(feature) // 如果在区域内,则添加到选中要素数组中
              }
            })
          })
          // 将选中的要素添加到目标数组 便于后续高亮显示
          const source = {
            type: 'geojson',
            data: {
              type: 'FeatureCollection',
              features: selectedFeatures
            }
          }
          map.addLayer({
            id: 'selected',
            type: 'circle',
            source: source,
            paint: {
              'circle-radius': 15,
              'circle-color': '#ddec0a'
            }
          })

          //计算面积和面要素的中心点坐标
          if (data.features.length > 0) {
            const area = turf.area(data);
            // const polygonfeatures = turf.points([data.features[0].geometry.coordinates[0]])
            const centrepostion = turf.centroid(data.features[0])
            // Restrict the area to 2 decimal points.
            const rounded_area = Math.round(area * 100) / 100;
            answer.innerHTML = `

面积为:${rounded_area}square meters


中心点坐标:${centrepostion.geometry.coordinates}

`
; console.log(centrepostion) } else { answer.innerHTML = ''; if (e.type !== 'draw.delete') alert('Click the map to draw a polygon.'); } }

运行效果如下:

2、实现地图上可拖动点

2.1、实现功能:

可以将点拖动到地图上的新位置,并在地图上显示新的点坐标。

2.2、实现思路:

首先定义一个空的点要素集合GeoJSON变量,用来存放拖动点坐标信息;然后使用MapTouchEvents来防止默认的地图拖动行为并获取更新的坐标。最后使用map.getSource中的setData对变量更新赋值,

2.3、代码示例:

首先dom中添加如下标签:

<pre id="coordinates" class="coordinates"></pre>
const canvas = map.getCanvasContainer();

const geojson = {
    'type': 'FeatureCollection',
    'features': [{
            'type': 'Feature',
            'geometry': {
                'type': 'Point',
                'coordinates': [0, 0]
            }
        }
    ]
};

function onMove(e) {
    const coords = e.lngLat;

    // Set a UI indicator for dragging.
    canvas.style.cursor = 'grabbing';

    // Update the Point feature in `geojson` coordinates
    // and call setData to the source layer `point` on it.
    geojson.features[0].geometry.coordinates = [coords.lng, coords.lat];
    map.getSource('point').setData(geojson);
}

function onUp(e) {
    const coords = e.lngLat;

    // Print the coordinates of where the point had
    // finished being dragged to on the map.
    coordinates.style.display = 'block';
    coordinates.innerHTML = `Longitude: ${coords.lng}
Latitude:
${coords.lat}`
; canvas.style.cursor = ''; // Unbind mouse/touch events map.off('mousemove', onMove); map.off('touchmove', onMove); } map.on('load', () => { // Add a single point to the map. map.addSource('point', { 'type': 'geojson', 'data': geojson }); map.addLayer({ 'id': 'point', 'type': 'circle', 'source': 'point', 'paint': { 'circle-radius': 10, 'circle-color': '#F84C4C' // red color } }); // When the cursor enters a feature in // the point layer, prepare for dragging. map.on('mouseenter', 'point', () => { map.setPaintProperty('point', 'circle-color', '#3bb2d0'); canvas.style.cursor = 'move'; }); map.on('mouseleave', 'point', () => { map.setPaintProperty('point', 'circle-color', '#3887be'); canvas.style.cursor = ''; }); map.on('mousedown', 'point', (e) => { // Prevent the default map drag behavior. e.preventDefault(); canvas.style.cursor = 'grab'; map.on('mousemove', onMove); map.once('mouseup', onUp); }); map.on('touchstart', 'point', (e) => { if (e.points.length !== 1) return; // Prevent the default map drag behavior. e.preventDefault(); map.on('touchmove', onMove); map.once('touchend', onUp); }); });

效果展示:

3、实时更新要素功能

实现功能:通过更新地图上的现有要素的数据来添加新坐标来动态显示路径
代码示例:

map.on('load', async () => {
// We fetch the JSON here so that we can parse and use it separately
// from GL JS's use in the added source.
const response = await fetch(
'https://docs.mapbox.com/mapbox-gl-js/assets/hike.geojson'
);
const data = await response.json();
// save full coordinate list for later
const coordinates = data.features[0].geometry.coordinates;
 
// start by showing just the first coordinate
data.features[0].geometry.coordinates = [coordinates[0]];
 
// add it to the map
map.addSource('trace', { type: 'geojson', data: data });
map.addLayer({
'id': 'trace',
'type': 'line',
'source': 'trace',
'paint': {
'line-color': 'yellow',
'line-opacity': 0.75,
'line-width': 5
}
});
 
// setup the viewport
map.jumpTo({ 'center': coordinates[0], 'zoom': 14 });
map.setPitch(30);
 
// on a regular basis, add more coordinates from the saved list and update the map
let i = 0;
const timer = setInterval(() => {
if (i < coordinates.length) {
data.features[0].geometry.coordinates.push(coordinates[i]);
map.getSource('trace').setData(data);
map.panTo(coordinates[i]);
i++;
} else {
window.clearInterval(timer);
}
}, 10);
});

效果展示:

你可能感兴趣的:(MapboxGL,vue.js,javascript,ecmascript)