【问题标题】:Cluster markers in MapBox, how to "accumulate" just distinct properties?MapBox中的集群标记,如何“累积”不同的属性?
【发布时间】:2021-03-09 23:45:13
【问题描述】:

我想在地图上显示标记,其中每个标记都是UserLocation。一个User 可以有多个UserLocation。 当我对标记进行聚类时,我想显示这些聚类标记的用户列表,没有重复。

例如,让我们以这 3 个附近的标记为例:

      { // Marker1
        type: 'Feature',
        properties: {user_id : "Daniele"},
        geometry: { type        : 'Point',
                    coordinates : [lng0, lat0]
                  }
      },
      {// Marker2
        type: 'Feature',
        properties: {user_id : "Daniele"},
        geometry: { type        : 'Point',
                    coordinates : [lng1, lat1]
                  }
      },
      {// Marker3
        type: 'Feature',
        properties: {user_id : "Roberto"},
        geometry: { type        : 'Point',
                    coordinates : [lng2, lat2]
                  }
      }

当我聚集它们时,单击聚集的圆圈,我想看到“Daniele,Roberto”。 我该怎么做?

另外,我想设置圆的大小,根据不同用户聚集的不同数量(在上面的例子中,应该是2)。


**更新 2


JSFIDDLE

一个想法可以是构建一个不同名称的数组,然后使用length 表达式来调整圆的大小。

反正应该有一种语法错误……

 clusterProperties: {
  distinctNames : 
                ['case', 
                   /*cond  */ ["!", ['in',['get', 'user_id'], ['accumulated']]], 
                   /*result*/ ['concat', ['concat', ['get', 'user_id'], ',']],
                                                         
                   /*default*/ ['accumulated']
                ]
}

【问题讨论】:

    标签: mapbox mapbox-gl-js mapbox-marker


    【解决方案1】:

    文档不是很清楚,但这是我如何实现这种“不同的累积”。

    来自clusterProperties 定义:

    引用特殊 ["accumulated"] 值的自定义 reduce 表达式,例如:

    {"sum": [["+", ["accumulated"], ["get", "sum"]], ["get", "scalerank"]]}
    

    与以下结果相同:{"sum": ["+", ["get", "scalerank"]]}

    在您的情况下,您希望从标记中累积 user_id 属性而不重复。

    逻辑是只在user_id尚未添加到累加值时添加它。

    clusterProperties: {
      distinctUsers: [
        // ['accumulated'] is the current value iterated during the reduce (the property is defined at [1])
        // ['get', 'distinctCountries'] is the accumulated / concatenated string
        [
          // Concat accumulated value + current value if not present in accumulated
          'concat',
          ['get', 'distinctUsers'],
          [
            'case',
            ['in', ['accumulated'], ['get', 'distinctUsers']],  // If accumulated (user_id) has already been added
            '',  // Add EMPTY string
            ['concat', ', ', ['accumulated']],  // Add the user_id (concatenated with a comma in your case)
          ],
        ],
        ['get', 'user_id'], // [1]: source marker property iterated in the custom reduce function
      ]
    }
    

    正如史蒂夫在他的answer 中所说,您还可以将user_id 包装在某个独特的字符中,这样您就不会意外地在另一个用户“robin”中找到用户“rob”。

    [1] 定义的源属性['get', 'user_id'] 将变为:

    ['concat', '%', ['get', 'user_id'], '%']
    

    【讨论】:

      【解决方案2】:

      根据documentation 你想做这样的事情:

      map.addSource(userData, {
         id: 'user-locations',
         type: 'geojson',
         data: 'myuserdata.geojson',
         cluster: true,
         clusterProperties: {
            names: ['concat', ['concat', ['get', 'user_id'], ',']]
         }
      }
      

      您的源中的聚集点现在将有一个属性 names,其中将包含逗号分隔(和逗号终止)的名称字符串。

      另外,我想设置圆的大小,根据不同用户聚集的不同数量(在上面的例子中,应该是2)

      这听起来……很有挑战性。我能想到的一种方法是按照这些思路编写一个自定义累加器函数:

      • 使函数返回一个包含两个值的数组,[distinctNames, allNames] 其中第一个是整数,第二个是字符串。
      • 如果allNames 包含我们当前的名称,则返回数组。
      • 否则,返回数组[distinctNames + 1, allNames + thisName]

      在 Mapbox GL 表达式中操作这样的数组是可能的,但非常繁琐。你需要使用['literal', ...]['at', ...]

      代码如下所示:

         clusterProperties: {
            names: ['concat', ['concat', ['get', 'user_id'], ',']],
            distinctNames: [
                ['case', ['in', ['get', 'distinctNames'], ['at', ['accumulated'], 1]
                  ['accumulated'],
                  ['literal', ['+', ['at', ['accumulated'], 0], 1], ['concat', ['at', ['accumulated'], 1], ['get', 'distinctNames']]]
                ],
                ['concat', '%', ['get', 'user_id'], '%'] // wrap user ID in some unique character so we don't accidentally find user "rob" within another user "robin" for instance.
            ]
         }
      

      从文档中不清楚 accumulator 函数是如何工作的,或者您如何访问当前值。他们的例子暗示它将是['get', <name of cluster property>],尽管这看起来有点奇怪。

      【讨论】:

      • 感谢您的回复。我明白了你的逻辑,我会测试它并让你知道。谢谢!
      • 算了...我对表达式语法还不是很了解,而且我对代码有点迷茫。我认为缺少括号...你能解决它吗?这将帮助我理解:)
      • 我已经更新了我的问题,并对您的回答发表了评论。我试图按照你的指示,但我错过了一些东西..
      • 更新2。试图“累积”工作
      • 正如我所说,这是一项非常具有挑战性的任务。我没有简单的方法来测试这段代码,只是希望能给你指明正确的方向。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多