Skip to content

Commit 94e9ab1

Browse files
committed
refactor(StyleOptions): move StyleOptions from Style to its own file
1 parent cfb9d0f commit 94e9ab1

File tree

5 files changed

+405
-251
lines changed

5 files changed

+405
-251
lines changed

src/Core/Feature.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as THREE from 'three';
22
import Extent from 'Core/Geographic/Extent';
33
import Coordinates from 'Core/Geographic/Coordinates';
44
import CRS from 'Core/Geographic/Crs';
5-
import Style from 'Core/Style';
5+
import StyleOptions from 'Core/StyleOptions';
66

77
function defaultExtent(crs) {
88
return new Extent(crs, Infinity, -Infinity, Infinity, -Infinity);
@@ -251,7 +251,7 @@ class Feature {
251251
}
252252
this._pos = 0;
253253
this._pushValues = (this.size === 3 ? push3DValues : push2DValues).bind(this);
254-
this.style = Style.setFromProperties;
254+
this.style = StyleOptions.setFromProperties;
255255
}
256256
/**
257257
* Instance a new {@link FeatureGeometry} and push in {@link Feature}.

src/Core/Style.js

Lines changed: 0 additions & 246 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import { FEATURE_TYPES } from 'Core/Feature';
21
import Cache from 'Core/Scheduler/Cache';
32
import Fetcher from 'Provider/Fetcher';
4-
import * as mapbox from '@mapbox/mapbox-gl-style-spec';
53
import { Color } from 'three';
64
import { deltaE } from 'Renderer/Color';
75
import Coordinates from 'Core/Geographic/Coordinates';
@@ -13,8 +11,6 @@ const cacheStyle = new Cache();
1311
const matrix = document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGMatrix();
1412
const canvas = document.createElement('canvas');
1513

16-
const inv255 = 1 / 255;
17-
1814
function baseAltitudeDefault(properties, ctx) {
1915
return ctx?.coordinates?.z || 0;
2016
}
@@ -47,37 +43,6 @@ export function readExpression(property, ctx) {
4743
return property;
4844
}
4945

50-
function rgba2rgb(orig) {
51-
if (!orig) {
52-
return {};
53-
} else if (orig.stops || orig.expression) {
54-
return { color: orig };
55-
} else if (typeof orig == 'string') {
56-
const result = orig.match(/(?:((hsl|rgb)a? *\(([\d.%]+(?:deg|g?rad|turn)?)[ ,]*([\d.%]+)[ ,]*([\d.%]+)[ ,/]*([\d.%]*)\))|(#((?:[\d\w]{3}){1,2})([\d\w]{1,2})?))/i);
57-
if (result === null) {
58-
return { color: orig, opacity: 1.0 };
59-
} else if (result[7]) {
60-
let opacity = 1.0;
61-
if (result[9]) {
62-
opacity = parseInt(result[9].length == 1 ? `${result[9]}${result[9]}` : result[9], 16) * inv255;
63-
}
64-
return { color: `#${result[8]}`, opacity };
65-
} else if (result[1]) {
66-
return { color: `${result[2]}(${result[3]},${result[4]},${result[5]})`, opacity: (result[6] ? Number(result[6]) : 1.0) };
67-
}
68-
}
69-
}
70-
71-
function readVectorProperty(property, options) {
72-
if (property != undefined) {
73-
if (mapbox.expression.isExpression(property)) {
74-
return mapbox.expression.createExpression(property, options).value;
75-
} else {
76-
return property;
77-
}
78-
}
79-
}
80-
8146
async function loadImage(source) {
8247
let promise = cacheStyle.get(source, 'null');
8348
if (!promise) {
@@ -700,217 +665,6 @@ class Style {
700665
this.context = ctx;
701666
}
702667

703-
/**
704-
* set Style from (geojson-like) properties.
705-
* @param {Object} properties (geojson-like) properties.
706-
* @param {FeatureContext} featCtx the context of the feature
707-
*
708-
* @returns {StyleOptions} containing all properties for itowns.Style
709-
*/
710-
static setFromProperties(properties, featCtx) {
711-
const type = featCtx.type;
712-
const style = {};
713-
if (type === FEATURE_TYPES.POINT) {
714-
const point = {
715-
...(properties.fill !== undefined && { color: properties.fill }),
716-
...(properties['fill-opacity'] !== undefined && { opacity: properties['fill-opacity'] }),
717-
...(properties.stroke !== undefined && { line: properties.stroke }),
718-
...(properties.radius !== undefined && { radius: properties.radius }),
719-
};
720-
if (Object.keys(point).length) {
721-
style.point = point;
722-
}
723-
const text = {
724-
...(properties['label-color'] !== undefined && { color: properties['label-color'] }),
725-
...(properties['label-opacity'] !== undefined && { opacity: properties['label-opacity'] }),
726-
...(properties['label-size'] !== undefined && { size: properties['label-size'] }),
727-
};
728-
if (Object.keys(point).length) {
729-
style.text = text;
730-
}
731-
const icon = {
732-
...(properties.icon !== undefined && { source: properties.icon }),
733-
...(properties['icon-scale'] !== undefined && { size: properties['icon-scale'] }),
734-
...(properties['icon-opacity'] !== undefined && { opacity: properties['icon-opacity'] }),
735-
...(properties['icon-color'] !== undefined && { color: properties['icon-color'] }),
736-
};
737-
if (Object.keys(icon).length) {
738-
style.icon = icon;
739-
}
740-
} else {
741-
const stroke = {
742-
...(properties.stroke !== undefined && { color: properties.stroke }),
743-
...(properties['stroke-width'] !== undefined && { width: properties['stroke-width'] }),
744-
...(properties['stroke-opacity'] !== undefined && { opacity: properties['stroke-opacity'] }),
745-
};
746-
if (Object.keys(stroke).length) {
747-
style.stroke = stroke;
748-
}
749-
if (type !== FEATURE_TYPES.LINE) {
750-
const fill = {
751-
...(properties.fill !== undefined && { color: properties.fill }),
752-
...(properties['fill-opacity'] !== undefined && { opacity: properties['fill-opacity'] }),
753-
};
754-
if (Object.keys(fill).length) {
755-
style.fill = fill;
756-
}
757-
}
758-
}
759-
return style;
760-
}
761-
762-
/**
763-
* set Style from vector tile layer properties.
764-
* @param {Object} layer vector tile layer.
765-
* @param {Object} sprites vector tile layer.
766-
* @param {Number} [order=0]
767-
* @param {Boolean} [symbolToCircle=false]
768-
*
769-
* @returns {StyleOptions} containing all properties for itowns.Style
770-
*/
771-
static setFromVectorTileLayer(layer, sprites, order = 0, symbolToCircle = false) {
772-
const style = {
773-
fill: {},
774-
stroke: {},
775-
point: {},
776-
text: {},
777-
icon: {},
778-
};
779-
780-
layer.layout = layer.layout || {};
781-
layer.paint = layer.paint || {};
782-
783-
style.order = order;
784-
785-
if (layer.type === 'fill') {
786-
const { color, opacity } = rgba2rgb(readVectorProperty(layer.paint['fill-color'] || layer.paint['fill-pattern'], { type: 'color' }));
787-
style.fill.color = color;
788-
style.fill.opacity = readVectorProperty(layer.paint['fill-opacity']) || opacity;
789-
if (layer.paint['fill-pattern']) {
790-
try {
791-
style.fill.pattern = {
792-
id: layer.paint['fill-pattern'],
793-
source: sprites.source,
794-
cropValues: sprites[layer.paint['fill-pattern']],
795-
};
796-
} catch (err) {
797-
err.message = `VTlayer '${layer.id}': argument sprites must not be null when using layer.paint['fill-pattern']`;
798-
throw err;
799-
}
800-
}
801-
802-
if (layer.paint['fill-outline-color']) {
803-
const { color, opacity } = rgba2rgb(readVectorProperty(layer.paint['fill-outline-color'], { type: 'color' }));
804-
style.stroke.color = color;
805-
style.stroke.opacity = opacity;
806-
style.stroke.width = 1.0;
807-
style.stroke.dasharray = [];
808-
}
809-
} else if (layer.type === 'line') {
810-
const prepare = readVectorProperty(layer.paint['line-color'], { type: 'color' });
811-
const { color, opacity } = rgba2rgb(prepare);
812-
style.stroke.dasharray = readVectorProperty(layer.paint['line-dasharray']);
813-
style.stroke.color = color;
814-
style.stroke.lineCap = layer.layout['line-cap'];
815-
style.stroke.width = readVectorProperty(layer.paint['line-width']);
816-
style.stroke.opacity = readVectorProperty(layer.paint['line-opacity']) || opacity;
817-
} else if (layer.type === 'circle' || symbolToCircle) {
818-
const { color, opacity } = rgba2rgb(readVectorProperty(layer.paint['circle-color'], { type: 'color' }));
819-
style.point.color = color;
820-
style.point.opacity = opacity;
821-
style.point.radius = readVectorProperty(layer.paint['circle-radius']);
822-
} else if (layer.type === 'symbol') {
823-
// overlapping order
824-
style.text.zOrder = readVectorProperty(layer.layout['symbol-z-order']);
825-
if (style.text.zOrder == 'auto') {
826-
style.text.zOrder = readVectorProperty(layer.layout['symbol-sort-key']) || 'Y';
827-
} else if (style.text.zOrder == 'viewport-y') {
828-
style.text.zOrder = 'Y';
829-
} else if (style.text.zOrder == 'source') {
830-
style.text.zOrder = 0;
831-
}
832-
833-
// position
834-
style.text.anchor = readVectorProperty(layer.layout['text-anchor']);
835-
style.text.offset = readVectorProperty(layer.layout['text-offset']);
836-
style.text.padding = readVectorProperty(layer.layout['text-padding']);
837-
style.text.size = readVectorProperty(layer.layout['text-size']);
838-
style.text.placement = readVectorProperty(layer.layout['symbol-placement']);
839-
style.text.rotation = readVectorProperty(layer.layout['text-rotation-alignment']);
840-
841-
// content
842-
style.text.field = readVectorProperty(layer.layout['text-field']);
843-
style.text.wrap = readVectorProperty(layer.layout['text-max-width']);
844-
style.text.spacing = readVectorProperty(layer.layout['text-letter-spacing']);
845-
style.text.transform = readVectorProperty(layer.layout['text-transform']);
846-
style.text.justify = readVectorProperty(layer.layout['text-justify']);
847-
848-
// appearance
849-
const { color, opacity } = rgba2rgb(readVectorProperty(layer.paint['text-color'], { type: 'color' }));
850-
style.text.color = color;
851-
style.text.opacity = readVectorProperty(layer.paint['text-opacity']) || (opacity !== undefined && opacity);
852-
853-
style.text.font = readVectorProperty(layer.layout['text-font']);
854-
const haloColor = readVectorProperty(layer.paint['text-halo-color'], { type: 'color' });
855-
if (haloColor) {
856-
style.text.haloColor = haloColor.color || haloColor;
857-
style.text.haloWidth = readVectorProperty(layer.paint['text-halo-width']);
858-
style.text.haloBlur = readVectorProperty(layer.paint['text-halo-blur']);
859-
}
860-
861-
// additional icon
862-
const iconImg = readVectorProperty(layer.layout['icon-image']);
863-
if (iconImg) {
864-
try {
865-
style.icon.id = iconImg;
866-
if (iconImg.stops) {
867-
const iconCropValue = {
868-
...(iconImg.base !== undefined && { base: iconImg.base }),
869-
stops: iconImg.stops.map((stop) => {
870-
let cropValues = sprites[stop[1]];
871-
if (stop[1].includes('{')) {
872-
cropValues = function _(p) {
873-
const id = stop[1].replace(/\{(.+?)\}/g, (a, b) => (p[b] || '')).trim();
874-
cropValues = sprites[id];
875-
return sprites[id];
876-
};
877-
}
878-
return [stop[0], cropValues];
879-
}),
880-
};
881-
style.icon.cropValues = iconCropValue;
882-
} else {
883-
style.icon.cropValues = sprites[iconImg];
884-
if (iconImg[0].includes('{')) {
885-
style.icon.cropValues = function _(p) {
886-
const id = iconImg.replace(/\{(.+?)\}/g, (a, b) => (p[b] || '')).trim();
887-
style.icon.cropValues = sprites[id];
888-
return sprites[id];
889-
};
890-
}
891-
}
892-
style.icon.source = sprites.source;
893-
style.icon.size = readVectorProperty(layer.layout['icon-size']) || 1;
894-
const { color, opacity } = rgba2rgb(readVectorProperty(layer.paint['icon-color'], { type: 'color' }));
895-
style.icon.color = color;
896-
style.icon.opacity = readVectorProperty(layer.paint['icon-opacity']) || (opacity !== undefined && opacity);
897-
} catch (err) {
898-
err.message = `VTlayer '${layer.id}': argument sprites must not be null when using layer.layout['icon-image']`;
899-
throw err;
900-
}
901-
}
902-
}
903-
// VectorTileSet: by default minZoom = 0 and maxZoom = 24
904-
// https://docs.mapbox.com/style-spec/reference/layers/#maxzoom and #minzoom
905-
// Should be move to layer properties, when (if) one mapBox layer will be considered as several itowns layers.
906-
// issue https://github.com/iTowns/itowns/issues/2153 (last point)
907-
style.zoom = {
908-
min: layer.minzoom || 0,
909-
max: layer.maxzoom || 24,
910-
};
911-
return style;
912-
}
913-
914668
/**
915669
* Applies the style.fill to a polygon of the texture canvas.
916670
* @param {CanvasRenderingContext2D} txtrCtx The Context 2D of the texture canvas.

0 commit comments

Comments
 (0)