Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Style Parsing #164

Merged
merged 13 commits into from
Aug 9, 2023
3 changes: 2 additions & 1 deletion elements/map/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"type": "module",
"dependencies": {
"lit-html": "^2.7.4",
"ol": "7.3.0"
"ol": "^7.4.0",
"ol-mapbox-style": "^10.6.0"
},
"devDependencies": {
"@eox/eslint-config": "^1.0.0",
Expand Down
2 changes: 1 addition & 1 deletion elements/map/src/draw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function addDraw(EOxMap: EOxMap, layerId: string, options: any): void {
const source = drawLayer.getSource();

const drawInteraction = new Draw({
type: options.type,
...options,
source,
});

Expand Down
45 changes: 44 additions & 1 deletion elements/map/src/generate.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import * as olLayers from "ol/layer";
import * as olSources from "ol/source";
import * as olFormats from "ol/format";
import { applyStyle } from "ol-mapbox-style";
import { FlatStyleLike } from "ol/style/flat";
import mapboxgl, { AnySourceData } from "mapbox-gl";

type EoxLayer = {
type: olLayers.Layer;
id: string;
properties?: Object;
source?: { type: olSources.Source };
layers?: Array<EoxLayer>;
style?: mapboxgl.Style | FlatStyleLike;
};

export const generateLayers = (layerArray: Array<EoxLayer>) => {
Expand All @@ -26,7 +30,8 @@ export const generateLayers = (layerArray: Array<EoxLayer>) => {
if (layer.source && !newSource) {
throw new Error(`Source type ${layer.source.type} not supported!`);
}
return new newLayer({

const olLayer = new newLayer({
...layer,
group,
...(layer.source && {
Expand All @@ -39,11 +44,49 @@ export const generateLayers = (layerArray: Array<EoxLayer>) => {
}),
}),
}),
style: undefined, // override layer style, apply style after
// @ts-ignore
...(layer.type === "Group" && {
layers: layer.layers.reverse().map((l) => createLayer(l, layer.id)),
}),
});

if (layer.style) {
if ("version" in layer.style) {
const mapboxStyle: mapboxgl.Style = layer.style;
// existing layer source will not get overridden by "style" property
// to allow vector layers without defined sources, create a dummy-geojson-source
// if source does exist
if (!mapboxStyle.sources) {
mapboxStyle.sources = {};
}
// @ts-ignore
const sourceName = layer.properties.id;
if (!mapboxStyle.sources[sourceName]) {
const dummy =
//@ts-ignore
layer.source.type === "VectorTile"
? {
type: "vector",
}
: {
type: "geojson",
data: {
type: "FeatureCollection",
//@ts-ignore
features: [],
},
};
mapboxStyle.sources[sourceName] = dummy as AnySourceData;
}
applyStyle(olLayer, mapboxStyle, sourceName, {
updateSource: false,
});
} else {
olLayer.setStyle(layer.style);
}
}
return olLayer;
}

return layerArray.reverse().map((l) => createLayer(l));
Expand Down
5 changes: 5 additions & 0 deletions elements/map/test/drawInteraction.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ describe("draw interaction", () => {
eoxMap.addDraw("drawLayer", {
id: "drawInteraction",
type: "Polygon",
style: {
"fill-color": "yellow",
"stroke-color": "black",
"stroke-width": 4,
},
});

eoxMap.addEventListener("drawend", (evt) => {
Expand Down
47 changes: 47 additions & 0 deletions elements/map/test/vectorLayer.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,51 @@ describe("layers", () => {
expect(eoxMap.getLayerById("regions")).to.exist;
});
});
it("correctly applies mapbox style", () => {
cy.mount(
`<eox-map layers='${JSON.stringify(vectorLayerStyleJson)}'></eox-map>`
).as("eox-map");
cy.get("eox-map").and(($el) => {
return new Cypress.Promise((resolve) => {
const layers = (<EOxMap>$el[0]).map.getLayers().getArray();
// wait for features to load
//@ts-ignore
layers[0].getSource().on("featuresloadend", () => {
//@ts-ignore
const feature = layers[0].getSource().getFeatures()[0];
//@ts-ignore
const styles = layers[0].getStyleFunction()(feature);
// 2 styles expected, one for the stroke, one for the fill.
expect(styles).to.have.length(2);
resolve();
});
});
});
});
it("correctly applies flat style", () => {
vectorLayerStyleJson[0].style = {
// @ts-ignore
"fill-color": "yellow",
"stroke-color": "black",
"stroke-width": 4,
};
cy.mount(
`<eox-map layers='${JSON.stringify(vectorLayerStyleJson)}'></eox-map>`
).as("eox-map");
cy.get("eox-map").and(($el) => {
return new Cypress.Promise((resolve) => {
const layers = (<EOxMap>$el[0]).map.getLayers().getArray();
// wait for features to load
//@ts-ignore
layers[0].getSource().on("featuresloadend", () => {
//@ts-ignore
const feature = layers[0].getSource().getFeatures()[0];
//@ts-ignore
const styles = layers[0].getStyleFunction()(feature);
expect(styles).to.have.length(1);
resolve();
});
});
});
});
});
27 changes: 26 additions & 1 deletion elements/map/test/vectorLayer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[
{
"type": "Vector",
"background": "#1a2b39",
"background": "#1366dd",
"properties": {
"id": "regions"
},
Expand All @@ -10,6 +10,31 @@
"url": "https://openlayers.org/data/vector/ecoregions.json",
"format": "GeoJSON",
"attributions": "Regions: @ openlayers.org"
},
"style": {
"version": 8,
"name": "regions",
"sources": {},
"layers": [
{
"id": "regions_fill",
"type": "fill",
"source": "regions",
"paint": {
"fill-color": ["get", "COLOR"],
"fill-opacity": 1
}
},
{
"id": "regions_outline",
"type": "line",
"source": "regions",
"paint": {
"line-color": "#141414",
"line-width": 1.5
}
}
]
}
}
]
77 changes: 68 additions & 9 deletions elements/map/test/vectorTilesLayer.cy.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,78 @@
import { VectorTile } from "ol/layer";
import "../main";
import vectorTileLayerStyleJson from "./vectorTilesLayer.json";
import { VectorTile } from "ol/layer";

describe("VectorTile Layer", () => {
it("loads a Vector Layer", () => {
it("loads a Vector Layer, applies flat style", () => {
// @ts-ignore
vectorTileLayerStyleJson[0].style = {
// @ts-ignore
"fill-color": "yellow",
"stroke-color": "black",
"stroke-width": 4,
};
cy.mount(
`<eox-map layers='${JSON.stringify(vectorTileLayerStyleJson)}'></eox-map>`
).as("eox-map");
return new Cypress.Promise((resolve) => {
cy.get("eox-map").should(($el) => {
const eoxMap = <EOxMap>$el[0];
const layer = eoxMap.getLayerById("countries") as VectorTile;
setTimeout(() => {
// to do: not able to wait for rendercomplete directly, as `applyStyle` is async
const features = layer
.getSource()
.getFeaturesInExtent(eoxMap.map.getView().calculateExtent());
expect(features.length).to.be.greaterThan(10);
resolve();
}, 1000);
});
});
});
it("loads a Vector Layer, applies mapbox style", () => {
vectorTileLayerStyleJson[0].style = {
version: 8,
name: "countries",
sources: {},
layers: [
{
id: "countries_fill",
type: "fill",
source: "countries",
"source-layer": "ne_10m_admin_0_countries",
paint: {
"fill-color": "green",
"fill-opacity": 1,
},
},
{
id: "countries_outline",
type: "line",
source: "countries",
"source-layer": "ne_10m_admin_0_countries",
paint: {
"line-color": "#cdcdcd",
"line-width": 2.5,
},
},
],
};
cy.mount(
`<eox-map layers='${JSON.stringify(vectorTileLayerStyleJson)}'></eox-map>`
).as("eox-map");
cy.get("eox-map").and(($el) => {
const eoxMap = <EOxMap>$el[0];
const layer = eoxMap.getLayerById("countries") as VectorTile;
const features = layer
.getSource()
.getFeaturesInExtent(eoxMap.map.getView().calculateExtent());
expect(features.length).to.be.greaterThan(10);
return new Cypress.Promise((resolve) => {
cy.get("eox-map").should(($el) => {
const eoxMap = <EOxMap>$el[0];
const layer = eoxMap.getLayerById("countries") as VectorTile;
setTimeout(() => {
// to do: not able to wait for rendercomplete directly, as `applyStyle` is async
const features = layer
.getSource()
.getFeaturesInExtent(eoxMap.map.getView().calculateExtent());
expect(features.length).to.be.greaterThan(10);
resolve();
}, 1000);
});
});
});
});
Loading
Loading