From d362fc210c4cbae85b4d8f5114143b709f35c222 Mon Sep 17 00:00:00 2001 From: Igor D Date: Fri, 16 Jun 2023 00:29:56 +0300 Subject: [PATCH] [feat] H3 Layer separate layer opacity into unique fill opacity and stroke opacity (#2261) --- .../layer-panel/layer-configurator.tsx | 25 +++--- .../src/column-layer/enhanced-column-layer.ts | 81 ++++++++++++++++++- .../src/h3-hexagon-layer/h3-hexagon-layer.ts | 21 ++++- src/localization/src/translations/en.ts | 1 + test/fixtures/test-hex-id-data.js | 1 + 5 files changed, 110 insertions(+), 19 deletions(-) diff --git a/src/components/src/side-panel/layer-panel/layer-configurator.tsx b/src/components/src/side-panel/layer-panel/layer-configurator.tsx index 6969d10b69..e920632fa9 100644 --- a/src/components/src/side-panel/layer-panel/layer-configurator.tsx +++ b/src/components/src/side-panel/layer-panel/layer-configurator.tsx @@ -490,12 +490,12 @@ export default function LayerConfiguratorFactory( }) { return ( - {/* Fill Color */} + {/* Fill */} {layer.config.colorField ? ( @@ -507,10 +507,15 @@ export default function LayerConfiguratorFactory( channel={layer.visualChannels.color} {...layerChannelConfigProps} /> + - {/* Outline Color */} + {/* Outline */} )} + - {/* Opacity */} - - - - {/* Coverage */} {!layer.config.coverageField ? ( diff --git a/src/deckgl-layers/src/column-layer/enhanced-column-layer.ts b/src/deckgl-layers/src/column-layer/enhanced-column-layer.ts index 4a58804931..20b5cc1ec6 100644 --- a/src/deckgl-layers/src/column-layer/enhanced-column-layer.ts +++ b/src/deckgl-layers/src/column-layer/enhanced-column-layer.ts @@ -18,7 +18,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import {ColumnLayer} from '@deck.gl/layers'; +import {UNIT} from '@deck.gl/core'; +import {ColumnLayer, ColumnLayerProps} from '@deck.gl/layers/typed'; +import GL from '@luma.gl/constants'; + import {editShader} from '../'; function addInstanceCoverage(vs) { @@ -38,8 +41,12 @@ function addInstanceCoverage(vs) { ); } +type EnhancedColumnLayerProps = ColumnLayerProps & { + strokeOpacity: any; +}; + // TODO: export all deck.gl layers from kepler.gl -class EnhancedColumnLayer extends ColumnLayer { +class EnhancedColumnLayer extends ColumnLayer { getShaders() { const shaders = super.getShaders(); @@ -50,12 +57,78 @@ class EnhancedColumnLayer extends ColumnLayer { } initializeState() { - super.initializeState(undefined); + super.initializeState(); - this.getAttributeManager().addInstanced({ + this.getAttributeManager()?.addInstanced({ instanceCoverage: {size: 1, accessor: 'getCoverage'} }); } + + draw({uniforms}) { + const { + lineWidthUnits, + lineWidthScale, + lineWidthMinPixels, + lineWidthMaxPixels, + radiusUnits, + elevationScale, + extruded, + filled, + stroked, + strokeOpacity, + wireframe, + offset, + coverage, + radius, + angle + } = this.props; + const {model, fillVertexCount, wireframeVertexCount, edgeDistance} = this.state; + + model.setUniforms(uniforms).setUniforms({ + radius, + angle: (angle / 180) * Math.PI, + offset, + extruded, + stroked, + coverage, + elevationScale, + edgeDistance, + radiusUnits: UNIT[radiusUnits], + widthUnits: UNIT[lineWidthUnits], + widthScale: lineWidthScale, + widthMinPixels: lineWidthMinPixels, + widthMaxPixels: lineWidthMaxPixels + }); + + // When drawing 3d: draw wireframe first so it doesn't get occluded by depth test + if (extruded && wireframe) { + model.setProps({isIndexed: true}); + model + .setVertexCount(wireframeVertexCount) + .setDrawMode(GL.LINES) + .setUniforms({isStroke: true}) + .draw(); + } + if (filled) { + model.setProps({isIndexed: false}); + model + .setVertexCount(fillVertexCount) + .setDrawMode(GL.TRIANGLE_STRIP) + .setUniforms({isStroke: false}) + .draw(); + } + // When drawing 2d: draw fill before stroke so that the outline is always on top + if (!extruded && stroked) { + model.setProps({isIndexed: false}); + // The width of the stroke is achieved by flattening the side of the cylinder. + // Skip the last 1/3 of the vertices which is the top. + model + .setVertexCount((fillVertexCount * 2) / 3) + .setDrawMode(GL.TRIANGLE_STRIP) + .setUniforms({isStroke: true, opacity: strokeOpacity}) + .draw(); + } + } } EnhancedColumnLayer.layerName = 'EnhancedColumnLayer'; diff --git a/src/layers/src/h3-hexagon-layer/h3-hexagon-layer.ts b/src/layers/src/h3-hexagon-layer/h3-hexagon-layer.ts index 293aa475a8..e424006226 100644 --- a/src/layers/src/h3-hexagon-layer/h3-hexagon-layer.ts +++ b/src/layers/src/h3-hexagon-layer/h3-hexagon-layer.ts @@ -67,6 +67,7 @@ export type HexagonIdLayerColumnsConfig = { export type HexagonIdLayerVisConfigSettings = { opacity: VisConfigNumber; + strokeOpacity: VisConfigNumber; colorRange: VisConfigColorRange; coverage: VisConfigNumber; enable3d: VisConfigBoolean; @@ -81,6 +82,7 @@ export type HexagonIdLayerVisConfigSettings = { export type HexagonIdLayerVisConfig = { opacity: number; + strokeOpacity: number; colorRange: ColorRange; coverage: number; enable3d: boolean; @@ -115,7 +117,8 @@ export const defaultElevation = 500; export const defaultCoverage = 1; export const HexagonIdVisConfigs: { - opacity: 'opacity'; + opacity: VisConfigNumber; + strokeOpacity: VisConfigNumber; colorRange: 'colorRange'; filled: VisConfigBoolean; outline: 'outline'; @@ -129,15 +132,26 @@ export const HexagonIdVisConfigs: { elevationScale: 'elevationScale'; enableElevationZoomFactor: 'enableElevationZoomFactor'; } = { - opacity: 'opacity', colorRange: 'colorRange', filled: { ...LAYER_VIS_CONFIGS.filled, defaultValue: true }, + opacity: { + ...LAYER_VIS_CONFIGS.opacity, + label: 'Fill Opacity', + range: [0, 1], + property: 'opacity' + }, outline: 'outline', strokeColor: 'strokeColor', strokeColorRange: 'strokeColorRange', + strokeOpacity: { + ...LAYER_VIS_CONFIGS.opacity, + label: 'Stroke Opacity', + range: [0, 1], + property: 'strokeOpacity' + }, thickness: 'thickness', coverage: 'coverage', enable3d: 'enable3d', @@ -432,7 +446,8 @@ export default class HexagonIdLayer extends Layer { 'hexagon-cell': { type: EnhancedColumnLayer, getCoverage: data.getCoverage, - updateTriggers: columnLayerTriggers + updateTriggers: columnLayerTriggers, + strokeOpacity: visConfig.strokeOpacity } } }), diff --git a/src/localization/src/translations/en.ts b/src/localization/src/translations/en.ts index fa3ccf49f3..6debc86142 100644 --- a/src/localization/src/translations/en.ts +++ b/src/localization/src/translations/en.ts @@ -464,6 +464,7 @@ export default { colorScale: 'Color Scale', sizeScale: 'Size Scale', strokeScale: 'Stroke Scale', + strokeColorScale: 'Stroke Color Scale', scale: 'Scale' }, fileUploader: { diff --git a/test/fixtures/test-hex-id-data.js b/test/fixtures/test-hex-id-data.js index f06ef5afcb..5d0ae0b25b 100644 --- a/test/fixtures/test-hex-id-data.js +++ b/test/fixtures/test-hex-id-data.js @@ -395,6 +395,7 @@ mergedH3Layer.config = { category: 'Uber', colors: ['#5A1846', '#900C3F', '#C70039', '#E3611C', '#F1920E', '#FFC300'] }, + strokeOpacity: 0.8, thickness: 2, coverage: 1, sizeRange: [0, 500],