ol-mapbox-style
ol-mapbox-style copied to clipboard
List of unsupported or not working style elements
Hi, When style rendered not as expected, it's hard to determine if its a bug in style/data or part of style is unsupported by ol-mapbox-style It would be nice to have list of unsupported and not working elements from Mapbox Style Specification on the main page or in the docs. And when or if they will be supported. It also would be nice to have "strict" mode option enabling which would produce warnings or errors in console for unsupported elements While trying to implement style for floor plan i found this elements not working:
- line-pattern
- line-offset (Not supported in ol. Will be supported: ?)
- fill-extrusion (Not supported in ol. Will be supported: no)
- symbol-sort-key
I created simple example of same Mapbox Style rendered with ol-mapbox-style (top) and mapbox-gl (bottom): https://codesandbox.io/s/ol-mapbox-style-missing-features-wrg51?file=/main.js In this example:
- line with line-pattern drawn as blue line
- lines with line-offset are invisible
- polygon with fill-extrusion is flat
- two points (text) with symbol-sort-key drawn one on top another (i originally tried using symbol-sort-key for icons, аnd found no mention of symbol-sort-key in git. Text labels overlapping each other may be because of another bug or missing declutter: true)
Mapbox Style Specification links: paint-line-line-pattern paint-line-line-offset fill-extrusion layout-symbol-symbol-sort-key
Creating a list of supported options would be a a welcome pull request. It should be easy to grep stylefunction.js
for all properties, and see which ones are found in there. Those are the supported ones.
line-pattern
is not supported, but line-dasharray
could be used to make a line look like yours.
fill-extrusion
should be easy to implement, if someone wants to take that on.
symbol-sort-key
is also something that could be implemented quite easily. To avoid the overlapping labels, ol-mapbox-style
should also configure Vector
layers with declutter: true
, not only VectorTile
layers. This would also be an easy pull request.
Would you be able and willing to take on any of the above tasks and provide pull requests?
The line-offset
, line-translate
, and fill-translate
properties should be fairly straightforward to implement.
I was thinking about using the translate property on Geometry
objects. But this imply a temporary duplication of the feature.
What do you think?
Regarding the list of supported features, the grep script
should be made available or we only need to provide a list that will be modified as we go along?
Any idea how that line-offset could be implemented?
Definitely not by using the translate()
method of the geometry, which is only useful for line-translate
and fill-translate
. It would require creating an offset geometry, and assigning that to the geometry
property of the used style (by using setGeometry()
).
I tried the following (main points briefly):
In case 'line-offset' is defined for 'line' type layer, get the original coordinates with feature.getGeometry().getFlatCoordinates() and store them to offsetCoordinates with the calculated offset, then create a new RenderFeature with 'LineString' type and the offsetCoordinates and set that to the style with style.setGeometry.
This works almost perfectly, but I get some strange quirks that on certain zoom levels the features get somehow mixed up so that some of the surrounding features are included in the style. The sources are MVT and all the quirks are clearly constrained to certain tiles.



Styles get reused, currently without checking for getGeometry()
. That explains the quirks you're seeing. So you need to add such a check, and not reuse the style in this case.
Ok, thanks, I'll try to fix the style usage.
Btw, for some reason I was not able to clone the geometry with the .clone() function which is available in openlayers geometry, but I don't know the ol-mapbox-style internals enough to understand the reason.
It‘s because we‘re dealing with ol/render/Feature
here, which only supports a subset of the full Feature API.
I had experimented with implementing this offset. Here is the code snippet I had if it helps
const lineOffset = getValue(layer, 'paint', 'line-offset', zoom, f);
if (lineOffset) {
let newGeometry = feature.clone().getGeometry();
newGeometry.translate(dx,dy) // TODO : check how to get dx and dy from lineOffset
feature.setGeometry(newGeometry)
style.setGeometry(newGeometry);
styles[stylesLength] = style;
}
I was not able to use the clone either on geometry or feature. Also, to my understanding the translate is usable only for straight lines. For lines that consists of multiple segments, the proper offset needs to be calculated separately for each - basically the new segment should be moving in the 90 degree direction from the original.
I used this:
if (offset) {
const offsetCoordinates = [];
const geom = feature.getGeometry();
const stride = geom.getStride();
const coordinates = geom.getFlatCoordinates();
for (
let i = 0, ii = coordinates.length - stride;
i < ii;
i += stride
) {
const x1 = coordinates[i];
const y1 = coordinates[i + 1];
const x2 = coordinates[i + stride];
const y2 = coordinates[i + stride + 1];
const angle = Math.atan2(y2 - y1, x2 - x1);
const sin = Math.sin(angle) * offset;
const cos = Math.cos(angle) * offset;
offsetCoordinates[i] = x1 + sin;
offsetCoordinates[i + 1] = y1 - cos;
if (i == coordinates.length - stride * 2) {
offsetCoordinates[i + 2] = x2 + sin;
offsetCoordinates[i + 3] = y2 - cos;
}
}
const offsetFeature = new RenderFeature(
'LineString',
offsetCoordinates,
[offsetCoordinates.length],
feature.getProperties(),
feature.id_
);
style.setGeometry(offsetFeature);
}