From d3778cf7f5e73c14c21ef424f85e2c7ab0d961ed Mon Sep 17 00:00:00 2001 From: "Juan D. Jara" Date: Thu, 23 Jan 2025 13:05:03 +0100 Subject: [PATCH 1/6] WIP tileset example --- packages/create-react/package.json | 2 +- .../src/components/views/IncomeView.tsx | 194 +++++++++++++++ packages/create-react/src/routes.tsx | 4 + yarn.lock | 222 +++++++++++++++++- 4 files changed, 418 insertions(+), 4 deletions(-) create mode 100644 packages/create-react/src/components/views/IncomeView.tsx diff --git a/packages/create-react/package.json b/packages/create-react/package.json index 849237a..c0a500a 100644 --- a/packages/create-react/package.json +++ b/packages/create-react/package.json @@ -16,7 +16,7 @@ }, "dependencies": { "@auth0/auth0-react": "^2.2.4", - "@carto/api-client": "^0.4.5", + "@carto/api-client": "0.5.0-alpha.1", "@carto/create-common": "^0.1.3", "@deck.gl/aggregation-layers": "^9.0.40", "@deck.gl/carto": "^9.0.40", diff --git a/packages/create-react/src/components/views/IncomeView.tsx b/packages/create-react/src/components/views/IncomeView.tsx new file mode 100644 index 0000000..ebac334 --- /dev/null +++ b/packages/create-react/src/components/views/IncomeView.tsx @@ -0,0 +1,194 @@ +import { Color, MapView, MapViewState, WebMercatorViewport } from "@deck.gl/core"; +import { useContext, useEffect, useMemo, useState } from "react"; +import { AppContext } from "../../context"; +import { useDebouncedState } from "../../hooks/useDebouncedState"; +import { createViewportSpatialFilter, vectorTilesetSource } from "@carto/api-client"; +import { VectorTileLayer } from "@deck.gl/carto"; +import { Card } from "../Card"; +import { FormulaWidget } from "../widgets/FormulaWidget"; +import DeckGL from "@deck.gl/react"; +import { Map } from 'react-map-gl/maplibre'; +import { Layers } from "../Layers"; +import { LegendEntryCategorical } from "../legends/LegendEntryCategorical"; + +const MAP_VIEW = new MapView({ repeat: true }); +const MAP_STYLE = + 'https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json'; + +const INITIAL_VIEW_STATE: MapViewState = { + latitude: 31.8028, + longitude: -103.0078, + zoom: 2, +}; + +const histogramTicks = [15000, 20000, 23000, 26000, 30000, 34000, 40000, 50000]; + +const colors = [ + '#f7fcf0', + '#e0f3db', + '#ccebc5', + '#a8ddb5', + '#7bccc4', + '#4eb3d3', + '#2b8cbe', + '#08589e', +].map((hex) => hexToRgb(hex)); + +function hexToRgb(hex: string) { + const r = parseInt(hex.slice(1, 3), 16); + const g = parseInt(hex.slice(3, 5), 16); + const b = parseInt(hex.slice(5, 7), 16); + return [r, g, b]; +} + +/** + * Example application page, showing U.S. income by block group. + */ +export default function IncomeView() { + // With authentication enabled, access token may change. + const { accessToken, apiBaseUrl } = useContext(AppContext); + const [attributionHTML, setAttributionHTML] = useState(''); + // Debounce view state to avoid excessive re-renders during pan and zoom. + const [viewState, setViewState] = useDebouncedState(INITIAL_VIEW_STATE, 200); + + /**************************************************************************** + * Sources (https://deck.gl/docs/api-reference/carto/data-sources) + */ + + const data = useMemo( + () => + vectorTilesetSource({ + accessToken, + apiBaseUrl, + connectionName: 'carto_dw', + tableName: 'carto-demo-data.demo_tilesets.sociodemographics_usa_blockgroup', + }), + [accessToken, apiBaseUrl], + ); + + /**************************************************************************** + * Layers (https://deck.gl/docs/api-reference/carto/overview#carto-layers) + */ + + const LAYER_ID = 'Income by block group' + + // Layer visibility represented as name/visibility pairs, managed by the Layers component. + const [layerVisibility, setLayerVisibility] = useState< + Record + >({ + [LAYER_ID]: true, + }); + + // Update layers when data or visualization parameters change. + const layers = useMemo(() => { + return [ + new VectorTileLayer({ + id: LAYER_ID, + pickable: true, + visible: layerVisibility[LAYER_ID], + data, + getLineColor: [0, 0 ,0], + lineWidthMinPixels: 0.3, + getFillColor: d => { + const n = d.properties.income_per_capita; + const index = histogramTicks.slice().reverse().findIndex((tick) => n >= tick); + const color = colors[index] || colors[colors.length - 1]; + return color as Color; + }, + onViewportLoad(tiles) { + data?.then((res) => { + res.widgetSource.loadTiles(tiles) + const bbox = new WebMercatorViewport(viewState).getBounds() + const spatialFilter = createViewportSpatialFilter(bbox) + if (spatialFilter) { + res.widgetSource.extractTileFeatures({ spatialFilter }) + } + }) + }, + }), + ]; + }, [data, layerVisibility]); + + /**************************************************************************** + * Attribution + */ + + useEffect(() => { + data?.then(({ attribution }) => setAttributionHTML(attribution)); + }, [data]); + + useEffect(() => { + if (data && viewState) { + data?.then((res) => { + const bbox = new WebMercatorViewport(viewState).getBounds() + const spatialFilter = createViewportSpatialFilter(bbox) + if (spatialFilter) { + res.widgetSource.extractTileFeatures({ spatialFilter }) + } + }) + } + }, [data, viewState]) + + return ( + <> + +
+ setViewState(viewState)} + > + + + + + + colors[histogramTicks.indexOf(Number(value))] as Color + } + /> + + +
+ + ) +} diff --git a/packages/create-react/src/routes.tsx b/packages/create-react/src/routes.tsx index 4e54c7f..a0a4cc3 100644 --- a/packages/create-react/src/routes.tsx +++ b/packages/create-react/src/routes.tsx @@ -6,6 +6,7 @@ import PopulationView from './components/views/PopulationView'; import NotFoundView from './components/views/NotFoundView'; import LoginView from './components/views/LoginView'; import LogoutView from './components/views/LogoutView'; +import IncomeView from './components/views/IncomeView'; /** * Available paths (URLs) in the application. @@ -13,6 +14,7 @@ import LogoutView from './components/views/LogoutView'; export const RoutePath = { CELL_TOWERS: '/', POPULATION: '/usa-population', + INCOME: '/income', LOGIN: '/login', LOGOUT: '/logout', NOT_FOUND: '/404', @@ -24,6 +26,7 @@ export const RoutePath = { export const NAV_ROUTES: { text: string; path: string }[] = [ { text: 'Cell towers', path: RoutePath.CELL_TOWERS }, { text: 'U.S. population', path: RoutePath.POPULATION }, + { text: 'Income', path: RoutePath.INCOME }, ]; /** @@ -40,6 +43,7 @@ export const routes: RouteObject[] = [ children: [ { path: RoutePath.CELL_TOWERS, element: }, { path: RoutePath.POPULATION, element: }, + { path: RoutePath.INCOME, element: }, ], }, { path: RoutePath.LOGIN, element: }, diff --git a/yarn.lock b/yarn.lock index d3535a8..71d0b74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2586,6 +2586,25 @@ __metadata: languageName: node linkType: hard +"@carto/api-client@npm:0.5.0-alpha.1": + version: 0.5.0-alpha.1 + resolution: "@carto/api-client@npm:0.5.0-alpha.1" + dependencies: + "@loaders.gl/schema": "npm:^4.3.3" + "@turf/bbox-clip": "npm:^7.1.0" + "@turf/bbox-polygon": "npm:^7.1.0" + "@turf/boolean-intersects": "npm:^7.1.0" + "@turf/boolean-within": "npm:^7.1.0" + "@turf/helpers": "npm:^7.1.0" + "@turf/intersect": "npm:^7.1.0" + "@turf/invariant": "npm:^7.1.0" + "@turf/union": "npm:^7.1.0" + "@types/geojson": "npm:^7946.0.15" + h3-js: "npm:4.1.0" + checksum: 10c0/8b8cfbfe5d3a73bdfb2491a792d5e007e1605473dd4f824c3a7d56f0ec811ca1e9fbeeb35c799b72136ad5b76643004ac2c2c683ece5d22d285948d93de2e6df + languageName: node + linkType: hard + "@carto/api-client@npm:^0.4.5": version: 0.4.5 resolution: "@carto/api-client@npm:0.4.5" @@ -2658,7 +2677,7 @@ __metadata: resolution: "@carto/create-react@workspace:packages/create-react" dependencies: "@auth0/auth0-react": "npm:^2.2.4" - "@carto/api-client": "npm:^0.4.5" + "@carto/api-client": "npm:0.5.0-alpha.1" "@carto/create-common": "npm:^0.1.3" "@deck.gl/aggregation-layers": "npm:^9.0.40" "@deck.gl/carto": "npm:^9.0.40" @@ -4017,7 +4036,7 @@ __metadata: languageName: node linkType: hard -"@loaders.gl/schema@npm:4.3.3": +"@loaders.gl/schema@npm:4.3.3, @loaders.gl/schema@npm:^4.3.3": version: 4.3.3 resolution: "@loaders.gl/schema@npm:4.3.3" dependencies: @@ -5295,6 +5314,18 @@ __metadata: languageName: node linkType: hard +"@turf/bbox@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/bbox@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@turf/meta": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/766d59d5f75c272481e971cd4004e139962607e8f34391b2abfb15bb34f9544a0479ceb14772565e005e4a12fdd82adf0d440ab1c9e0decbde6de50a5706db43 + languageName: node + linkType: hard + "@turf/boolean-clockwise@npm:^5.1.5": version: 5.1.5 resolution: "@turf/boolean-clockwise@npm:5.1.5" @@ -5305,6 +5336,74 @@ __metadata: languageName: node linkType: hard +"@turf/boolean-disjoint@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/boolean-disjoint@npm:7.2.0" + dependencies: + "@turf/boolean-point-in-polygon": "npm:^7.2.0" + "@turf/helpers": "npm:^7.2.0" + "@turf/line-intersect": "npm:^7.2.0" + "@turf/meta": "npm:^7.2.0" + "@turf/polygon-to-line": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/f9e27f3b46fdddd5e96e67e7f130e25678922c843afd5d898a1c13b599285b126a8ab9df5bd5e76454e88deacc359ebc1fa47d50cbd21f64c0547201d0fb9118 + languageName: node + linkType: hard + +"@turf/boolean-intersects@npm:^7.1.0": + version: 7.2.0 + resolution: "@turf/boolean-intersects@npm:7.2.0" + dependencies: + "@turf/boolean-disjoint": "npm:^7.2.0" + "@turf/helpers": "npm:^7.2.0" + "@turf/meta": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/2b4ef09eb77fa02db9671e5c4d0c0c4133a815bbd9a744e70e65a3b37a8b6a13c26d51dc77de0822f39ed2b882646f416fa07561888d4813bb4d31b7003fcba5 + languageName: node + linkType: hard + +"@turf/boolean-point-in-polygon@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/boolean-point-in-polygon@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@turf/invariant": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + point-in-polygon-hao: "npm:^1.1.0" + tslib: "npm:^2.8.1" + checksum: 10c0/eeb431f70175e466205b27076dbc331b862d3e6867d43730ac4099ecd7e6d6f0fed9e3301fd29f6375f340e379f477489f09060e6aec9fc0f7afa01ac58d5c09 + languageName: node + linkType: hard + +"@turf/boolean-point-on-line@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/boolean-point-on-line@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@turf/invariant": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/a7f81170ff795025f209602559a289330304adf046340133e1b18f950aca386e8f2d4f1f91b85c2456306d95359fdd19b8323c13f88327491dbf2f196fa1e635 + languageName: node + linkType: hard + +"@turf/boolean-within@npm:^7.1.0": + version: 7.2.0 + resolution: "@turf/boolean-within@npm:7.2.0" + dependencies: + "@turf/bbox": "npm:^7.2.0" + "@turf/boolean-point-in-polygon": "npm:^7.2.0" + "@turf/boolean-point-on-line": "npm:^7.2.0" + "@turf/helpers": "npm:^7.2.0" + "@turf/invariant": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/2aed21d55b820a19d1d7f22f521fdd9c780ba8ab036828ac2a316efea984d3c70c71190aeaa5766fce922b5dcd52987d86dc0fcb27a0d50306a9e7e270cf80ce + languageName: node + linkType: hard + "@turf/clone@npm:^5.1.5": version: 5.1.5 resolution: "@turf/clone@npm:5.1.5" @@ -5331,6 +5430,29 @@ __metadata: languageName: node linkType: hard +"@turf/helpers@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/helpers@npm:7.2.0" + dependencies: + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/4d6f57164cca00ec7a18e2d3c0200d0274e4ab2b6b3201c6a867b867d899f3f618a82ae242617d467efb04f32740cec150ae06a0e07ee39318397ebc34914687 + languageName: node + linkType: hard + +"@turf/intersect@npm:^7.1.0": + version: 7.2.0 + resolution: "@turf/intersect@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@turf/meta": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + polyclip-ts: "npm:^0.16.8" + tslib: "npm:^2.8.1" + checksum: 10c0/16c39a87819c0173572e1030e29eca1c522115f9aa2c07a3baa00b6b28626573e6e54b428cd919d055f80e49ab1dd90c17166f5e8ba46eb3da738d1a8c8bbd71 + languageName: node + linkType: hard + "@turf/invariant@npm:^5.1.5": version: 5.2.0 resolution: "@turf/invariant@npm:5.2.0" @@ -5351,6 +5473,29 @@ __metadata: languageName: node linkType: hard +"@turf/invariant@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/invariant@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/6968b766d5522488bb2b149a72f863e3f0d4bb0342b14f3992e3e920d9e32c252e1e07e84213732cb51609aef7a82833a8fe76b1c7d0db4cd384954cfedaa4e5 + languageName: node + linkType: hard + +"@turf/line-intersect@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/line-intersect@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + sweepline-intersections: "npm:^1.5.0" + tslib: "npm:^2.8.1" + checksum: 10c0/d2ed0159ce84e179f999ed461c5481f063c813bedfdfb4af45e46432503b0acd240128be5c6c2d324e05edc4981fd806a41ee0282567c5d0c80c223497e40cb4 + languageName: node + linkType: hard + "@turf/meta@npm:^5.1.5": version: 5.2.0 resolution: "@turf/meta@npm:5.2.0" @@ -5370,6 +5515,28 @@ __metadata: languageName: node linkType: hard +"@turf/meta@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/meta@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + checksum: 10c0/707ed63ba64fe48769806bf2419f5c0cd2ebf821a6467aeffb784ba7ebd6a63ec98d4192b97915948529c00304ed46ddc83842a80714fb1f2018fd4e3c455498 + languageName: node + linkType: hard + +"@turf/polygon-to-line@npm:^7.2.0": + version: 7.2.0 + resolution: "@turf/polygon-to-line@npm:7.2.0" + dependencies: + "@turf/helpers": "npm:^7.2.0" + "@turf/invariant": "npm:^7.2.0" + "@types/geojson": "npm:^7946.0.10" + tslib: "npm:^2.8.1" + checksum: 10c0/b840b218e631a252655d233b2c569607d4d3e8d3715a1eab7d26394e4acc1f325b736837d2a82e5c4f678600b2ddc32004782ed3825ca5b1027dce12a4e4cde9 + languageName: node + linkType: hard + "@turf/rewind@npm:^5.1.5": version: 5.1.5 resolution: "@turf/rewind@npm:5.1.5" @@ -7149,6 +7316,13 @@ __metadata: languageName: node linkType: hard +"bignumber.js@npm:^9.1.0": + version: 9.1.2 + resolution: "bignumber.js@npm:9.1.2" + checksum: 10c0/e17786545433f3110b868725c449fa9625366a6e675cd70eb39b60938d6adbd0158cb4b3ad4f306ce817165d37e63f4aa3098ba4110db1d9a3b9f66abfbaf10d + languageName: node + linkType: hard + "bin-links@npm:^4.0.4": version: 4.0.4 resolution: "bin-links@npm:4.0.4" @@ -10428,7 +10602,7 @@ __metadata: languageName: node linkType: hard -"h3-js@npm:^4.1.0": +"h3-js@npm:4.1.0, h3-js@npm:^4.1.0": version: 4.1.0 resolution: "h3-js@npm:4.1.0" checksum: 10c0/58adb7c7a19ff6e6959ef97a60b383bb06c560ffd12826ce603470b25bb34bb26b9bedee6e406591b97017fb888a6194b4043d16abd0d100e6cb51d449e9c3d1 @@ -14152,6 +14326,25 @@ __metadata: languageName: node linkType: hard +"point-in-polygon-hao@npm:^1.1.0": + version: 1.2.4 + resolution: "point-in-polygon-hao@npm:1.2.4" + dependencies: + robust-predicates: "npm:^3.0.2" + checksum: 10c0/12badef8b15216acdae7d609a8aca1b916d6a9cac2f53ace2928e3b521bee57224489ea8fba41d001c0c05c50e64152c175e3d6583d8cad6fe7af929f082b49a + languageName: node + linkType: hard + +"polyclip-ts@npm:^0.16.8": + version: 0.16.8 + resolution: "polyclip-ts@npm:0.16.8" + dependencies: + bignumber.js: "npm:^9.1.0" + splaytree-ts: "npm:^1.0.2" + checksum: 10c0/8de02c32e566421875c70890fe6d3d7bd55a92fc39867446e65999e042c4632fb27ab1a7e106e96edd12d63b32a643f3a690d9a980aeda655a41ddf4e8750f5d + languageName: node + linkType: hard + "polygon-clipping@npm:^0.15.3": version: 0.15.7 resolution: "polygon-clipping@npm:0.15.7" @@ -16224,6 +16417,13 @@ __metadata: languageName: node linkType: hard +"splaytree-ts@npm:^1.0.2": + version: 1.0.2 + resolution: "splaytree-ts@npm:1.0.2" + checksum: 10c0/4c34573891a749055ffe22381ea841ae03dbf7b55a3ea4a1d7df5013bfbe128e79f6c468579358ec573734cdbdf5f77a97ae7185f155248eb8be58151428c85e + languageName: node + linkType: hard + "splaytree@npm:^3.1.0": version: 3.1.2 resolution: "splaytree@npm:3.1.2" @@ -16584,6 +16784,15 @@ __metadata: languageName: node linkType: hard +"sweepline-intersections@npm:^1.5.0": + version: 1.5.0 + resolution: "sweepline-intersections@npm:1.5.0" + dependencies: + tinyqueue: "npm:^2.0.0" + checksum: 10c0/587a597c75b787e61054ef88b98463af47f60855265b7829fa8acc5ebe68fb4bc3d148a80e9f72c69c16a0241bfed38d3fbbe93a735ea5a2276c00116adc5283 + languageName: node + linkType: hard + "symbol-observable@npm:4.0.0": version: 4.0.0 resolution: "symbol-observable@npm:4.0.0" @@ -16772,6 +16981,13 @@ __metadata: languageName: node linkType: hard +"tinyqueue@npm:^2.0.0": + version: 2.0.3 + resolution: "tinyqueue@npm:2.0.3" + checksum: 10c0/d7b590088f015a94a17132fa209c2f2a80c45158259af5474901fdf5932e95ea13ff6f034bcc725a6d5f66d3e5b888b048c310229beb25ad5bebb4f0a635abf2 + languageName: node + linkType: hard + "tinyqueue@npm:^3.0.0": version: 3.0.0 resolution: "tinyqueue@npm:3.0.0" From 37dcb4988f5d081edc7a59d14e6a10da20e16748 Mon Sep 17 00:00:00 2001 From: "Juan D. Jara" Date: Wed, 29 Jan 2025 16:51:53 +0100 Subject: [PATCH 2/6] dropped features data --- .../src/components/views/IncomeView.tsx | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/create-react/src/components/views/IncomeView.tsx b/packages/create-react/src/components/views/IncomeView.tsx index ebac334..eaa47e5 100644 --- a/packages/create-react/src/components/views/IncomeView.tsx +++ b/packages/create-react/src/components/views/IncomeView.tsx @@ -48,6 +48,12 @@ export default function IncomeView() { // With authentication enabled, access token may change. const { accessToken, apiBaseUrl } = useContext(AppContext); const [attributionHTML, setAttributionHTML] = useState(''); + + // data to calculate feature dropping for each zoom level + const [fractionsDropped, setFractionsDropped] = useState([]); + const [minZoom, setMinZoom] = useState(0); + const [maxZoom, setMaxZoom] = useState(20); + // Debounce view state to avoid excessive re-renders during pan and zoom. const [viewState, setViewState] = useDebouncedState(INITIAL_VIEW_STATE, 200); @@ -114,7 +120,13 @@ export default function IncomeView() { */ useEffect(() => { - data?.then(({ attribution }) => setAttributionHTML(attribution)); + data?.then((res) => { + const { fraction_dropped_per_zoom, minzoom, maxzoom, attribution } = res + setFractionsDropped(fraction_dropped_per_zoom ?? []) + setMinZoom(minzoom ?? 0) + setMaxZoom(maxzoom ?? 20) + setAttributionHTML(attribution) + }) }, [data]); useEffect(() => { @@ -128,7 +140,21 @@ export default function IncomeView() { }) } }, [data, viewState]) - + + function clamp(n: number, min: number, max: number) { + return Math.min(Math.max(n, min), max); + } + + const droppingPercent = useMemo(() => { + if (!fractionsDropped.length) { + return 0 + } + const roundedZoom = Math.round(viewState.zoom) + const clampedZoom = clamp(roundedZoom, minZoom, maxZoom) + const percent = fractionsDropped[clampedZoom] + return percent + }, [minZoom, maxZoom, fractionsDropped, viewState.zoom]) + return ( <>
; + /** Column containing a value to be aggregated. */ + operationColumn: string; /** Map view state. If specified, widget will be filtered to the view. */ viewState?: MapViewState; /** Filter state. If specified, widget will be filtered. */ @@ -42,6 +44,7 @@ export function CategoryWidget({ data, column, operation, + operationColumn, viewState, filters, onFiltersChange, @@ -66,6 +69,7 @@ export function CategoryWidget({ widgetSource.getCategories({ column, operation, + operationColumn, spatialFilter: viewState && createSpatialFilter(viewState), abortController, filterOwner: owner, From 09b826d5bd9204d4745b6b434c212c840c736d2e Mon Sep 17 00:00:00 2001 From: "Juan D. Jara" Date: Thu, 6 Feb 2025 15:16:09 +0100 Subject: [PATCH 4/6] use same tileset as deck.gl example --- packages/create-react/.env | 2 +- .../views/{IncomeView.tsx => RiversView.tsx} | 45 ++++++++++--------- packages/create-react/src/routes.tsx | 8 ++-- 3 files changed, 30 insertions(+), 25 deletions(-) rename packages/create-react/src/components/views/{IncomeView.tsx => RiversView.tsx} (83%) diff --git a/packages/create-react/.env b/packages/create-react/.env index ad068d2..1809182 100644 --- a/packages/create-react/.env +++ b/packages/create-react/.env @@ -1,5 +1,5 @@ VITE_APP_TITLE="React template" -VITE_ACCESS_TOKEN="eyJhbGciOiJIUzI1NiJ9.eyJhIjoiYWNfNDd1dW5tZWciLCJqdGkiOiJhZjRlM2QxMSJ9.e1GDIOtg3Jy2zcwbFpAxsvK38RqycRrWII1NVTH7KtQ" +VITE_ACCESS_TOKEN="eyJhbGciOiJIUzI1NiJ9.eyJhIjoiYWNfN3hoZnd5bWwiLCJqdGkiOiIwNjU0ZTQ5MyJ9.WoBKztKg5ExQFkUsbAFbwjSZK9nV0ESE9S0_hWS5WgE" VITE_API_BASE_URL="https://gcp-us-east1.api.carto.com" VITE_AUTH_ENABLED="false" diff --git a/packages/create-react/src/components/views/IncomeView.tsx b/packages/create-react/src/components/views/RiversView.tsx similarity index 83% rename from packages/create-react/src/components/views/IncomeView.tsx rename to packages/create-react/src/components/views/RiversView.tsx index eaa7964..664d995 100644 --- a/packages/create-react/src/components/views/IncomeView.tsx +++ b/packages/create-react/src/components/views/RiversView.tsx @@ -3,18 +3,18 @@ import { useContext, useEffect, useMemo, useState } from "react"; import { AppContext } from "../../context"; import { useDebouncedState } from "../../hooks/useDebouncedState"; import { createViewportSpatialFilter, vectorTilesetSource } from "@carto/api-client"; -import { VectorTileLayer } from "@deck.gl/carto"; +import { BASEMAP, VectorTileLayer } from "@deck.gl/carto"; import { Card } from "../Card"; import { FormulaWidget } from "../widgets/FormulaWidget"; import DeckGL from "@deck.gl/react"; import { Map } from 'react-map-gl/maplibre'; import { Layers } from "../Layers"; import { LegendEntryCategorical } from "../legends/LegendEntryCategorical"; -import { CategoryWidget } from "../widgets/CategoryWidget"; +// import { CategoryWidget } from "../widgets/CategoryWidget"; +const CONNECTION_NAME = 'amanzanares-pm-bq'; +const TILESET_NAME = 'cartodb-on-gcp-pm-team.amanzanares_opensource_demo.national_water_model_tileset_final_test_4'; const MAP_VIEW = new MapView({ repeat: true }); -const MAP_STYLE = - 'https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json'; const INITIAL_VIEW_STATE: MapViewState = { latitude: 31.8028, @@ -43,7 +43,7 @@ function hexToRgb(hex: string) { } /** - * Example application page, showing U.S. income by block group. + * Example application page, showing U.S. streams network. */ export default function IncomeView() { // With authentication enabled, access token may change. @@ -68,8 +68,8 @@ export default function IncomeView() { vectorTilesetSource({ accessToken, apiBaseUrl, - connectionName: 'carto_dw', - tableName: 'carto-demo-data.demo_tilesets.sociodemographics_usa_blockgroup', + connectionName: CONNECTION_NAME, + tableName: TILESET_NAME, }), [accessToken, apiBaseUrl], ); @@ -95,14 +95,19 @@ export default function IncomeView() { pickable: true, visible: layerVisibility[LAYER_ID], data, - getLineColor: [0, 0 ,0], - lineWidthMinPixels: 0.3, - getFillColor: d => { - const n = d.properties.income_per_capita; - const index = histogramTicks.slice().reverse().findIndex((tick) => n >= tick); - const color = colors[index] || colors[colors.length - 1]; - return color as Color; + getLineColor: d => { + const [r, g, b] = hexToRgb('#d5d5d7'); + const n = d.properties.streamOrder; + const alphaPart = Math.min(n / 10, 1); + const alpha = 120 + 128 * alphaPart; + return [r, g, b, alpha]; }, + getLineWidth: d => { + const n = d.properties.streamOrder; + return n * 0.5; + }, + lineWidthUnits: 'pixels', + lineWidthMinPixels: 1, onViewportLoad(tiles) { data?.then((res) => { setTilesLoaded(true) @@ -163,7 +168,7 @@ export default function IncomeView() {