【问题标题】:Mapbox - How to check if linestring is in viewMapbox - 如何检查线串是否在视图中
【发布时间】:2019-08-10 16:00:58
【问题描述】:

情况:

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

这按预期工作。

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


问题/目标:

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

  • 用户更改了露营车的位置,线串被纳入视野后
  • 线串显示后,用户更改了缩放比例

这可以通过添加/删除.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>

【问题讨论】:

    标签: javascript mapbox mapbox-gl-js


    【解决方案1】:

    您可以收听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);
    

    【讨论】:

    • 谢谢。唯一的问题:当用户缩小时,这不会显示缩放按钮,对吗?每当发生 zoomToLineString 后的相机时,我都试图让按钮出现。
    • moveend 事件本身可能足以触发任何类型的缩放或平移。
    猜你喜欢
    • 2023-03-23
    • 2020-10-29
    • 2011-11-17
    • 2021-09-23
    • 1970-01-01
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多