倾斜后悬停时突出显示填充挤出特征?

问题描述 投票:0回答:2

我想在将鼠标悬停在填充挤出功能上时突出显示它们。 与此相关的样式使用表达式和功能状态是直接的,但我在检索正确的功能时遇到了困难。

网上有代码可以在鼠标悬停时更改功能状态,而且看起来很简单,所以我对其进行了修改:

var hover_id = null;
const feature_state = { hover: true }

map.on('mousemove', '3d-buildings', (e) => {
  
    // Get features under cursor, following render order
    const features = map.queryRenderedFeatures(e.point);

    // Check that features are not empty
    if (features.length > 0) {

        // Clean up previously hovered feature
        if (hover_id) {
            map.removeFeatureState({source: "composite", sourceLayer: 'building', id: hover_id});
        }

        // Set feature state of the new hovered feature
        hover_id = features[0].id;
        map.setFeatureState({source: 'composite', sourceLayer: 'building', id: hover_id}, feature_state);

        console.log(hover_id)
  }
});

虽然最初效果很好,但一旦我使用鼠标右键倾斜相机,它就会停止工作。倾斜后,最前面的元素不再被选择(似乎选择了其他元素并打印出 ID,但地图上没有显示任何内容,也不会引发错误)。 与此相关的是,只有在放大相当远的距离后才会选择正确的功能 - 在很大的缩放范围内,建筑物已经渲染到屏幕上,但似乎没有被 queryRenderedFeatures 拾取。这是预期的行为吗?

预期行为: map.queryRenderedFeatures(...)[0] 选择最重要的特征,与相机倾斜无关。

相机倾斜影响特征选择的可能原因是什么?这是一个错误还是我滥用了 API?

mapbox mapbox-gl-js mapbox-gl
2个回答
2
投票

我认为您面临的问题与倾斜无关,而是与您添加和删除状态而不是更改状态值这一事实有关。状态必须在图层定义中声明,用表达式改变颜色,然后只需要改变状态的值即可。

这里有一个我创建的小提琴来展示如何在鼠标悬停/移出时更改填充挤压的颜色

相关代码是这样的:

        let mapConfig = {
          NYC: {
            origin: [-74.044514, 40.689259, 39],
            center: [-74.0137, 40.70346, 0],
            zoom: 16.2,
            pitch: 60,
            bearing: 35
          }
        }

        mapboxgl.accessToken = 'PUT YOUR TOKEN HERE';
        let point = mapConfig.NYC;
        var map = new mapboxgl.Map({
          style: 'mapbox://styles/mapbox/streets-v11',
          center: point.center,
          zoom: point.zoom,
          pitch: point.pitch,
          bearing: point.bearing,
          container: 'map',
          antialias: true,
          hash: true
        });

        map.on('style.load', function() {

          if (map.getSource('composite')) {
            map.addLayer({
              'id': '3d-buildings',
              'source': 'composite',
              'source-layer': 'building',
              'type': 'fill-extrusion',
              'minzoom': 14,
              'paint': {
                'fill-extrusion-color': [
                  'case',
                  ['boolean', ['feature-state', 'hover'], false],
                  '#ff0000',
                  '#ddd'
                ],
                'fill-extrusion-height': ["number", ["get", "height"], 5],
                'fill-extrusion-base': ["number", ["get", "min_height"], 0],
                'fill-extrusion-opacity': 1
              }
            }, 'road-label');
          }

          let fHover;

          map.on('mousemove', function(e) {
            //157001066
            var features = map.queryRenderedFeatures(e.point, {
              layers: ['3d-buildings']
            });
            if (features[0]) {
              mouseout();
              mouseover(features[0]);
            } else {
              mouseout();
            }

          });

          map.on('mouseout', function(e) {
            mouseout();
          });

          function mouseout() {
            if (!fHover) return;
            map.getCanvasContainer().style.cursor = 'default';
            map.setFeatureState({
              source: fHover.source,
              sourceLayer: fHover.sourceLayer,
              id: fHover.id
            }, {
              hover: false
            });

          }

          function mouseover(feature) {
            fHover = feature;
            map.getCanvasContainer().style.cursor = 'pointer';

            map.setFeatureState({
              source: fHover.source,
              sourceLayer: fHover.sourceLayer,
              id: fHover.id
            }, {
              hover: true
            });
          }


        });

如果此答案解决了您的问题,请将其标记为接受答案,这样也将帮助其他用户知道这是正确的解决方案。


1
投票

@jscastro 这工作得很好:我的要求是我需要用纬度和经度改变一些建筑物的颜色。我已经通过使用下面的 API 实现了从纬度和经度获取建筑物 ID

https://api.mapbox.com/v4/mapbox.mapbox-streets-v8,mapbox.mapbox-terrain-v2/tilequery/55.26365875255766,25.188400365955193.json?radius=30&limit=10&dedupe&access_token=.

我在这里面临一个问题,颜色仅在缩放级别 17 后才发生变化。我想更改缩放级别 15 上的颜色。

map.on("style.load", function () {
  if (map.getSource("composite")) {
    const layers = map.getStyle().layers;
    const labelLayerId = layers.find(
      (layer) => layer.type === "symbol" && layer.layout["text-field"]
    ).id;
    map.addLayer(
      {
        id: "3d-buildings",
        source: "composite",
        "source-layer": "building",
        filter: ["==", "extrude", "true"],
        type: "fill-extrusion",
        minzoom: 15,
        zoom: 15,
        pitch: 60,
        bearing: -60,
        layout: {
          // Make the layer visible by default.
          visibility: "visible",
        },
        paint: {
          "fill-extrusion-color": [
            "case",
            ["boolean", ["feature-state", "hover"], false],
            "#00ff00",
            "#AED0EC",
          ],
          "fill-extrusion-height": [
            "interpolate",
            ["linear"],
            ["zoom"],
            15,
            0,
            15.5,
            ["get", "height"],
          ],
          "fill-extrusion-base": [
            "interpolate",
            ["linear"],
            ["zoom"],
            15,
            0,
            15.05,
            ["get", "min_height"],
          ],
          "fill-extrusion-opacity": 1,
        },
      },
      labelLayerId
    );
  }
  map.getCanvasContainer().style.cursor = "pointer";
  map.setFeatureState(
    {
      source: "composite",
      sourceLayer: "building",
      id: "4411722601841895",
    },
    {
      hover: true,
    }
  );
  map.getCanvasContainer().style.cursor = "pointer";
  map.setFeatureState(
    {
      source: "composite",
      sourceLayer: "building",
      id: "1315660041727095",
    },
    {
      hover: true,
    }
  );
  map.getCanvasContainer().style.cursor = "pointer";
  map.setFeatureState(
    {
      source: "composite",
      minzoom: 15,
      sourceLayer: "building",
      id: "3957345234349675",
    },
    {
      hover: true,
    }
  );
  map.getCanvasContainer().style.cursor = "pointer";
  map.setFeatureState(
    {
      source: "composite",
      sourceLayer: "building",
      id: "5328485811",
    },
    {
      hover: true,
    }
  );
});

© www.soinside.com 2019 - 2024. All rights reserved.