Skip to content

Commit

Permalink
Allow precise customization by passing the feature object
Browse files Browse the repository at this point in the history
Without the feature object customizers have very little information to apply style changes.
Now they will be able to look at the feature properties.

This is also true for the protected methods of the Vector Encoder.
  • Loading branch information
gberaudo committed Jun 11, 2024
1 parent 1959855 commit f707cb4
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 37 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Use ol getFontParameters to parse font.
- Fallback to fill color if none is specified on circle style.
- Pass feature object to allow informed customization.


## 0.2.14
Expand Down
6 changes: 3 additions & 3 deletions src/BaseCustomizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,23 +67,23 @@ export default class BaseCustomizer {
* @param symbolizer
* @param stroke
*/
line(layerState: State, symbolizer: MFPSymbolizerLine, stroke: Stroke) {}
line(layerState: State, geojsonFeature: GeoJSONFeature, symbolizer: MFPSymbolizerLine, stroke: Stroke) {}

/**
* Can be used to manipulate the image symbolizers
* @param layerState
* @param symbolizer
* @param image
*/
point(layerState: State, symbolizer: MFPSymbolizerPoint, image: Image) {}
point(layerState: State, geojsonFeature: GeoJSONFeature, symbolizer: MFPSymbolizerPoint, image: Image) {}

/**
* Can be used to manipulate the text symbolizers
* @param layerState
* @param symbolizer
* @param text
*/
text(layerState: State, symbolizer: MFPSymbolizerText, text: Text) {}
text(layerState: State, geojsonFeature: GeoJSONFeature, symbolizer: MFPSymbolizerText, text: Text) {}

/**
* Can be used to manipulate a converted WMTS layer
Expand Down
74 changes: 40 additions & 34 deletions src/VectorEncoder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {rgbArrayToHex} from './utils';
import {GeoJSON as olFormatGeoJSON} from 'ol/format.js';
import type {Fill, Icon, Image, Stroke, Style, Text} from 'ol/style.js';
import {Circle as olStyleCircle, Icon as olStyleIcon} from 'ol/style.js';
import type {Fill, Icon, Image, Style, Text} from 'ol/style.js';
import {Circle as olStyleCircle, Icon as olStyleIcon, Stroke} from 'ol/style.js';
import Feature from 'ol/Feature.js';
import type Circle from 'ol/geom/Circle.js';
import {getUid} from 'ol';
Expand All @@ -26,6 +26,7 @@ import {fromCircle} from 'ol/geom/Polygon.js';
import {Constants} from './constants';

import {getFontParameters} from 'ol/css.js';
import {type ColorLike} from 'ol/colorlike';

/** Represents the different types of printing styles. */
export const PrintStyleType = {
Expand All @@ -34,21 +35,23 @@ export const PrintStyleType = {
POLYGON: 'Polygon',
} as const;

/** Supported geometry types */
type GeometryType = 'LineString' | 'Point' | 'Polygon' | 'MultiLineString' | 'MultiPolygon';

/**
* Link between supported geometry and print style types.
* Circles will be handled as polygon.
* */
export const PrintStyleTypes_ = {
export const PrintStyleTypes = Object.freeze({
LineString: PrintStyleType.LINE_STRING,
Point: PrintStyleType.POINT,
Polygon: PrintStyleType.POLYGON,
MultiLineString: PrintStyleType.LINE_STRING,
MultiPoint: PrintStyleType.POINT,
MultiPolygon: PrintStyleType.POLYGON,
} as const;
});

function isSupportedGeometryType(geometryType: string): geometryType is keyof typeof PrintStyleTypes {
return geometryType in PrintStyleTypes;
}

/** Key prefix to feature style prop */
const FEATURE_STYLE_PROP = '_mfp_style';
Expand Down Expand Up @@ -203,8 +206,7 @@ export default class VectorEncoder {
}
}

const geometryType = geometry.getType();
this.addVectorStyle(mapfishStyleObject, geojsonFeature, geometryType, style);
this.addVectorStyle(mapfishStyleObject, geojsonFeature, style);
});
}

Expand Down Expand Up @@ -241,7 +243,6 @@ export default class VectorEncoder {
addVectorStyle(
mapfishStyleObject: MFPVectorStyle,
geojsonFeature: GeoJSONFeature,
geometryType: GeometryType,
style: Style,
) {
const styleId = this.getDeepStyleUid(style);
Expand All @@ -251,7 +252,7 @@ export default class VectorEncoder {
// do nothing if we already have a style object for this CQL rule
hasSymbolizer = true;
} else {
const styleObject = this.encodeVectorStyle(geometryType, style);
const styleObject = this.encodeVectorStyle(geojsonFeature, style);
hasSymbolizer = styleObject && styleObject.symbolizers.length !== 0;
if (hasSymbolizer) {
// @ts-ignore
Expand Down Expand Up @@ -288,12 +289,13 @@ export default class VectorEncoder {
* Encodes the vector style based on the geometry type and style.
* @returns The encoded vector style, or null if the geometry type is unsupported.
*/
encodeVectorStyle(geometryType: GeometryType, style: Style): MFPSymbolizers | null {
if (!(geometryType in PrintStyleTypes_)) {
encodeVectorStyle(geojsonFeature: GeoJSONFeature, style: Style): MFPSymbolizers | null {
const geometryType = geojsonFeature.geometry.type;
if (!isSupportedGeometryType(geometryType)) {
console.warn('Unsupported geometry type: ', geometryType);
return null;
}
const styleType = PrintStyleTypes_[geometryType];
const styleType = PrintStyleTypes[geometryType];
const styleObject = {
symbolizers: [],
} as MFPSymbolizers;
Expand All @@ -303,19 +305,19 @@ export default class VectorEncoder {
const textStyle = style.getText();
if (styleType === PrintStyleType.POLYGON) {
if (fillStyle !== null) {
this.encodeVectorStylePolygon(styleObject.symbolizers, fillStyle, strokeStyle);
this.encodeVectorStylePolygon(geojsonFeature, styleObject.symbolizers, fillStyle, strokeStyle);
}
} else if (styleType === PrintStyleType.LINE_STRING) {
if (strokeStyle !== null) {
this.encodeVectorStyleLine(styleObject.symbolizers, strokeStyle);
this.encodeVectorStyleLine(geojsonFeature, styleObject.symbolizers, strokeStyle);
}
} else if (styleType === PrintStyleType.POINT) {
if (imageStyle !== null) {
this.encodeVectorStylePoint(styleObject.symbolizers, imageStyle);
this.encodeVectorStylePoint(geojsonFeature, styleObject.symbolizers, imageStyle);
}
}
if (textStyle !== null) {
this.encodeVectorStyleText(styleObject.symbolizers, textStyle);
this.encodeVectorStyleText(geojsonFeature, styleObject.symbolizers, textStyle);
}
return styleObject;
}
Expand All @@ -324,6 +326,7 @@ export default class VectorEncoder {
* Encodes the vector style fill for a symbolizer.
*/
protected encodeVectorStyleFill(
geojsonFeature: GeoJSONFeature,
symbolizer: MFPSymbolizerPoint | MFPSymbolizerPolygon | MFPSymbolizerText,
fillStyle: Fill,
) {
Expand All @@ -342,27 +345,27 @@ export default class VectorEncoder {
/**
* Encodes the vector style for a line symbolizer, using the given stroke style.
*/
protected encodeVectorStyleLine(symbolizers: MFPSymbolizer[], strokeStyle: Stroke) {
protected encodeVectorStyleLine(geojsonFeature: GeoJSONFeature, symbolizers: MFPSymbolizer[], strokeStyle: Stroke) {
const symbolizer = {
type: 'line',
} as MFPSymbolizerLine;
this.encodeVectorStyleStroke(symbolizer, strokeStyle);
this.customizer_.line(this.layerState_, symbolizer, strokeStyle);
this.encodeVectorStyleStroke(geojsonFeature, symbolizer, strokeStyle);
this.customizer_.line(this.layerState_, geojsonFeature, symbolizer, strokeStyle);
symbolizers.push(symbolizer);
}

/**
* Encodes a vector style point.
*/
protected encodeVectorStylePoint(symbolizers: MFPSymbolizer[], imageStyle: Image) {
protected encodeVectorStylePoint(geojsonFeature: GeoJSONFeature, symbolizers: MFPSymbolizer[], imageStyle: Image) {
let symbolizer: MFPSymbolizerPoint | undefined;
if (imageStyle instanceof olStyleCircle) {
symbolizer = this.encodeVectorStylePointStyleCircle(imageStyle);
symbolizer = this.encodeVectorStylePointStyleCircle(geojsonFeature, imageStyle);
} else if (imageStyle instanceof olStyleIcon) {
symbolizer = this.encodeVectorStylePointStyleIcon(imageStyle);
symbolizer = this.encodeVectorStylePointStyleIcon(geojsonFeature, imageStyle);
}
if (symbolizer) {
this.customizer_.point(this.layerState_, symbolizer, imageStyle);
this.customizer_.point(this.layerState_, geojsonFeature, symbolizer, imageStyle);
symbolizers.push(symbolizer);
}
}
Expand All @@ -371,7 +374,7 @@ export default class VectorEncoder {
* Encodes the vector style point style circle.
* @returns The encoded symbolizer point.
*/
protected encodeVectorStylePointStyleCircle(imageStyle: olStyleCircle): MFPSymbolizerPoint {
protected encodeVectorStylePointStyleCircle(geojsonFeature: GeoJSONFeature, imageStyle: olStyleCircle): MFPSymbolizerPoint {
const symbolizer = {
type: 'point',
} as MFPSymbolizerPoint;
Expand All @@ -386,17 +389,19 @@ export default class VectorEncoder {
}
const fillStyle = imageStyle.getFill();
let strokeStyle = imageStyle.getStroke();

if (fillStyle !== null) {
this.encodeVectorStyleFill(symbolizer, fillStyle);
this.encodeVectorStyleFill(geojsonFeature, symbolizer, fillStyle);
if (!strokeStyle) {
// Without a stroke style a black border would appear around the circle
strokeStyle = new Stroke({
color: fillStyle.getColor() as ColorLike,
});
}
}

if (strokeStyle !== null) {
this.encodeVectorStyleStroke(symbolizer, strokeStyle);
this.encodeVectorStyleStroke(geojsonFeature, symbolizer, strokeStyle);
}
return symbolizer;
}
Expand All @@ -405,7 +410,7 @@ export default class VectorEncoder {
* Encodes a Vector Style point style icon.
* @returns The encoded symbolizer point style or undefined if imageStyle src is undefined.
*/
protected encodeVectorStylePointStyleIcon(imageStyle: olStyleIcon): MFPSymbolizerPoint | undefined {
protected encodeVectorStylePointStyleIcon(geojsonFeature: GeoJSONFeature, imageStyle: olStyleIcon): MFPSymbolizerPoint | undefined {
const src = imageStyle.getSrc();
if (src === undefined) {
return undefined;
Expand Down Expand Up @@ -474,13 +479,13 @@ export default class VectorEncoder {
/**
* Encodes the vector style of a polygon by applying fill and stroke styles.
*/
protected encodeVectorStylePolygon(symbolizers: MFPSymbolizer[], fillStyle: Fill, strokeStyle: Stroke) {
protected encodeVectorStylePolygon(geojsonFeature: GeoJSONFeature, symbolizers: MFPSymbolizer[], fillStyle: Fill, strokeStyle: Stroke) {
const symbolizer = {
type: 'polygon',
} as MFPSymbolizerPolygon;
this.encodeVectorStyleFill(symbolizer, fillStyle);
this.encodeVectorStyleFill(geojsonFeature, symbolizer, fillStyle);
if (strokeStyle !== null) {
this.encodeVectorStyleStroke(symbolizer, strokeStyle);
this.encodeVectorStyleStroke(geojsonFeature, symbolizer, strokeStyle);
}
symbolizers.push(symbolizer);
}
Expand All @@ -489,6 +494,7 @@ export default class VectorEncoder {
* Encodes the vector style stroke properties.
*/
protected encodeVectorStyleStroke(
geojsonFeature: GeoJSONFeature,
symbolizer: MFPSymbolizerPoint | MFPSymbolizerLine | MFPSymbolizerPolygon,
strokeStyle: Stroke,
) {
Expand Down Expand Up @@ -523,7 +529,7 @@ export default class VectorEncoder {
/**
* Encodes vector style text.
*/
protected encodeVectorStyleText(symbolizers: MFPSymbolizer[], textStyle: Text) {
protected encodeVectorStyleText(geojsonFeature: GeoJSONFeature, symbolizers: MFPSymbolizer[], textStyle: Text) {
const label = textStyle.getText();
if (label) {
const fp = getFontParameters(textStyle.getFont() || 'sans-serif');
Expand All @@ -542,7 +548,7 @@ export default class VectorEncoder {
} as MFPSymbolizerText;
const fillStyle = textStyle.getFill();
if (fillStyle !== null) {
this.encodeVectorStyleFill(symbolizer, fillStyle);
this.encodeVectorStyleFill(geojsonFeature, symbolizer, fillStyle);
symbolizer.fontColor = symbolizer.fillColor;
}
const strokeStyle = textStyle.getStroke();
Expand All @@ -561,7 +567,7 @@ export default class VectorEncoder {
symbolizer.haloRadius = strokeWidth;
}
}
this.customizer_.text(this.layerState_, symbolizer, textStyle);
this.customizer_.text(this.layerState_, geojsonFeature, symbolizer, textStyle);
symbolizers.push(symbolizer);
}
}
Expand Down

0 comments on commit f707cb4

Please sign in to comment.