diff --git a/core/src/main/java/net/pl3x/map/core/markers/marker/Icon.java b/core/src/main/java/net/pl3x/map/core/markers/marker/Icon.java index d374df88d9..a13e3e6318 100644 --- a/core/src/main/java/net/pl3x/map/core/markers/marker/Icon.java +++ b/core/src/main/java/net/pl3x/map/core/markers/marker/Icon.java @@ -60,6 +60,11 @@ public class Icon extends Marker { private Vector shadowSize; private Vector shadowAnchor; + private double hueRotation = 0.0; + private double saturation = 1.0; + private double brightness = 1.0; + private double opacity = 1.0; + private Icon(String key) { super("icon", key); } @@ -560,6 +565,86 @@ public Icon setShadowAnchor(@Nullable Vector shadowAnchor) { return this; } + /** + * Get the hue rotation to be applied to the icon image, in degrees between 0 and 360. + * + * @return hue rotation + */ + public double getHueRotation() { + return this.hueRotation; + } + + /** + * Set the hue rotation to be applied to the icon image, in degrees between 0 and 360. + * + * @param hueRotation new hue rotation + * @return this icon + */ + public Icon setHueRotation(double hueRotation) { + this.hueRotation = hueRotation; + return this; + } + + /** + * Get the saturation filter to be applied to the icon image, as a double between 0 and 2. + * + * @return saturation + */ + public double getSaturation() { + return this.saturation; + } + + /** + * Set the saturation filter to be applied to the icon image, as a double between 0 and 2. + * + * @param saturation new saturation + * @return this icon + */ + public Icon setSaturation(double saturation) { + this.saturation = saturation; + return this; + } + + /** + * Get the brightness filter to be applied to the icon image, as a double between 0 and 2. + * + * @return brightness + */ + public double getBrightness() { + return this.brightness; + } + + /** + * Set the brightness filter to be applied to the icon image, as a double between 0 and 2. + * + * @param brightness new brightness + * @return this icon + */ + public Icon setBrightness(double brightness) { + this.brightness = brightness; + return this; + } + + /** + * Get the opacity of the icon image, as a double between 0 and 1. + * + * @return opacity + */ + public double getOpacity() { + return this.opacity; + } + + /** + * Set the opacity of the icon image, as a double between 0 and 1. + * + * @param opacity new opacity + * @return this icon + */ + public Icon setOpacity(double opacity) { + this.opacity = opacity; + return this; + } + @Override public JsonObject toJson() { JsonObjectWrapper wrapper = new JsonObjectWrapper(); @@ -576,6 +661,10 @@ public JsonObject toJson() { wrapper.addProperty("rotationAngle", getRotationAngle()); wrapper.addProperty("rotationOrigin", getRotationOrigin()); wrapper.addProperty("pane", getPane()); + wrapper.addProperty("hueRotation", getHueRotation()); + wrapper.addProperty("saturation", getSaturation()); + wrapper.addProperty("brightness", getBrightness()); + wrapper.addProperty("opacity", getOpacity()); return wrapper.getJsonObject(); } @@ -677,6 +766,10 @@ public String toString() { + ",shadowAnchor=" + getShadowAnchor() + ",pane=" + getPane() + ",options=" + getOptions() + + ",hueRotation=" + getHueRotation() + + ",saturation=" + getSaturation() + + ",brightness=" + getBrightness() + + ",opacity=" + getOpacity() + "}"; } } diff --git a/webmap/src/marker/Icon.ts b/webmap/src/marker/Icon.ts index 4e3cbdb212..b84164b656 100644 --- a/webmap/src/marker/Icon.ts +++ b/webmap/src/marker/Icon.ts @@ -19,6 +19,11 @@ interface IconOptions extends L.MarkerOptions { rotationAngle?: number; rotationOrigin?: string; pane: string; + className: string; + hueRotation: number; + saturation: number; + brightness: number; + opacity: number; } export class Icon extends Marker { @@ -39,6 +44,13 @@ export class Icon extends Marker { if (isset(data.shadowSize)) props = {...props, shadowSize: [data.shadowSize!.x, data.shadowSize!.z]}; if (isset(data.shadowAnchor)) props = {...props, shadowAnchor: [data.shadowAnchor!.x, data.shadowAnchor!.z]}; + let filterClasses = ""; + if (isset(data.hueRotation)) filterClasses += ` hue-${Math.round(data.hueRotation / 5) * 5}`; + if (isset(data.saturation)) filterClasses += ` sat-${Math.round(data.saturation * 10) * 10}`; + if (isset(data.brightness)) filterClasses += ` bright-${Math.round(data.brightness * 10) * 10}`; + if (isset(data.opacity)) filterClasses += ` opacity-${Math.round(data.opacity * 5) * 20}`; + if(filterClasses.length > 0) props = {...props, className: "dynamic-filter " + filterClasses.trim()}; + const tooltipOffset: L.PointExpression | undefined = type.options?.tooltip?.properties?.offset; const popupOffset: L.PointExpression | undefined = type.options?.popup?.properties?.offset; @@ -73,6 +85,7 @@ export class Icon extends Marker { const iconOptions: IconOptions = icon.options as IconOptions; iconOptions.rotationAngle = data.rotationAngle; iconOptions.rotationOrigin = data.rotationOrigin; + iconOptions.hueRotation = data.hueRotation; if (options?.tooltip?.content) { icon.setTooltipContent(options?.tooltip?.content); } diff --git a/webmap/src/scss/_filter.scss b/webmap/src/scss/_filter.scss new file mode 100644 index 0000000000..ab282dfc0c --- /dev/null +++ b/webmap/src/scss/_filter.scss @@ -0,0 +1,31 @@ +.dynamic-filter { + filter: hue-rotate(var(--hue,)) Saturate(var(--sat,)) Brightness(var(--bright,)); +} + +@for $i from 0 through 20 { + $percentage: $i * 10; + .sat-#{$percentage} { + --sat: #{$percentage / 100}; + } +} + +@for $i from 0 through 72 { + $degrees: $i * 5; + .hue-#{$degrees} { + --hue: #{$degrees}deg; + } +} + +@for $i from 0 through 40 { + $percentage: $i * 10; + .bright-#{$percentage} { + --bright: #{$percentage / 100}; + } +} + +@for $i from 0 through 20 { + $percentage: $i * 5; + .opacity-#{$percentage} { + opacity: #{$percentage / 100}; + } +} diff --git a/webmap/src/scss/styles.scss b/webmap/src/scss/styles.scss index ae47f571fc..241ce66f86 100644 --- a/webmap/src/scss/styles.scss +++ b/webmap/src/scss/styles.scss @@ -2,6 +2,7 @@ @import 'placeholders'; @import 'leaflet'; @import 'sidebar'; +@import 'filter'; :root { color-scheme: dark;