Mapbox-如何检查线串是否在视图中

时间:2019-08-10 16:00:58

标签: javascript mapbox mapbox-gl-js

情况:

我使用Mapbox创建带有三个标记+连接它们的线串的地图。在this exmaple之后,我创建了一个按钮,可将相机缩放到线串的边界。

这按预期工作。

无论何时调用此函数(单击并在第一次加载地图时),相机都会正确缩放到线串边界。


问题/目标:

我只想在任何时候显示按钮:

  • 在显示线串之后,用户已更改了Campera的位置
  • 在显示线串之后,用户更改了缩放比例

只需添加/删除.is-visible类即可完成此操作。

但是,在以线串显示之后,我不知怎么想出如何聆听这两种可能的用户交互。

我尝试了一些看似过于复杂且行不通的方法。我觉得答案很简单,只是看不到。

任何帮助表示赞赏!


代码:

<script src='https://unpkg.com/mapbox@1.0.0-beta9/dist/mapbox-sdk.min.js'></script>
<script src='https://api.mapbox.com/mapbox-gl-js/v1.2.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v1.2.0/mapbox-gl.css' rel='stylesheet' />

<div id='map' class="traveljournal__map"></div>
<div class='traveljournal__map-actions'>
    <div id='zoomto' class="traveljournal__map-action traveljournal__map-action--zoomto"></div>
</div>

<script>

    mapboxgl.accessToken = 'TOKENHERE';
    let client = new MapboxClient(mapboxgl.accessToken);


    // DEFINE MAP
    var map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/nilsdannemann/cjz2kdev503jo1dnsr23qoca8',
        center: [174.724779, -41.288030], // Coordinates of newest Moment
        zoom: 9
    });


    // DEFINE MOMENTS
    var moments = [{
        id: "1",
        properties: {
            title: "moment title",
            content: "moment content",
            mood: "happy",
            date: "01. Aug 2019",
            weather: "sunny",
            iconSize: [60, 60],
            location: [174.800314, -41.317955],
        },
        camera: {
            center: [174.800314, -41.317955],
            zoom: 13,
            bearing: 20, // Add 20 for every location
            pitch: 40 
        }
    }, {
        id: "2",
        properties: {
            title: "moment title",
            content: "moment content",
            mood: "happy",
            date: "01. Aug 2019",
            weather: "sunny",
            iconSize: [60, 60],
            location: [174.773008, -41.282235],
        },
        camera: {
            center: [174.773008, -41.282235],
            zoom: 13,
            bearing: 40, // Add 20 for every location
            pitch: 40 
        }
    }, {
        id: "3",
        properties: {
            title: "moment title",
            content: "moment content",
            mood: "happy",
            date: "01. Aug 2019",
            weather: "sunny",
            iconSize: [60, 60],
            location: [174.724779, -41.288030],
        },
        camera: {
            center: [174.724779, -41.288030],
            zoom: 13,
            bearing: 60, // Add 20 for every location
            pitch: 40
        }
    }];


    // ADD MARKERS
    moments.forEach(function(marker, index) {
        // Create a DOM element for Marker
        var el = document.createElement('div');
        el.className = 'traveljournal__map-marker';
        el.style.width = marker.properties.iconSize[0] + 'px';
        el.style.height = marker.properties.iconSize[1] + 'px';

        el.addEventListener('click', function() {
            //Move Campera to Marker
            map.flyTo(moments[index].camera);
        });

        // Add Marker to Map
        new mapboxgl.Marker(el)
            .setLngLat(marker.properties.location)
            .addTo(map);
    }); 

    // ADD LINE BETWEEN MARKERS
    var linestring = [];
    moments.forEach(function(item) {
        linestring.push(item.properties.location);
    });

    // ADD ZOOM TO LINESTRING FUNCTION
    function zoomToLineString() {
        var bounds = linestring.reduce(function(bounds, coord) {
            return bounds.extend(coord);
        }, new mapboxgl.LngLatBounds(linestring[0], linestring[0]));

        map.fitBounds(bounds, {
            padding: {top: 30, right: 0, bottom: 75, left: 0},
            bearing: 0,
            pitch: 0 
        });
    };

    // ADD ZOOM TO LINESTRING BUTTON EVENT
    document.getElementById('zoomto').addEventListener('click', function() {
        zoomToLineString();
    });

    // LOAD MAP
    map.on('load', function() {

        // ADD LINE TO MAP
        map.addLayer({
            "id": "route",
            "type": "line",
            "source": {
                "type": "geojson",
                "data": {
                    "type": "Feature",
                    "properties": {},
                    "geometry": {
                        "type": "LineString",
                        "coordinates": linestring
                    }
                }
            },
            "layout": {
                "line-join": "round",
                "line-cap": "round"
            },
            "paint": {
                "line-color": "#2BABEE",
                "line-width": 2
            }
        });

        // ZOOM TO LINESTRING ON MAP LOAD
        zoomToLineString();

    });

</script>

1 个答案:

答案 0 :(得分:0)

您可以侦听zoomendmoveend事件以执行边界检查,并根据需要更新类。您可以使用queryRenderedFeatures查看行是否(部分)在视口中。

function checkLine() {
   if (map.queryRenderedFeatures({layers: 'route'}).length) {
      // route is within view, do what you want
   }
}

map.on('zoomend', checkLine);
map.on('moveend', checkLine);