我想在地图上显示标记,其中每个标记都是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& lt;——
可以建立一个不同名称的数组,然后使用length
表达式来确定圆的大小。
无论如何,应该有一种语法错误…
clusterProperties: {
distinctNames :
['case',
/*cond */ ["!", ['in',['get', 'user_id'], ['accumulated']]],
/*result*/ ['concat', ['concat', ['get', 'user_id'], ',']],
/*default*/ ['accumulated']
]
}
根据文档,您需要这样做:
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.
]
}
从文档中不清楚累加器函数是如何工作的,或者如何访问当前值。他们的例子暗示它将是['get', <name of cluster property>]
,尽管这看起来有点奇怪。
文档不是很清楚,但这里是我如何实现这个"独特的累积"。
来自clusterProperties
定义:
引用特殊["累加"]值的自定义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
]
}
正如Steve在他的回答中所说,你也可以用一些独特的字符来包装user_id
,这样你就不会意外地发现用户"抢劫"了。在另一个用户"robin"例如,
在[1]
定义的源属性['get', 'user_id']
将变成:
['concat', '%', ['get', 'user_id'], '%']