Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 17bbe88

Browse files
committed
refactor(style): change Style.drawingFromContext(ctx) to Style.getFromContext(ctx) for hierarchization of style properties
1 parent 6b44ef9 commit 17bbe88

File tree

5 files changed

+123
-76
lines changed

5 files changed

+123
-76
lines changed

src/Converter/Feature2Mesh.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Extent from 'Core/Geographic/Extent';
77
import Crs from 'Core/Geographic/Crs';
88
import OrientationUtils from 'Utils/OrientationUtils';
99
import Coordinates from 'Core/Geographic/Coordinates';
10-
import { StyleContext } from 'Core/Style';
10+
import Style, { StyleContext } from 'Core/Style';
1111

1212
const coord = new Coordinates('EPSG:4326', 0, 0, 0);
1313
const context = new StyleContext();
@@ -194,6 +194,7 @@ function featureToPoint(feature, options) {
194194

195195
const pointMaterialSize = [];
196196
context.globals = { point: true };
197+
context.setFeature(feature);
197198

198199
for (const geometry of feature.geometries) {
199200
const start = geometry.indices[0].offset;
@@ -208,7 +209,7 @@ function featureToPoint(feature, options) {
208209
}
209210

210211
coord.copy(context.setLocalCoordinatesFromArray(feature.vertices, v));
211-
const style = feature.style.applyContext(context);
212+
const style = Style.applyContext(context);
212213
const { base_altitude, color, radius } = style.point;
213214
coord.z = 0;
214215

@@ -253,6 +254,7 @@ function featureToLine(feature, options) {
253254

254255
const lineMaterialWidth = [];
255256
context.globals = { stroke: true };
257+
context.setFeature(feature);
256258

257259
const countIndices = (count - feature.geometries.length) * 2;
258260
const indices = getIntArrayFromSize(countIndices, count);
@@ -288,7 +290,7 @@ function featureToLine(feature, options) {
288290
}
289291

290292
coord.copy(context.setLocalCoordinatesFromArray(feature.vertices, v));
291-
const style = feature.style.applyContext(context);
293+
const style = Style.applyContext(context);
292294
const { base_altitude, color, width } = style.stroke;
293295
coord.z = 0;
294296

@@ -322,6 +324,7 @@ function featureToPolygon(feature, options) {
322324
const batchIds = new Uint32Array(vertices.length / 3);
323325
const batchId = options.batchId || ((p, id) => id);
324326
context.globals = { fill: true };
327+
context.setFeature(feature);
325328

326329
inverseScale.setFromMatrixScale(context.collection.matrixWorldInverse);
327330
normal.set(0, 0, 1).multiply(inverseScale);
@@ -349,7 +352,7 @@ function featureToPolygon(feature, options) {
349352
}
350353

351354
coord.copy(context.setLocalCoordinatesFromArray(feature.vertices, i));
352-
const style = feature.style.applyContext(context);
355+
const style = Style.applyContext(context);
353356
const { base_altitude, color } = style.fill;
354357
coord.z = 0;
355358

@@ -410,6 +413,7 @@ function featureToExtrudedPolygon(feature, options) {
410413
let featureId = 0;
411414

412415
context.globals = { fill: true };
416+
context.setFeature(feature);
413417
inverseScale.setFromMatrixScale(context.collection.matrixWorldInverse);
414418
normal.set(0, 0, 1).multiply(inverseScale);
415419
coord.setCrs(context.collection.crs);
@@ -435,7 +439,7 @@ function featureToExtrudedPolygon(feature, options) {
435439

436440
coord.copy(context.setLocalCoordinatesFromArray(ptsIn, i));
437441

438-
const style = feature.style.applyContext(context);
442+
const style = Style.applyContext(context);
439443
const { base_altitude, extrusion_height, color } = style.fill;
440444
coord.z = 0;
441445

@@ -653,6 +657,7 @@ export default {
653657
// as in examples/source_file_gpx_3d.html.
654658
options.layer = this || { style: options.style };
655659
}
660+
context.layerStyle = options.layer.style;
656661

657662
context.setCollection(collection);
658663

src/Converter/Feature2Texture.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ function drawPolygon(ctx, vertices, indices = [{ offset: 0, count: 1 }], style =
2525
if (vertices.length === 0) {
2626
return;
2727
}
28-
2928
if (style.length) {
3029
for (const s of style) {
3130
_drawPolygon(ctx, vertices, indices, s, size, extent, invCtxScale, canBeFilled);
@@ -73,19 +72,21 @@ function drawPoint(ctx, x, y, style = {}, invCtxScale) {
7372

7473
const coord = new Coordinates('EPSG:4326', 0, 0, 0);
7574

76-
function drawFeature(ctx, feature, extent, style, invCtxScale) {
75+
function drawFeature(ctx, feature, extent, invCtxScale) {
7776
const extentDim = extent.planarDimensions();
7877
const scaleRadius = extentDim.x / ctx.canvas.width;
7978

79+
context.setFeature(feature);
80+
8081
for (const geometry of feature.geometries) {
8182
if (Extent.intersectsExtent(geometry.extent, extent)) {
8283
context.setGeometry(geometry);
83-
const contextStyle = (geometry.properties.style || style).applyContext(context);
84+
85+
const contextStyle = Style.applyContext(context);
8486

8587
if (contextStyle) {
8688
if (
87-
feature.type === FEATURE_TYPES.POINT
88-
&& contextStyle.point
89+
feature.type === FEATURE_TYPES.POINT && contextStyle.point
8990
) {
9091
// cross multiplication to know in the extent system the real size of
9192
// the point
@@ -121,8 +122,9 @@ const featureExtent = new Extent('EPSG:4326', 0, 0, 0, 0);
121122
export default {
122123
// backgroundColor is a THREE.Color to specify a color to fill the texture
123124
// with, given there is no feature passed in parameter
124-
createTextureFromFeature(collection, extent, sizeTexture, style = {}, backgroundColor) {
125+
createTextureFromFeature(collection, extent, sizeTexture, layerStyle = {}, backgroundColor) {
125126
let texture;
127+
context.layerStyle = layerStyle;
126128

127129
if (collection) {
128130
// A texture is instancied drawn canvas
@@ -139,7 +141,9 @@ export default {
139141
ctx.fillStyle = backgroundColor.getStyle();
140142
ctx.fillRect(0, 0, sizeTexture, sizeTexture);
141143
}
142-
ctx.globalCompositeOperation = style.globalCompositeOperation || 'source-over';
144+
145+
// Documentation needed !!
146+
ctx.globalCompositeOperation = layerStyle.globalCompositeOperation || 'source-over';
143147
ctx.imageSmoothingEnabled = false;
144148
ctx.lineJoin = 'round';
145149

@@ -177,7 +181,7 @@ export default {
177181

178182
// Draw the canvas
179183
for (const feature of collection.features) {
180-
drawFeature(ctx, feature, featureExtent, feature.style || style, invCtxScale);
184+
drawFeature(ctx, feature, featureExtent, invCtxScale);
181185
}
182186

183187
texture = new THREE.CanvasTexture(c);

src/Core/Style.js

Lines changed: 69 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ function defineStyleProperty(style, category, name, value, defaultValue) {
166166
* @property {Object} collection The FeatureCollection to which the FeatureGeometry is attached.
167167
* @property {Object} properties Properties of the FeatureGeometry.
168168
* @property {string} type Geometry type of the feature. Can be `point`, `line`, or `polygon`.
169+
* @property {Style} style Style of the FeatureGeometry computed from Layer.style and user.style.
169170
* @property {Coordinates} coordinates The coordinates (in world space) of the last vertex (x, y, z) set with
170171
* setLocalCoordinatesFromArray().
171172
* private properties:
@@ -215,6 +216,38 @@ export class StyleContext {
215216
return this.#feature.type;
216217
}
217218

219+
get style() {
220+
const layerStyle = this.layerStyle || {};
221+
let featureStyle = this.#feature.style;
222+
if (featureStyle instanceof Function) {
223+
featureStyle = readExpression(featureStyle, this);
224+
}
225+
const style = {
226+
fill: {
227+
...featureStyle.fill,
228+
...layerStyle.fill,
229+
},
230+
stroke: {
231+
...featureStyle.stroke,
232+
...layerStyle.stroke,
233+
},
234+
point: {
235+
...featureStyle.point,
236+
...layerStyle.point,
237+
},
238+
icon: {
239+
...featureStyle.icon,
240+
...layerStyle.icon,
241+
},
242+
text: {
243+
...featureStyle.text,
244+
...layerStyle.text,
245+
},
246+
order: layerStyle.order || featureStyle.order,
247+
};
248+
return style;
249+
}
250+
218251
get coordinates() {
219252
if (!this.#worldCoordsComputed) {
220253
this.#worldCoordsComputed = true;
@@ -645,10 +678,10 @@ class Style {
645678
}
646679

647680
/**
648-
* Clones this style.
649-
*
650-
* @return {Style} The new style, cloned from this one.
651-
*/
681+
* Clones this style.
682+
*
683+
* @return {Style} The new style, cloned from this one.
684+
*/
652685
clone() {
653686
const clone = new Style();
654687
return clone.copy(this);
@@ -662,27 +695,47 @@ class Style {
662695
*
663696
* @return {Style} mapped style depending on context.
664697
*/
665-
applyContext(context) {
698+
static applyContext(context) {
699+
const styleConc = new Style(context.style);
666700
const style = {};
667-
if (this.fill.color || this.fill.pattern || context.globals.fill) {
668-
mapPropertiesFromContext('fill', this, style, context);
701+
if (styleConc.fill.color || styleConc.fill.pattern || context.globals.fill) {
702+
mapPropertiesFromContext('fill', styleConc, style, context);
669703
}
670-
if (this.stroke.color || context.globals.stroke) {
671-
mapPropertiesFromContext('stroke', this, style, context);
704+
if (styleConc.stroke.color || context.globals.stroke) {
705+
mapPropertiesFromContext('stroke', styleConc, style, context);
672706
}
673-
if (this.point.color || this.point.model || context.globals.point) {
674-
mapPropertiesFromContext('point', this, style, context);
707+
if (styleConc.point.color || styleConc.point.model || context.globals.point) {
708+
mapPropertiesFromContext('point', styleConc, style, context);
675709
}
676-
if (this.text || context.globals.text) {
677-
mapPropertiesFromContext('text', this, style, context);
710+
711+
if (styleConc.text || context.globals.text) {
712+
mapPropertiesFromContext('text', styleConc, style, context);
678713
}
679-
if (this.icon || context.globals.icon) {
680-
mapPropertiesFromContext('icon', this, style, context);
714+
if (styleConc.icon || context.globals.icon) {
715+
mapPropertiesFromContext('icon', styleConc, style, context);
681716
}
682-
style.order = this.order;
717+
style.order = styleConc.order;
683718
return new Style(style);
684719
}
685720

721+
/**
722+
* Returns a string, associating `style.text.field` and properties to use to
723+
* replace the keys in `style.text.field`.
724+
*
725+
* @param {FeatureContext} context The context linked to the feature
726+
*
727+
* @return {string|undefined} The formatted string if `style.text.field` is defined, nothing otherwise.
728+
*/
729+
getTextFromProperties(context) {
730+
if (!this.text.field) { return; }
731+
732+
if (this.text.field.expression) {
733+
return readExpression(this.text.field, context);
734+
} else {
735+
return this.text.field.replace(/\{(.+?)\}/g, (a, b) => (context.properties()[b] || '')).trim();
736+
}
737+
}
738+
686739
/**
687740
* set Style from (geojson-like) properties.
688741
* @param {Object} properties (geojson-like) properties.
@@ -1055,24 +1108,6 @@ class Style {
10551108
return this.text.anchor;
10561109
}
10571110
}
1058-
1059-
/**
1060-
* Returns a string, associating `style.text.field` and properties to use to
1061-
* replace the keys in `style.text.field`.
1062-
*
1063-
* @param {Object} ctx - An object containing the feature context.
1064-
*
1065-
* @return {String|undefined} The formatted string if `style.text.field` is defined, nothing otherwise.
1066-
*/
1067-
getTextFromProperties(ctx) {
1068-
if (!this.text.field) { return; }
1069-
1070-
if (this.text.field.expression) {
1071-
return readExpression(this.text.field, ctx);
1072-
} else {
1073-
return this.text.field.replace(/\{(.+?)\}/g, (a, b) => (ctx.properties[b] || '')).trim();
1074-
}
1075-
}
10761111
}
10771112

10781113
// Add custom style sheet with iTowns specifics

src/Layer/LabelLayer.js

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Coordinates from 'Core/Geographic/Coordinates';
66
import Extent from 'Core/Geographic/Extent';
77
import Label from 'Core/Label';
88
import { FEATURE_TYPES } from 'Core/Feature';
9-
import { readExpression, StyleContext } from 'Core/Style';
9+
import Style, { readExpression, StyleContext } from 'Core/Style';
1010
import { ScreenGrid } from 'Renderer/Label2DRenderer';
1111

1212
const context = new StyleContext();
@@ -249,17 +249,19 @@ class LabelLayer extends GeometryLayer {
249249
text: true,
250250
zoom: extent.zoom,
251251
};
252+
context.layerStyle = this.style;
252253

253254
data.features.forEach((f) => {
254255
// TODO: add support for LINE and POLYGON
255256
if (f.type !== FEATURE_TYPES.POINT) {
256257
return;
257258
}
259+
context.setFeature(f);
258260

259-
const featureField = f.style.text.field;
261+
const featureField = f.style?.text?.field;
260262

261263
// determine if altitude style is specified by the user
262-
const altitudeStyle = f.style.point.base_altitude;
264+
const altitudeStyle = f.style?.point?.base_altitude;
263265
const isDefaultElevationStyle = altitudeStyle instanceof Function && altitudeStyle.name == 'baseAltitudeDefault';
264266

265267
// determine if the altitude needs update with ElevationLayer
@@ -273,31 +275,31 @@ class LabelLayer extends GeometryLayer {
273275
coord.applyMatrix4(data.matrixWorld);
274276

275277
if (!_extent.isPointInside(coord)) { return; }
276-
277-
const geometryField = g.properties.style && g.properties.style.text.field;
278+
const geometryField = g.properties.style && g.properties.style.text && g.properties.style.text.field;
278279

279280
context.setGeometry(g);
280281
let content;
281282
if (this.labelDomelement) {
282283
content = readExpression(this.labelDomelement, context);
283284
} else if (!geometryField && !featureField && !layerField) {
284285
// Check if there is an icon, with no text
285-
if (!(g.properties.style && (g.properties.style.icon.source || g.properties.style.icon.id))
286-
&& !(f.style && (f.style.icon.source || f.style.icon.id))
287-
&& !(this.style && (this.style.icon.source || this.style.icon.id))) {
286+
if (!(g.properties.style && (g.properties.style.icon.source || g.properties.style.icon.key))
287+
&& !(f.style && f.style.icon && (f.style.icon.source || f.style.icon.key))
288+
&& !(this.style && this.style.icon && (this.style.icon.source || this.style.icon.key))) {
288289
return;
289290
}
290291
} else if (geometryField) {
291-
content = g.properties.style.getTextFromProperties(context);
292+
content = new Style(g.properties.style).getTextFromProperties(context);
292293
} else if (featureField) {
293-
content = f.style.getTextFromProperties(context);
294+
content = new Style(f.style).getTextFromProperties(context);
294295
} else if (layerField) {
295-
content = this.style.getTextFromProperties(context);
296+
content = new Style(this.style).getTextFromProperties(context);
296297
}
297298

298-
const style = (g.properties.style || f.style || this.style).applyContext(context);
299+
const style = Style.applyContext(context);
299300

300301
const label = new Label(content, coord.clone(), style);
302+
301303
label.layerId = this.id;
302304
label.padding = this.margin || label.padding;
303305

0 commit comments

Comments
 (0)