In a small demo I created, there was a small requirement: to retrieve features with specified attributes through a database search and then highlight them.
If using the conventional WFS loading method, there is no problem; you can simply traverse the layer
's feature source
. There is no issue with the logic, regardless of efficiency. However, there is a requirement that the layer has a very large number of features
(due to the buffer zones generated for coastlines on a global scale), so during the map loading process, vector tiles are used. The source
of vector tiles does not have a getFeatures()
method, which complicates the traversal of features that need to be highlighted.
The static style of the layer is set using the latest example from openlayers
:
// Color table
const colorTable = {
"No": "rgba(200, 54, 54, 0)",
"type1": "#FF0000",
"type2": "#E69800",
...
"": "#00FFFFFF",
};
export function createRiskLevelStyle(feature) {
const riskLevel = feature.get('props_X');
let selected = !!selection[feature.getId()];
return new Style({
fill: new Fill({
//color: colorTable[riskLevel],
color: selected ? 'rgba(200,20,20,0.8)' : colorTable[riskLevel],
//color:
}),
stroke: new Stroke({
color: '#FFFFFF',
width: 0.1,
})
})
}
Here, selected
is used for highlighting on mouse click. The logic is roughly that after clicking, the id
of the feature
is stored as a key value to indicate that the feature has been selected.
Naturally, when considering this requirement, my first thought was to traverse the featureCollection
to find the corresponding Id
of the relevant feature and store it in the global variable selection
. However, since the vector tile source
does not have a getFeatures()
method, this idea fell through. I even considered creating a regular WFS layer to traverse the data, but the data volume was too large, requiring over 50 MB for a single load, making this approach completely unfeasible.
Later, considering that since the style can be set using this form of styleFunc
during loading, I wondered if assigning a new Func
to the layer during retrieval would be effective and how the performance would be. Thus, after slight adjustments to the styleFunc
, it became as follows:
export function createRiskLevelStyleSearch(names) {
return function (feature) {
const riskLevel = feature.get('props_X');
let properties = feature.getProperties();
let zh = properties['label'];
let en = properties['name'];
let searched = false;
if (zh === undefined || en === undefined) {
searched = false;
} else {
names.forEach((v) => {
if (en === v.key)
searched = true;
});
}
return new Style({
fill: new Fill({
//color: colorTable[riskLevel],
color: searched ? 'rgba(200,20,20,0.8)' : colorTable[riskLevel],
//color:
}),
stroke: new Stroke({
color: '#FFFFFF',
width: 0.1,
})
});
}
}
The parameter names
is an array of country names, where the key
of each item
corresponds to the value that needs to be searched.
This method performs reasonably well with this data volume, as shown in the image below: