Mapbox 鼠标悬停圆圈以使用特征状态更改颜色

Posted

技术标签:

【中文标题】Mapbox 鼠标悬停圆圈以使用特征状态更改颜色【英文标题】:Mapbox mouseover circle to change color using feature-state 【发布时间】:2019-01-16 06:08:26 【问题描述】:

鼠标悬停在 Mapbox 地图上时,我无法让标记更改颜色。 0.47 版本的 mapbox-gl.js 允许您使用 feature-state 更改动态样式的功能。

这适用于 Mapbox 示例:https://www.mapbox.com/mapbox-gl-js/example/hover-styles/

但是在我的示例中,当特征标记的 feature-state 更改时,样式似乎永远不会被触发。

我已经设法使用 map.setFilter 函数让鼠标悬停工作,但是当我添加 1000 个标记时,这变得非常低效和缓慢。

任何提示将不胜感激,非常感谢。

请看我的示例代码...

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' />
    <title>Create a hover effect</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.css' rel='stylesheet' />
    <style>
        body  margin:0; padding:0; 
        /* #map  position:absolute; top:0; bottom:0; width:100%;  */
        #map  width:100%; height: 500px; 
    </style>
</head>
<body>

<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiY29kYm9kIiwiYSI6IjhjbFE1aUUifQ.Gimi98Oh3Uex9WQZlb5Wkw';
var map = new mapboxgl.Map(
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v9',
    center: [-0.1507524, 51.5140731],
    zoom: 9
);
var hoveredStateId =  null;

map.on('load', function () 
    map.addSource("sites", 
        "type": "geojson",
        "data": 
          "type": "FeatureCollection",
          "features": [
            
              "type": "Feature",
              "geometry": 
                "type": "Point",
                "coordinates": [
                  -0.1407524,
                  51.5240731
                ]
              ,
              "properties": 
                "id": 2,
                "name": "Oxford Street"
              
            
          ]
        
    );

    // The feature-state dependent fill-opacity expression will render the hover effect
    // when a feature's hover state is set to true.
    map.addLayer(
        'id': 'sites-bold',
        'type': 'circle',
        'source': 'sites',
        'layout': ,
        'paint': 
          'circle-radius': 10,
          // 'circle-color': '#ff442b',
          'circle-color': ['case',
            ['boolean', ['feature-state', 'hover'], false],
              'red',
              'blue'
            ],
          'circle-opacity': 0.6,
          'circle-stroke-color': 'cyan',
          'circle-stroke-width': 1
        
      );


    // When the user moves their mouse over the state-fill layer, we'll update the
    // feature state for the feature under the mouse.
    map.on("mousemove", "sites-bold", function(e) 
      // console.log('in', e.features)
      if (e.features.length > 0) 
          // if (this.hoveredStateId) 
          //     map.setFeatureState(source: 'sites', id: this.hoveredStateId,  hover: false);
          // 
          this.hoveredStateId = e.features[0].properties.id;
          console.log('in-f-id', this.hoveredStateId)
          map.setFeatureState(source: 'sites', id: this.hoveredStateId,  hover: true);
          console.log('in-f', e.features[0])
      
      console.log('in', map.getFeatureState(source: 'sites', id: this.hoveredStateId))
    );

    // When the mouse leaves the state-fill layer, update the feature state of the
    // previously hovered feature.
    map.on("mouseleave", "sites-bold", function() 
      console.log('out-id', this.hoveredStateId)
      // if (this.hoveredStateId) 
          map.setFeatureState(source: 'sites', id: this.hoveredStateId,  hover: false);
      // 
      console.log('out', map.getFeatureState(source: 'sites', id: this.hoveredStateId))
      hoveredStateId =  null;
    );
);
</script>

</body>
</html>

【问题讨论】:

【参考方案1】:

要使用setFeatureState,您需要为数据源中的每个功能设置一个唯一 ID。所以从字面上看,你需要做的就是像这样添加一个 ID:

map.addSource("sites", 
    "type": "geojson",
    "data": 
      "type": "FeatureCollection",
      "features": [
        
          "type": "Feature",
          "id": 2,
          "geometry": 
            "type": "Point",
            "coordinates": [
              -0.1407524,
              51.5240731
            ]
          ,
          "properties": 
            "id": 2,
            "name": "Oxford Street"
          
        
      ]
    
);

注意该功能的id 属性。将其嵌套在 properties 中是不够的;它必须位于该功能的顶层。该方法的文档应该会在本周下一个版本发布时更新。

【讨论】:

非常感谢瑞恩。我还注意到id 必须同时在功能根和属性中。真的很感激! ...实际上我的最后一条评论是因为我在mousemove 函数中调用了this.hoveredStateId = e.features[0].properties.id;。再次感谢。

以上是关于Mapbox 鼠标悬停圆圈以使用特征状态更改颜色的主要内容,如果未能解决你的问题,请参考以下文章

将鼠标悬停在上下文菜单上时如何更改 li 项的颜色

悬停链接以使用 css 更改 *PAGE* 背景颜色

散景:在悬停回调中更改圆圈大小

在三个js中使用鼠标悬停更改网格颜色

如何编写一个考虑缩放、特征状态和数据驱动样式的 Mapbox 绘制表达式?

使用对象时如何在鼠标悬停时更改 SVG 笔触颜色