Point features (and by extension marker features) support clustering. Once clustered, point.data() returns the clustered data, which is a list of unclustered point records followed by the clustered point records for a particular zoom level. The style accessors reference these records, not the original records set in data(). There isn't currently any official way to get the original data value or to get the points within different clusters.
As such, this results in messy code like
var original_data = [... some array of point data that contains style information on each point ...];
var points = layer.createFeature('point');
points.data(original_data);
points.clustering({radius: 10});
var firstPoint = (prop, d, i) => {
if (d.__cluster) {
d = d.obj;
}
if (d._points === undefined) {
return d[prop];
}
if (d._points.length) {
// we have to access the original data, since we don't have a public way to get to it now.
return original_data[d._points[0].index][prop];
}
return firstPoint(prop, d._clusters[0], i);
}
points.style({
radius: (d, i) => {
// scale the radius based on how many points are included
if (d.__cluster) {
return 5 * (d.obj._count ** 0.5);
}
return 5;
},
// have other styles use style of the first point
fillColor: (d, i) => firstPoint('fillColor', d, i),
strokeColor: (d, i) => firstPoint('strokeColor', d, i),
fillOpacity: (d, i) => firstPoint('fillOpacity', d, i),
strokeOpacity: (d, i) => firstPoint('strokeOpacity', d, i)
});
This is a mess -- we shouldn't need to access the internal methods and properties to do this. There is also an internal __data property that is not used and not set as commented.
We should remove __data and add some convenience methods. (update: see #1389)
I think the following would be appropriate:
points.unclusteredData() : return the original data (rather than adding an overload parameter to the data method, which would be the other approach to this).
points.clustered(d): where d is the data value passed to a style accessor, returns a boolean
points.clusterPointCount(d): returns the count of points (1 for unclustered)
points.clusterPoint(d, cluster_point_index): returns a specific point within the cluster. This is the original data record, not the cluster point record.
points.clusterPoints(d, onlyDirect=false, limit=null): return the points associated with a cluser. If onlyDirect was set, this would not include sub-clusters. If onlyDirect is false, this is functionally the list that is used to pull points from points.getClusterPoint(d, cluster_point_index). These are the original data records, not the cluster point records.
points.clusterClusters(d): return a list of immediate clusters that are children of this cluster. These could be passed to the cluster* methods above to recurse manually.
With this , our code would now look like:
var original_data = [... some array of point data that contains style information on each point ...];
var points = layer.createFeature('point');
points.data(original_data);
points.clustering({radius: 10});
points.style({
radius: (d, i) => 5 * this.clusterPointCount(d) ** 0.5,
fillColor: (d, i) => this.clusterPoint(d, 0).fillColor,
strokeColor: (d, i) => this.clusterPoint(d, 0).strokeColor,
fillOpacity: (d, i) => this.clusterPoint(d, 0).fillOpacity,
strokeOpacity: (d, i) => this.clusterPoint(d, 0).strokeOpacity,
});
Point features (and by extension marker features) support clustering. Once clustered,
point.data()returns the clustered data, which is a list of unclustered point records followed by the clustered point records for a particular zoom level. The style accessors reference these records, not the original records set indata(). There isn't currently any official way to get the original data value or to get the points within different clusters.As such, this results in messy code like
This is a mess -- we shouldn't need to access the internal methods and properties to do this. There is also an internal
__dataproperty that is not used and not set as commented.We should remove
__dataand add some convenience methods. (update: see #1389)I think the following would be appropriate:
points.unclusteredData(): return the original data (rather than adding an overload parameter to thedatamethod, which would be the other approach to this).points.clustered(d): wheredis the data value passed to a style accessor, returns a booleanpoints.clusterPointCount(d): returns the count of points (1 for unclustered)points.clusterPoint(d, cluster_point_index): returns a specific point within the cluster. This is the original data record, not the cluster point record.points.clusterPoints(d, onlyDirect=false, limit=null): return the points associated with a cluser. IfonlyDirectwas set, this would not include sub-clusters. IfonlyDirectis false, this is functionally the list that is used to pull points frompoints.getClusterPoint(d, cluster_point_index). These are the original data records, not the cluster point records.points.clusterClusters(d): return a list of immediate clusters that are children of this cluster. These could be passed to thecluster*methods above to recurse manually.With this , our code would now look like: