From 135a74540241bef4d94f4186ddcf34f9979da3e7 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Wed, 22 Sep 2021 09:51:27 -0400 Subject: [PATCH 01/24] layers - refactor pickable in poi layers --- src/components/layers/poi-cluster.js | 4 +--- src/components/layers/poi-geojson.js | 5 +++-- src/components/layers/poi-icon.js | 5 +++-- src/components/layers/poi-polygon.js | 5 +++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/components/layers/poi-cluster.js b/src/components/layers/poi-cluster.js index b4c84a5b..9664966b 100644 --- a/src/components/layers/poi-cluster.js +++ b/src/components/layers/poi-cluster.js @@ -41,7 +41,6 @@ class IconClusterLayer extends CompositeLayer { static defaultProps = { id: 'icon-cluster', getPosition: d => d.geometry.coordinates, - pickable: true, iconAtlas, iconMapping, sizeScale: 40, @@ -101,7 +100,6 @@ class IconClusterLayer extends CompositeLayer { iconMapping, sizeScale, getPosition, - pickable, visible, ...props } = this.props @@ -116,8 +114,8 @@ class IconClusterLayer extends CompositeLayer { getPosition, getIcon: d => getIconName(d), getSize: getIconSize(), - pickable, visible, + pickable: visible, ...props, }), ) diff --git a/src/components/layers/poi-geojson.js b/src/components/layers/poi-geojson.js index 0ecfec65..00bdb226 100644 --- a/src/components/layers/poi-geojson.js +++ b/src/components/layers/poi-geojson.js @@ -6,7 +6,6 @@ import { TYPE_RADIUS } from '../../constants' const defaultProps = { id: 'geojson-layer', - pickable: true, stroked: true, visible: false, filled: true, @@ -38,7 +37,7 @@ const defaultProps = { * @param { number } param.POIType - POI type * @returns { instanceOf GeoJsonLayer } */ -const POIGeoJson = ({ data, mapProps, POIType, ...props }) => +const POIGeoJson = ({ data, mapProps, POIType, visible, ...props }) => new GeoJsonLayer({ data, ...defaultProps, @@ -63,6 +62,8 @@ const POIGeoJson = ({ data, mapProps, POIType, ...props }) => getLineWidth: () => mapProps.lineWidth, opacity: mapProps.opacity, transitions: data.length === 1 ? { ...defaultProps.transitions } : {}, + visible, + pickable: visible, ...props, }) diff --git a/src/components/layers/poi-icon.js b/src/components/layers/poi-icon.js index 175baeed..dab74338 100644 --- a/src/components/layers/poi-icon.js +++ b/src/components/layers/poi-icon.js @@ -13,7 +13,6 @@ const defaultProps = { getIcon: () => 'marker', getPosition: d => d.geometry.coordinates, getSize: 5, - pickable: true, visible: false, } @@ -22,10 +21,12 @@ const defaultProps = { * @param { object } props - props object for passing data and other attributes to POIIcon * @returns { instanceOf IconLayer} */ -const POIIcon = (props) => +const POIIcon = ({ visible, ...props }) => new IconLayer({ ...defaultProps, sizeScale: props.data.length === 1 ? 12 : (props.data.length < 8 ? 8 : 5), + visible, + pickable: visible, ...props, }) diff --git a/src/components/layers/poi-polygon.js b/src/components/layers/poi-polygon.js index 6134b7e5..08c57995 100644 --- a/src/components/layers/poi-polygon.js +++ b/src/components/layers/poi-polygon.js @@ -4,7 +4,6 @@ import { PolygonLayer } from '@deck.gl/layers' const defaultProps = { id: 'polygon-layer', - pickable: true, stroked: true, filled: true, wireframe: true, @@ -20,7 +19,7 @@ const defaultProps = { * @param { array } param.data - data array * @returns { instanceOf PolygonLayer } */ -const POIPolygon = ({ mapProps, data, ...props }) => +const POIPolygon = ({ mapProps, data, visible, ...props }) => new PolygonLayer({ data, ...defaultProps, @@ -28,6 +27,8 @@ const POIPolygon = ({ mapProps, data, ...props }) => getLineColor: () => mapProps.lineColour, getLineWidth: () => mapProps.lineWidth, opacity: mapProps.opacity, + visible, + pickable: visible, ...props, }) export default POIPolygon From b26c2bdcb34d775c4f7bab867adb5f2d452035c1 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Wed, 22 Sep 2021 10:12:40 -0400 Subject: [PATCH 02/24] POIMap/utils - create utils file for POImap and move processLayers & setLayer in it from shared/utils --- src/components/poi-map/index.js | 8 ++------ src/components/poi-map/utils.js | 30 ++++++++++++++++++++++++++++++ src/shared/utils/index.js | 29 ----------------------------- 3 files changed, 32 insertions(+), 35 deletions(-) create mode 100644 src/components/poi-map/utils.js diff --git a/src/components/poi-map/index.js b/src/components/poi-map/index.js index ccf9feb1..eb749662 100644 --- a/src/components/poi-map/index.js +++ b/src/components/poi-map/index.js @@ -23,12 +23,8 @@ import DrawButtonGroup from './draw-button-group' import MapTooltip from '../tooltip' import tooltipNode from '../tooltip/tooltip-node' -import { - processLayers, - setView, - createCircleFromPointRadius, - getCircleRadiusCentroid, -} from '../../shared/utils' +import { processLayers } from './utils' +import { setView, createCircleFromPointRadius, getCircleRadiusCentroid } from '../../shared/utils' import { getCursor, truncate, formatDataPOI } from '../../utils' import { useResizeObserver } from '../../hooks' import { diff --git a/src/components/poi-map/utils.js b/src/components/poi-map/utils.js new file mode 100644 index 00000000..c8e66a74 --- /dev/null +++ b/src/components/poi-map/utils.js @@ -0,0 +1,30 @@ +import * as eqMapLayers from '../../components/layers' + + +/** + * processLayers - returns layers used by a map + * @param { object } param + * @param { array } param.mapLayers - array of layers to show on map + * @param { array } param.layerPool - array of all layers used by map in general + * @param { object } param.props - layers' props + * @returns { array } - array of Deck.gl and Nebula.gl layers used by a map + */ +export const processLayers = ({ mapLayers, layerPool, props }) => + layerPool.map(layer => + mapLayers.includes(layer) ? + setLayer({ layer, props, visible: true }) : + setLayer({ layer, props, visible: false }), + ) + +/** +* setLayer - sets a map layer +* @param { object } param +* @param { string } param.layer - name of a layer found in src/components/layers/index.js +* @param { object } param.props - object of layer props +* @param { boolean } param.visible - boolean to be used to set a certain layer visible or not on the map +* @returns { instanceOf } - Deck.gl or Nebula.gl layer +*/ +const setLayer = ({ layer, props, visible }) => + layer === 'POICluster' ? + new eqMapLayers[layer]({ ...props, visible }) : + eqMapLayers[layer]({ ...props, visible }) diff --git a/src/shared/utils/index.js b/src/shared/utils/index.js index 09396e53..ccb6c74c 100644 --- a/src/shared/utils/index.js +++ b/src/shared/utils/index.js @@ -1,5 +1,4 @@ import { WebMercatorViewport } from '@deck.gl/core' -import * as eqMapLayers from '../../components/layers' import circle from '@turf/circle' import { point } from '@turf/helpers' @@ -11,34 +10,6 @@ import { color } from 'd3-color' import { extent } from 'd3-array' -/** - * processLayers - returns layers used by a map - * @param { object } param - * @param { array } param.mapLayers - array of layers to show on map - * @param { array } param.layerPool - array of all layers used by map in general - * @param { object } param.props - layers' props - * @returns { array } - array of Deck.gl and Nebula.gl layers used by a map - */ -export const processLayers = ({ mapLayers, layerPool, props }) => - layerPool.map(layer => - mapLayers.includes(layer) ? - setLayer({ layer, props, visible: true }) : - setLayer({ layer, props, visible: false }), - ) - -/** - * setLayer - sets a map layer - * @param { object } param - * @param { string } param.layer - name of a layer found in src/components/layers/index.js - * @param { object } param.props - object of layer props - * @param { boolean } param.visible - boolean to be used to set a certain layer visible or not on the map - * @returns { instanceOf } - Deck.gl or Nebula.gl layer - */ -const setLayer = ({ layer, props, visible }) => - layer === 'POICluster' ? - new eqMapLayers[layer]({ ...props, visible }) : - eqMapLayers[layer]({ ...props, visible }) - /** * setView - handles calculations of viewState lat, long, and zoom, based on * data coordinates and deck size From 2f29047ba098f8ca49f6186e9e97514bd4be7735 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Wed, 22 Sep 2021 10:17:18 -0400 Subject: [PATCH 03/24] POIMap/utils - edit comments for processLayers --- src/components/poi-map/utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/poi-map/utils.js b/src/components/poi-map/utils.js index c8e66a74..0b751ea1 100644 --- a/src/components/poi-map/utils.js +++ b/src/components/poi-map/utils.js @@ -2,12 +2,12 @@ import * as eqMapLayers from '../../components/layers' /** - * processLayers - returns layers used by a map + * processLayers - returns layers used by POIMap * @param { object } param * @param { array } param.mapLayers - array of layers to show on map * @param { array } param.layerPool - array of all layers used by map in general * @param { object } param.props - layers' props - * @returns { array } - array of Deck.gl and Nebula.gl layers used by a map + * @returns { array } - array of Deck.gl and Nebula.gl layers used by POIMap */ export const processLayers = ({ mapLayers, layerPool, props }) => layerPool.map(layer => From cc01647848e840f846800f254d92dfeb955a2186 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Wed, 22 Sep 2021 10:46:08 -0400 Subject: [PATCH 04/24] POIMap - retrieve current cluster layer elements in the viewport as clusterLayerData --- src/components/poi-map/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/poi-map/index.js b/src/components/poi-map/index.js index eb749662..de495fa1 100644 --- a/src/components/poi-map/index.js +++ b/src/components/poi-map/index.js @@ -131,7 +131,9 @@ const POIMap = ({ const [onClickPayload, setOnClickPayload] = useState({}) const [hoverInfo, setHoverInfo] = useState(null) const [showRadius, setShowRadius] = useState(false) + const [clusterLayerData, setClusterLayerData] = useState() const mapContainerRef = useRef() + const deckRef = useRef() const mapRef = useRef() const { width, height } = useResizeObserver(mapContainerRef) @@ -519,6 +521,7 @@ const POIMap = ({ )} {mapCanRender && ( From 26a3fb37671d5a3dbbcfea21af559fed2441cc28 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Wed, 22 Sep 2021 10:48:13 -0400 Subject: [PATCH 05/24] POIMap/utils - add clusterZoomLevel and use in POIMap to determine if we see or not clusters in the current viewport --- src/components/poi-map/index.js | 8 +++++++- src/components/poi-map/utils.js | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/components/poi-map/index.js b/src/components/poi-map/index.js index de495fa1..a2e188fa 100644 --- a/src/components/poi-map/index.js +++ b/src/components/poi-map/index.js @@ -23,7 +23,7 @@ import DrawButtonGroup from './draw-button-group' import MapTooltip from '../tooltip' import tooltipNode from '../tooltip/tooltip-node' -import { processLayers } from './utils' +import { processLayers, clusterZoomLevel } from './utils' import { setView, createCircleFromPointRadius, getCircleRadiusCentroid } from '../../shared/utils' import { getCursor, truncate, formatDataPOI } from '../../utils' import { useResizeObserver } from '../../hooks' @@ -444,6 +444,12 @@ const POIMap = ({ const getCurrentCursor = getCursor({ layers }) + useEffect(() => { + if (clusterLayerData?.length) { + console.log('clusterZoomLevel: ', clusterZoomLevel({ clusterLayerData })) + } + }, [clusterLayerData]) + /** * finalTooltipKeys - React hook that returns an object of keys for MapTooltip component * @returns { object } - object of tooltip keys diff --git a/src/components/poi-map/utils.js b/src/components/poi-map/utils.js index 0b751ea1..e351b429 100644 --- a/src/components/poi-map/utils.js +++ b/src/components/poi-map/utils.js @@ -28,3 +28,14 @@ const setLayer = ({ layer, props, visible }) => layer === 'POICluster' ? new eqMapLayers[layer]({ ...props, visible }) : eqMapLayers[layer]({ ...props, visible }) + + +/** +* clusterZoomLevel - determines if we still have clusters in the data displayed in current viewport +* @param { object } param +* @param { string } param.clusterLayerData - cluster layer data displayed in the current viewport +* @returns { boolean } - boolean indicating if we see or not clusters in the viewport +*/ +export const clusterZoomLevel = ({ clusterLayerData }) => { + return Boolean(clusterLayerData.find(elem => elem?.object?.cluster)) +} From 57c13ee0f4ced77eb844c26964a2aabdddf8b578 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Wed, 22 Sep 2021 12:10:58 -0400 Subject: [PATCH 06/24] POIMap/utils - rename clusterLayerData as layerVisibleData; add showCluster to state and use it to change map layers and view --- src/components/poi-map/index.js | 22 ++++++++++++---------- src/components/poi-map/utils.js | 6 +++--- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/components/poi-map/index.js b/src/components/poi-map/index.js index a2e188fa..a04b3bf2 100644 --- a/src/components/poi-map/index.js +++ b/src/components/poi-map/index.js @@ -131,7 +131,8 @@ const POIMap = ({ const [onClickPayload, setOnClickPayload] = useState({}) const [hoverInfo, setHoverInfo] = useState(null) const [showRadius, setShowRadius] = useState(false) - const [clusterLayerData, setClusterLayerData] = useState() + const [showClusters, setShowClusters] = useState(true) + const [layerVisibleData, setLayerVisibleData] = useState() const mapContainerRef = useRef() const deckRef = useRef() const mapRef = useRef() @@ -176,7 +177,7 @@ const POIMap = ({ if (showRadius) { return ['POIGeoJson', 'POIIcon'] } - if (cluster) { + if (cluster && showClusters) { return ['POICluster'] } return ['POIIcon'] @@ -189,7 +190,7 @@ const POIMap = ({ return ['POIGeoJson'] } return [] - }, [mode, activePOI, cluster, POIType, createDrawMode, showRadius, showIcon]) + }, [mode, activePOI, cluster, showClusters, POIType, createDrawMode, showRadius, showIcon]) // React Hook to handle setting up data for DeckGL layers @@ -256,7 +257,7 @@ const POIMap = ({ return { display: { type: 'data view', - payload: { data, height, width }, + payload: { data, height, width, cluster, showClusters }, }, edit: { type: 'edit', @@ -274,7 +275,7 @@ const POIMap = ({ payload: INIT_VIEW[mapMode], }, } - }, [data, height, width, mapMode]) + }, [data, height, width, mapMode, cluster, showClusters]) // React hook that selects feature when map is in editing mode useEffect(() => { @@ -322,7 +323,8 @@ const POIMap = ({ // state viewState const [{ viewState }, viewStateDispatch] = useReducer((state, { type, payload }) => { - if (['data view', 'edit', 'create'].includes(type)) { + const { cluster, showClusters } = payload + if (['data view', 'edit', 'create'].includes(type) && ((cluster && showClusters) || !cluster) ) { return { viewState: { ...state.viewState, @@ -445,10 +447,10 @@ const POIMap = ({ const getCurrentCursor = getCursor({ layers }) useEffect(() => { - if (clusterLayerData?.length) { - console.log('clusterZoomLevel: ', clusterZoomLevel({ clusterLayerData })) + if (layerVisibleData?.length) { + setShowClusters(clusterZoomLevel({ layerVisibleData })) } - }, [clusterLayerData]) + }, [layerVisibleData]) /** * finalTooltipKeys - React hook that returns an object of keys for MapTooltip component @@ -558,7 +560,7 @@ const POIMap = ({ setAllowDrawing(true) } setHoverInfo(null) - setClusterLayerData(deckRef?.current?.pickObjects({ x: 0, y: 0, width, height })) + setLayerVisibleData(deckRef?.current?.pickObjects({ x: 0, y: 0, width, height })) }} getCursor={getCurrentCursor} > diff --git a/src/components/poi-map/utils.js b/src/components/poi-map/utils.js index e351b429..259bce88 100644 --- a/src/components/poi-map/utils.js +++ b/src/components/poi-map/utils.js @@ -33,9 +33,9 @@ const setLayer = ({ layer, props, visible }) => /** * clusterZoomLevel - determines if we still have clusters in the data displayed in current viewport * @param { object } param -* @param { string } param.clusterLayerData - cluster layer data displayed in the current viewport +* @param { string } param.clusterLayerVisibleData - cluster layer data displayed in the current viewport * @returns { boolean } - boolean indicating if we see or not clusters in the viewport */ -export const clusterZoomLevel = ({ clusterLayerData }) => { - return Boolean(clusterLayerData.find(elem => elem?.object?.cluster)) +export const clusterZoomLevel = ({ layerVisibleData }) => { + return Boolean(layerVisibleData.find(elem => elem?.object?.cluster)) } From 40f3ad112c1279df6909f848806e979b42dae0df Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Wed, 22 Sep 2021 18:42:56 -0400 Subject: [PATCH 07/24] constants - add CLUSTER_SIZE_SCALE, SUPERCLUSTER_ZOOM --- src/constants.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/constants.js b/src/constants.js index 52445901..2922c7a3 100644 --- a/src/constants.js +++ b/src/constants.js @@ -23,3 +23,6 @@ export const SCALES = { 'quantile': scaleQuantile, 'quantize': scaleQuantize, } + +export const CLUSTER_SIZE_SCALE = 40 +export const SUPERCLUSTER_ZOOM = 20 From 7533f2b806125568acfada6aa54b094405fa879a Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Wed, 22 Sep 2021 18:43:44 -0400 Subject: [PATCH 08/24] shared/utils - add getSuperclusterRadius --- src/components/poi-map/utils.js | 38 +++++++++++++++++++++++++++------ src/shared/utils/index.js | 14 +++++++++++- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/components/poi-map/utils.js b/src/components/poi-map/utils.js index 259bce88..529db000 100644 --- a/src/components/poi-map/utils.js +++ b/src/components/poi-map/utils.js @@ -1,5 +1,9 @@ +import Supercluster from 'supercluster' import * as eqMapLayers from '../../components/layers' +import { getSuperclusterRadius } from '../../shared/utils' +import { SUPERCLUSTER_ZOOM } from '../../constants' + /** * processLayers - returns layers used by POIMap @@ -29,13 +33,35 @@ const setLayer = ({ layer, props, visible }) => new eqMapLayers[layer]({ ...props, visible }) : eqMapLayers[layer]({ ...props, visible }) - /** -* clusterZoomLevel - determines if we still have clusters in the data displayed in current viewport +* isClusterZoomLevel - determines if we should use cluster layer for the data in the current viewport * @param { object } param -* @param { string } param.clusterLayerVisibleData - cluster layer data displayed in the current viewport -* @returns { boolean } - boolean indicating if we see or not clusters in the viewport +* @param { string } param.layerVisibleData - layer data displayed in the current viewport +* @returns { boolean } - boolean indicating whether we should show clusters on the map */ -export const clusterZoomLevel = ({ layerVisibleData }) => { - return Boolean(layerVisibleData.find(elem => elem?.object?.cluster)) +export const isClusterZoomLevel = ({ layerVisibleData, zoom }) => { + if (layerVisibleData[0].layer.id === 'IconClusterLayer') { + return Boolean(layerVisibleData?.find(elem => elem?.object?.cluster)) + } + const visiblePOIs = layerVisibleData.reduce((agg, elem) => { + return elem.objects ? [...agg, ...elem.objects] : [...agg, elem.object] + }, []) + + if (visiblePOIs?.length) { + const getPosition = d => d.geometry.coordinates + const index = new Supercluster({ + maxZoom: SUPERCLUSTER_ZOOM, + radius: getSuperclusterRadius({ zoom }), + }) + index.load( + visiblePOIs.map(d => ({ + geometry: { coordinates: getPosition(d) }, + properties: d.properties, + })), + ) + const z = Math.floor(zoom) + const clusterData = index.getClusters([-180, -85, 180, 85], z) + + return Boolean(clusterData.find(elem => elem?.properties?.cluster)) + } } diff --git a/src/shared/utils/index.js b/src/shared/utils/index.js index ccb6c74c..1741978e 100644 --- a/src/shared/utils/index.js +++ b/src/shared/utils/index.js @@ -5,7 +5,7 @@ import { point } from '@turf/helpers' import tCentroid from '@turf/centroid' import tBBox from '@turf/bbox' import tDistance from '@turf/distance' -import { SCALES } from '../../constants' +import { SCALES, CLUSTER_SIZE_SCALE } from '../../constants' import { color } from 'd3-color' import { extent } from 'd3-array' @@ -268,3 +268,15 @@ export const getArrayGradientFillColors = ({ fillColors, opacity }) => */ export const setLegendOpacity = ({ opacity }) => opacity >= 1 ? 1 : (opacity > 0.6 ? 0.9 : opacity + 0.2) + +/** + * getSuperclusterRadius - determines cluster radius + * @param { object } param + * @param { number } param.zoom - viewstate zoom + * @param { number } param.sizeScale - scale for cluster radius size + * @returns { number } - cluster radius in pixels + */ +export const getSuperclusterRadius = ({ zoom, sizeScale = CLUSTER_SIZE_SCALE }) => + zoom > 15 ? + sizeScale / 2 : + sizeScale From d6eb0cec422a599d178db58d45d2bd79e5ecf8ac Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Wed, 22 Sep 2021 18:48:39 -0400 Subject: [PATCH 09/24] layers/POICluster - use CLUSTER_SIZE_SCALE, SUPERCLUSTER_ZOOM, getSuperclusterRadius from constants and shared/utils --- src/components/layers/poi-cluster.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/layers/poi-cluster.js b/src/components/layers/poi-cluster.js index 9664966b..32cce912 100644 --- a/src/components/layers/poi-cluster.js +++ b/src/components/layers/poi-cluster.js @@ -10,6 +10,9 @@ import Supercluster from 'supercluster' import iconMapping from '../icons/cluster.json' import iconAtlas from '../icons/cluster.png' +import { getSuperclusterRadius } from '../../shared/utils' +import { CLUSTER_SIZE_SCALE, SUPERCLUSTER_ZOOM } from '../../constants' + /** * getIconName - sets icon name for clusters * @param { object } d - POI data point @@ -43,10 +46,9 @@ class IconClusterLayer extends CompositeLayer { getPosition: d => d.geometry.coordinates, iconAtlas, iconMapping, - sizeScale: 40, - superclusterZoom: 20, - getSuperclusterRadius: (viewportZoom, sizeScale) => - viewportZoom > 15 ? sizeScale / 2 : sizeScale, + sizeScale: CLUSTER_SIZE_SCALE, + superclusterZoom: SUPERCLUSTER_ZOOM, + getSuperclusterRadius, visible: false, } @@ -60,7 +62,7 @@ class IconClusterLayer extends CompositeLayer { if (rebuildIndex) { const index = new Supercluster({ maxZoom: props.superclusterZoom, - radius: props.getSuperclusterRadius(this.context.viewport.zoom, props.sizeScale), + radius: props.getSuperclusterRadius({ zoom: this.context.viewport.zoom }), }) index.load( props.data.map(d => ({ From a1a2a969a3c315f156b717c1b0019e6ae9413f8d Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Wed, 22 Sep 2021 18:55:06 -0400 Subject: [PATCH 10/24] POIMap - rename clusterZoomLevel as isClusterZoomLevel; add zoom to state; refactor useEffect for showClusters state; add onViewStateChange to get zoom; refactor onInteractionStateChange --- src/components/poi-map/index.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/components/poi-map/index.js b/src/components/poi-map/index.js index a04b3bf2..ccaa0f35 100644 --- a/src/components/poi-map/index.js +++ b/src/components/poi-map/index.js @@ -23,7 +23,7 @@ import DrawButtonGroup from './draw-button-group' import MapTooltip from '../tooltip' import tooltipNode from '../tooltip/tooltip-node' -import { processLayers, clusterZoomLevel } from './utils' +import { processLayers, isClusterZoomLevel } from './utils' import { setView, createCircleFromPointRadius, getCircleRadiusCentroid } from '../../shared/utils' import { getCursor, truncate, formatDataPOI } from '../../utils' import { useResizeObserver } from '../../hooks' @@ -130,6 +130,7 @@ const POIMap = ({ const [allowDrawing, setAllowDrawing] = useState(true) const [onClickPayload, setOnClickPayload] = useState({}) const [hoverInfo, setHoverInfo] = useState(null) + const [zoom, setZoom] = useState(INIT_VIEW_STATE.zoom) const [showRadius, setShowRadius] = useState(false) const [showClusters, setShowClusters] = useState(true) const [layerVisibleData, setLayerVisibleData] = useState() @@ -446,17 +447,18 @@ const POIMap = ({ const getCurrentCursor = getCursor({ layers }) + // set state for showClusters useEffect(() => { - if (layerVisibleData?.length) { - setShowClusters(clusterZoomLevel({ layerVisibleData })) + if (layerVisibleData?.length && zoom) { + setShowClusters(isClusterZoomLevel({ layerVisibleData, zoom })) } - }, [layerVisibleData]) + }, [layerVisibleData, zoom]) /** - * finalTooltipKeys - React hook that returns an object of keys for MapTooltip component - * @returns { object } - object of tooltip keys - * { name, id, metricKeys, metricAliases, nameAccessor, idAccessor, metricAccessor} - */ + * finalTooltipKeys - React hook that returns an object of keys for MapTooltip component + * @returns { object } - object of tooltip keys + * { name, id, metricKeys, metricAliases, nameAccessor, idAccessor, metricAccessor} + */ const finalTooltipKeys = useMemo(() => { const { id, idAccessor, name, nameAccessor } = tooltipKeys let metricKeysArray = tooltipKeys?.metricKeys || ['lon', 'lat'] @@ -552,15 +554,19 @@ const POIMap = ({ // data[0].properties.isOnMapEditing = false // } // }} + onViewStateChange={o => { + const { viewState } = o + setZoom(viewState.zoom) + }} onInteractionStateChange={interactionState => { const{ inTransition } = interactionState if (inTransition) { setAllowDrawing(false) } else { setAllowDrawing(true) + setLayerVisibleData(deckRef?.current?.pickObjects({ x: 0, y: 0, width, height })) } setHoverInfo(null) - setLayerVisibleData(deckRef?.current?.pickObjects({ x: 0, y: 0, width, height })) }} getCursor={getCurrentCursor} > From c13ba453e5de5c46fb56551c4590b9be4ccece37 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Wed, 22 Sep 2021 18:58:26 -0400 Subject: [PATCH 11/24] POIMap/utils - fix function descriptions --- src/components/poi-map/utils.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/components/poi-map/utils.js b/src/components/poi-map/utils.js index 529db000..9a973880 100644 --- a/src/components/poi-map/utils.js +++ b/src/components/poi-map/utils.js @@ -21,24 +21,25 @@ export const processLayers = ({ mapLayers, layerPool, props }) => ) /** -* setLayer - sets a map layer -* @param { object } param -* @param { string } param.layer - name of a layer found in src/components/layers/index.js -* @param { object } param.props - object of layer props -* @param { boolean } param.visible - boolean to be used to set a certain layer visible or not on the map -* @returns { instanceOf } - Deck.gl or Nebula.gl layer -*/ + * setLayer - sets a map layer + * @param { object } param + * @param { string } param.layer - name of a layer found in src/components/layers/index.js + * @param { object } param.props - object of layer props + * @param { boolean } param.visible - boolean to be used to set a certain layer visible or not on the map + * @returns { instanceOf } - Deck.gl or Nebula.gl layer + */ const setLayer = ({ layer, props, visible }) => layer === 'POICluster' ? new eqMapLayers[layer]({ ...props, visible }) : eqMapLayers[layer]({ ...props, visible }) /** -* isClusterZoomLevel - determines if we should use cluster layer for the data in the current viewport -* @param { object } param -* @param { string } param.layerVisibleData - layer data displayed in the current viewport -* @returns { boolean } - boolean indicating whether we should show clusters on the map -*/ + * isClusterZoomLevel - determines if we should use cluster layer for the data in the current viewport + * @param { object } param + * @param { string } param.layerVisibleData - layer data displayed in the current viewport + * @param { string } param.zoom - current map viewport zoom + * @returns { boolean } - boolean indicating whether we should show clusters on the map + */ export const isClusterZoomLevel = ({ layerVisibleData, zoom }) => { if (layerVisibleData[0].layer.id === 'IconClusterLayer') { return Boolean(layerVisibleData?.find(elem => elem?.object?.cluster)) From d2237fb5b5206d4f47097f93cebca5dd768211b1 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Thu, 23 Sep 2021 14:43:02 -0400 Subject: [PATCH 12/24] POIMap - add clusterZoom to state; set inital showClusters to false; add switch for Show Clusters; adjust mapLayers to the new state; add conditions for switch elements --- src/components/poi-map/index.js | 67 +++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/src/components/poi-map/index.js b/src/components/poi-map/index.js index ccaa0f35..befaa836 100644 --- a/src/components/poi-map/index.js +++ b/src/components/poi-map/index.js @@ -46,7 +46,7 @@ setup(React.createElement) const MapWrapper = styled('div')` ` -const SwitchContainer = styled('div')` +const SwitchContainerCluster = styled('div')` position: absolute; margin: 15px; z-index: 1; @@ -55,6 +55,17 @@ const SwitchContainer = styled('div')` padding: 5px; ` +const SwitchContainerRadius = styled('div')` + position: absolute; + margin: 15px; + margin-top: ${props => props.clusterswitch ? 60 : 15}px; + z-index: 1; + background-color: white; + border-radius: 3px; + padding: 5px; + width: 154px; +` + const DrawButtonContainer = styled('div')` position: absolute; right: 15px; @@ -132,7 +143,8 @@ const POIMap = ({ const [hoverInfo, setHoverInfo] = useState(null) const [zoom, setZoom] = useState(INIT_VIEW_STATE.zoom) const [showRadius, setShowRadius] = useState(false) - const [showClusters, setShowClusters] = useState(true) + const [showClusters, setShowClusters] = useState(false) + const [clusterZoom, setClusterZoom] = useState(false) const [layerVisibleData, setLayerVisibleData] = useState() const mapContainerRef = useRef() const deckRef = useRef() @@ -175,10 +187,10 @@ const POIMap = ({ return ['POIEditDraw'] } if (POIType === TYPE_RADIUS.code) { - if (showRadius) { + if ((cluster && showClusters && !clusterZoom && showRadius) || showRadius) { return ['POIGeoJson', 'POIIcon'] } - if (cluster && showClusters) { + if (cluster && showClusters && clusterZoom) { return ['POICluster'] } return ['POIIcon'] @@ -191,7 +203,7 @@ const POIMap = ({ return ['POIGeoJson'] } return [] - }, [mode, activePOI, cluster, showClusters, POIType, createDrawMode, showRadius, showIcon]) + }, [mode, activePOI, cluster, showClusters, clusterZoom, POIType, createDrawMode, showRadius, showIcon]) // React Hook to handle setting up data for DeckGL layers @@ -258,7 +270,7 @@ const POIMap = ({ return { display: { type: 'data view', - payload: { data, height, width, cluster, showClusters }, + payload: { data, height, width }, }, edit: { type: 'edit', @@ -276,7 +288,7 @@ const POIMap = ({ payload: INIT_VIEW[mapMode], }, } - }, [data, height, width, mapMode, cluster, showClusters]) + }, [data, height, width, mapMode]) // React hook that selects feature when map is in editing mode useEffect(() => { @@ -324,8 +336,7 @@ const POIMap = ({ // state viewState const [{ viewState }, viewStateDispatch] = useReducer((state, { type, payload }) => { - const { cluster, showClusters } = payload - if (['data view', 'edit', 'create'].includes(type) && ((cluster && showClusters) || !cluster) ) { + if (['data view', 'edit', 'create'].includes(type)) { return { viewState: { ...state.viewState, @@ -447,12 +458,21 @@ const POIMap = ({ const getCurrentCursor = getCursor({ layers }) - // set state for showClusters + // set state for clusterZoom + useEffect(() => { + if (zoom && cluster && showClusters) { + if (layerVisibleData?.length) { + setClusterZoom(isClusterZoomLevel({ layerVisibleData, zoom })) + } + } + }, [layerVisibleData, zoom, cluster, showClusters]) + + // hide radius switch when we have clusters enabled and cluster level zoom useEffect(() => { - if (layerVisibleData?.length && zoom) { - setShowClusters(isClusterZoomLevel({ layerVisibleData, zoom })) + if (cluster && clusterZoom && showClusters) { + setShowRadius(false) } - }, [layerVisibleData, zoom]) + }, [cluster, showClusters, clusterZoom]) /** * finalTooltipKeys - React hook that returns an object of keys for MapTooltip component @@ -486,8 +506,23 @@ const POIMap = ({ return ( - {POIType === TYPE_RADIUS.code && !cluster && mode !=='edit' && !mode.startsWith('create-') && ( - + {POIType === TYPE_RADIUS.code && cluster && mode !=='edit' && !mode.startsWith('create-') && ( + + setShowClusters(!showClusters)} + /> + } + label='Show Clusters' + /> + + )} + {POIType === TYPE_RADIUS.code && + ((cluster && showClusters && !clusterZoom) || (cluster && !showClusters) || !cluster) && + mode !=='edit' && !mode.startsWith('create-') && ( + - + )} {hoverInfo?.object && From 9663e6a46f7a141e29e505631ddf42d1cbfa1ef0 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Thu, 23 Sep 2021 14:44:18 -0400 Subject: [PATCH 13/24] Stories/poi - rephrase story titles --- stories/poi.stories.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stories/poi.stories.js b/stories/poi.stories.js index 42a24976..5c2440fe 100644 --- a/stories/poi.stories.js +++ b/stories/poi.stories.js @@ -39,11 +39,11 @@ POIClusters.args = { cluster: true, ...displayArgs, } -POIClusters.storyName = 'Point POIs - clusters with POICluster layer' +POIClusters.storyName = 'Point POIs - using clusters with POICluster, POIIcon, & POIGeoJson layers' export const RadiiAndIcons = Template.bind({}) RadiiAndIcons.args = { POIData: POIsRadiiTo, ...displayArgs } -RadiiAndIcons.storyName = 'Point POIs - radii & icons with POIIcon & POIGeoJson layers' +RadiiAndIcons.storyName = 'Point POIs - radii & icons with POIIcon & POIGeoJson layers - no clusters' export const PointPOIOne = Template.bind({}) PointPOIOne.args = { POIData: [POIsRadiiTo[0]], ...displayArgs } From 33efdf4b8deb5877f716f19332a9f1e7df13a6d6 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Fri, 24 Sep 2021 16:40:55 -0400 Subject: [PATCH 14/24] POImap/utils - add viewportBBOX prop to isClusterZoomLevel and use it to calculate clusters --- src/components/poi-map/utils.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/poi-map/utils.js b/src/components/poi-map/utils.js index 9a973880..0b89530b 100644 --- a/src/components/poi-map/utils.js +++ b/src/components/poi-map/utils.js @@ -37,13 +37,11 @@ const setLayer = ({ layer, props, visible }) => * isClusterZoomLevel - determines if we should use cluster layer for the data in the current viewport * @param { object } param * @param { string } param.layerVisibleData - layer data displayed in the current viewport + * @param { string } param.viewportBBOX - bounding box coordinates for the current viewport * @param { string } param.zoom - current map viewport zoom * @returns { boolean } - boolean indicating whether we should show clusters on the map */ -export const isClusterZoomLevel = ({ layerVisibleData, zoom }) => { - if (layerVisibleData[0].layer.id === 'IconClusterLayer') { - return Boolean(layerVisibleData?.find(elem => elem?.object?.cluster)) - } +export const isClusterZoomLevel = ({ layerVisibleData, viewportBBOX, zoom }) => { const visiblePOIs = layerVisibleData.reduce((agg, elem) => { return elem.objects ? [...agg, ...elem.objects] : [...agg, elem.object] }, []) @@ -61,7 +59,7 @@ export const isClusterZoomLevel = ({ layerVisibleData, zoom }) => { })), ) const z = Math.floor(zoom) - const clusterData = index.getClusters([-180, -85, 180, 85], z) + const clusterData = index.getClusters(viewportBBOX, z) return Boolean(clusterData.find(elem => elem?.properties?.cluster)) } From c67a587ab2652c20503df0fca502b05977db079f Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Fri, 24 Sep 2021 16:44:12 -0400 Subject: [PATCH 15/24] POIMap - add viewportBBOX to state; calculate viewportBBOX coords in onViewStateChange; move setLayerVisibleData to onAfterRender; fix useEffect fro clusterZoom --- src/components/poi-map/index.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/components/poi-map/index.js b/src/components/poi-map/index.js index befaa836..7377facb 100644 --- a/src/components/poi-map/index.js +++ b/src/components/poi-map/index.js @@ -14,6 +14,7 @@ import DeckGL from '@deck.gl/react' import { FlyToInterpolator } from '@deck.gl/core' import { StaticMap } from 'react-map-gl' import Geocoder from 'react-map-gl-geocoder' +import { WebMercatorViewport } from '@deck.gl/core' import { FormControlLabel } from '@material-ui/core' import { Switch } from '@eqworks/lumen-ui' @@ -142,6 +143,7 @@ const POIMap = ({ const [onClickPayload, setOnClickPayload] = useState({}) const [hoverInfo, setHoverInfo] = useState(null) const [zoom, setZoom] = useState(INIT_VIEW_STATE.zoom) + const [viewportBBOX, setViewportBBOX] = useState() const [showRadius, setShowRadius] = useState(false) const [showClusters, setShowClusters] = useState(false) const [clusterZoom, setClusterZoom] = useState(false) @@ -205,7 +207,6 @@ const POIMap = ({ return [] }, [mode, activePOI, cluster, showClusters, clusterZoom, POIType, createDrawMode, showRadius, showIcon]) - // React Hook to handle setting up data for DeckGL layers useEffect(() => { // remove created activePOI from data list if it was added to POI list in poi-manage @@ -460,12 +461,10 @@ const POIMap = ({ // set state for clusterZoom useEffect(() => { - if (zoom && cluster && showClusters) { - if (layerVisibleData?.length) { - setClusterZoom(isClusterZoomLevel({ layerVisibleData, zoom })) - } + if (cluster && showClusters && layerVisibleData?.length && viewportBBOX?.length && zoom) { + setClusterZoom(isClusterZoomLevel({ layerVisibleData, viewportBBOX, zoom })) } - }, [layerVisibleData, zoom, cluster, showClusters]) + }, [cluster, showClusters, layerVisibleData, viewportBBOX, zoom]) // hide radius switch when we have clusters enabled and cluster level zoom useEffect(() => { @@ -493,9 +492,7 @@ const POIMap = ({ } }, [tooltipKeys, dataPropertyAccessor]) - /** - * mapCanRender - conditions to render the map - */ + // mapCanRender - conditions to render the map const mapCanRender = Boolean(useMemo(() => (mapLayers.includes('POIEditDraw') && data[0]?.properties?.poiType === TYPE_POLYGON.code) || (!mapLayers.includes('POIEditDraw') && data.length) || @@ -592,6 +589,7 @@ const POIMap = ({ onViewStateChange={o => { const { viewState } = o setZoom(viewState.zoom) + setViewportBBOX(new WebMercatorViewport(viewState).getBounds()) }} onInteractionStateChange={interactionState => { const{ inTransition } = interactionState @@ -599,11 +597,13 @@ const POIMap = ({ setAllowDrawing(false) } else { setAllowDrawing(true) - setLayerVisibleData(deckRef?.current?.pickObjects({ x: 0, y: 0, width, height })) } setHoverInfo(null) }} getCursor={getCurrentCursor} + onAfterRender={() => + setLayerVisibleData(deckRef?.current?.pickObjects({ x: 0, y: 0, width, height })) + } > Date: Mon, 27 Sep 2021 13:08:17 -0400 Subject: [PATCH 16/24] POIMap - add clusterClick to state and use it to block reset of view state in useLayoutEffect; simplify conditions for switch rendering --- src/components/poi-map/index.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/components/poi-map/index.js b/src/components/poi-map/index.js index 7377facb..6e4b50cb 100644 --- a/src/components/poi-map/index.js +++ b/src/components/poi-map/index.js @@ -147,6 +147,8 @@ const POIMap = ({ const [showRadius, setShowRadius] = useState(false) const [showClusters, setShowClusters] = useState(false) const [clusterZoom, setClusterZoom] = useState(false) + // used to block reset of view state when we transition from the cluster to the icon layer + const [clusterClick, setClusterClick] = useState(false) const [layerVisibleData, setLayerVisibleData] = useState() const mapContainerRef = useRef() const deckRef = useRef() @@ -306,6 +308,11 @@ const POIMap = ({ * @param { array } param.coordinate - coordinates of the clicked object */ const onClick = useCallback(({ object, layer, coordinate }) => { + if (mapLayers.includes('POICluster')) { + setClusterClick(true) + } else { + setClusterClick(false) + } // if clicked object is a cluster, zoom in if (object?.cluster) { const [longitude, latitude] = coordinate @@ -320,7 +327,7 @@ const POIMap = ({ // custom onClick onClickHandle({ object, layer, coordinate }, setOnClickPayload) } - }, [setActivePOI, onClickHandle, height, width]) + }, [mapLayers, setActivePOI, onClickHandle, height, width]) /** * onHover - React hook that handles onHover event @@ -366,10 +373,10 @@ const POIMap = ({ useLayoutEffect(() => { if (((data?.length && mapLayers.length) || (mapMode === 'emptyMap' && !data?.length && !mapLayers.length)) && - width && height) { + width && height && !clusterClick) { viewStateDispatch(viewParam[mapMode]) } - }, [data, mapLayers, width, height, viewParam, mapMode]) + }, [data, mapLayers, width, height, viewParam, mapMode, clusterClick]) // React Hook to update viewState for onClick events useEffect(() => { @@ -503,7 +510,7 @@ const POIMap = ({ return ( - {POIType === TYPE_RADIUS.code && cluster && mode !=='edit' && !mode.startsWith('create-') && ( + {POIType === TYPE_RADIUS.code && cluster && mapMode === 'display' && data?.length > 1 && ( + mapMode === 'display' && ( + 1 ? 'yes' : undefined}> Date: Mon, 27 Sep 2021 13:10:08 -0400 Subject: [PATCH 17/24] package - change version to 0.7.2-alpha.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c209608f..a593246a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@eqworks/react-maps", - "version": "0.7.1", + "version": "0.7.2-alpha.6", "description": "React maps", "author": "EQ Inc.", "license": "UNLICENSED", From 6d35ba4c8eb68c85209359cf47a69b073f2cd5bb Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Tue, 28 Sep 2021 09:26:42 -0400 Subject: [PATCH 18/24] POIMap - use deckref to calculate viewport with and height instead of useResizeObserver --- src/components/poi-map/index.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/poi-map/index.js b/src/components/poi-map/index.js index 6e4b50cb..584ca04f 100644 --- a/src/components/poi-map/index.js +++ b/src/components/poi-map/index.js @@ -27,7 +27,6 @@ import tooltipNode from '../tooltip/tooltip-node' import { processLayers, isClusterZoomLevel } from './utils' import { setView, createCircleFromPointRadius, getCircleRadiusCentroid } from '../../shared/utils' import { getCursor, truncate, formatDataPOI } from '../../utils' -import { useResizeObserver } from '../../hooks' import { typographyPropTypes, typographyDefaultProps, @@ -153,7 +152,7 @@ const POIMap = ({ const mapContainerRef = useRef() const deckRef = useRef() const mapRef = useRef() - const { width, height } = useResizeObserver(mapContainerRef) + const [{ width, height }, setDimensions ] = useState({}) // React hook that sets POIType const POIType = useMemo(() => { @@ -574,6 +573,13 @@ const POIMap = ({ initialViewState={viewState} layers={layers} controller={controller} + onLoad={() => { + const { height, width } = deckRef?.current?.deck + setDimensions({ height, width }) + }} + onResize={({ height, width }) => { + setDimensions({ height, width }) + }} /** * USE once nebula.gl fixes selectedFeatureIndex out of range value cases (ie [], null) * onClick for edit mode to select feature for editing From 866ed81d22fc55f3e235b78b0809df19192905db Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Tue, 28 Sep 2021 09:27:25 -0400 Subject: [PATCH 19/24] hooks - delete useResizeObserver --- src/hooks/index.js | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/hooks/index.js b/src/hooks/index.js index 9817bb05..95a2c75d 100644 --- a/src/hooks/index.js +++ b/src/hooks/index.js @@ -292,27 +292,3 @@ export const useTimeline = (timestampInit, speedInterval) => { } export { useReport, useFullReport } from './report' - -/** - * useResizeObserver - returns the dimensions of a changing HTML element - * based on: https://github.com/plouc/nivo/blob/7d52c07/packages/core/src/hooks/useMeasure.js & - * https://github.com/EQWorks/snoke-builder-viz/pull/21/files - * @param { object } ref - React ref - * @returns { object } - dimensions { width, height } of an HTML element - */ -export const useResizeObserver = (ref) => { - const [dimensions, setDimensions] = useState({ width: 0, height: 0 }) - const observer = useMemo(() => - new ResizeObserver(([entry]) => setDimensions(entry.contentRect)) - ,[]) - - useEffect(() => { - if (ref.current) { - observer.observe(ref.current) - } - - return () => observer.disconnect() - }, [ref, observer]) - - return dimensions -} From 59d7b2b0c7c7b250b1dfcaa6b19334008c78e5d3 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Tue, 28 Sep 2021 10:57:29 -0400 Subject: [PATCH 20/24] layers/POICluster - refactor radius in new Soperclaster --- src/components/layers/poi-cluster.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/layers/poi-cluster.js b/src/components/layers/poi-cluster.js index 32cce912..5624afdb 100644 --- a/src/components/layers/poi-cluster.js +++ b/src/components/layers/poi-cluster.js @@ -62,7 +62,7 @@ class IconClusterLayer extends CompositeLayer { if (rebuildIndex) { const index = new Supercluster({ maxZoom: props.superclusterZoom, - radius: props.getSuperclusterRadius({ zoom: this.context.viewport.zoom }), + radius: props.getSuperclusterRadius(this.context.viewport.zoom), }) index.load( props.data.map(d => ({ From 1a57ed23e8b1914013c089dddf4ac486fc4cc9c3 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Tue, 28 Sep 2021 11:11:02 -0400 Subject: [PATCH 21/24] POIMap - refactor mapLayers for showRadius; setClusterClick in onClick; reset clusterClick at the end of useLayoutEffect" --- src/components/poi-map/index.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/components/poi-map/index.js b/src/components/poi-map/index.js index 584ca04f..9ea8f4c8 100644 --- a/src/components/poi-map/index.js +++ b/src/components/poi-map/index.js @@ -152,7 +152,7 @@ const POIMap = ({ const mapContainerRef = useRef() const deckRef = useRef() const mapRef = useRef() - const [{ width, height }, setDimensions ] = useState({}) + const [{ width, height }, setDimensions] = useState({}) // React hook that sets POIType const POIType = useMemo(() => { @@ -190,7 +190,7 @@ const POIMap = ({ return ['POIEditDraw'] } if (POIType === TYPE_RADIUS.code) { - if ((cluster && showClusters && !clusterZoom && showRadius) || showRadius) { + if (showRadius) { return ['POIGeoJson', 'POIIcon'] } if (cluster && showClusters && clusterZoom) { @@ -307,11 +307,7 @@ const POIMap = ({ * @param { array } param.coordinate - coordinates of the clicked object */ const onClick = useCallback(({ object, layer, coordinate }) => { - if (mapLayers.includes('POICluster')) { - setClusterClick(true) - } else { - setClusterClick(false) - } + setClusterClick(mapLayers.includes('POICluster')) // if clicked object is a cluster, zoom in if (object?.cluster) { const [longitude, latitude] = coordinate @@ -375,6 +371,7 @@ const POIMap = ({ width && height && !clusterClick) { viewStateDispatch(viewParam[mapMode]) } + setClusterClick(false) }, [data, mapLayers, width, height, viewParam, mapMode, clusterClick]) // React Hook to update viewState for onClick events From e75474218de3e86ff159c81fe6628f789c54059f Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Wed, 29 Sep 2021 13:26:47 -0400 Subject: [PATCH 22/24] POIMap - delete clusterClick and simplify useLayoutEffect conditions --- src/components/poi-map/index.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/components/poi-map/index.js b/src/components/poi-map/index.js index 9ea8f4c8..c5684056 100644 --- a/src/components/poi-map/index.js +++ b/src/components/poi-map/index.js @@ -147,7 +147,6 @@ const POIMap = ({ const [showClusters, setShowClusters] = useState(false) const [clusterZoom, setClusterZoom] = useState(false) // used to block reset of view state when we transition from the cluster to the icon layer - const [clusterClick, setClusterClick] = useState(false) const [layerVisibleData, setLayerVisibleData] = useState() const mapContainerRef = useRef() const deckRef = useRef() @@ -307,7 +306,6 @@ const POIMap = ({ * @param { array } param.coordinate - coordinates of the clicked object */ const onClick = useCallback(({ object, layer, coordinate }) => { - setClusterClick(mapLayers.includes('POICluster')) // if clicked object is a cluster, zoom in if (object?.cluster) { const [longitude, latitude] = coordinate @@ -322,7 +320,7 @@ const POIMap = ({ // custom onClick onClickHandle({ object, layer, coordinate }, setOnClickPayload) } - }, [mapLayers, setActivePOI, onClickHandle, height, width]) + }, [setActivePOI, onClickHandle, height, width]) /** * onHover - React hook that handles onHover event @@ -366,13 +364,11 @@ const POIMap = ({ // FIX: FlyToInterpolator doesn't seem to be trigerred when transitioning from empty map to some data // React Hook to handle setting up viewState based on POIs coordinates and deck map container size useLayoutEffect(() => { - if (((data?.length && mapLayers.length) || - (mapMode === 'emptyMap' && !data?.length && !mapLayers.length)) && - width && height && !clusterClick) { + if (((mapMode === 'emptyMap' && !data?.length) || data?.length) && + viewParam && mapMode && width && height) { viewStateDispatch(viewParam[mapMode]) } - setClusterClick(false) - }, [data, mapLayers, width, height, viewParam, mapMode, clusterClick]) + }, [data, width, height, viewParam, mapMode]) // React Hook to update viewState for onClick events useEffect(() => { From ef9105309d9a7b51707304fc050bf34ea3ec1848 Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Thu, 30 Sep 2021 17:57:44 -0400 Subject: [PATCH 23/24] POIMap/poi-cluster - send props directly from map to cluster layer as there was a delay in the POICluster of calc zoom and we had cluster icons changing quick between 2 zooms; set transitionDuration to 2 sec; remove optional chain for visiblePOI in isClusterZoomLevel --- src/components/layers/poi-cluster.js | 4 ++-- src/components/poi-map/index.js | 17 +++++++++++++++-- src/components/poi-map/utils.js | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/components/layers/poi-cluster.js b/src/components/layers/poi-cluster.js index 5624afdb..25e6421f 100644 --- a/src/components/layers/poi-cluster.js +++ b/src/components/layers/poi-cluster.js @@ -62,7 +62,7 @@ class IconClusterLayer extends CompositeLayer { if (rebuildIndex) { const index = new Supercluster({ maxZoom: props.superclusterZoom, - radius: props.getSuperclusterRadius(this.context.viewport.zoom), + radius: props.getSuperclusterRadius(this.props.zoom), }) index.load( props.data.map(d => ({ @@ -73,7 +73,7 @@ class IconClusterLayer extends CompositeLayer { this.setState({ index }) } - const z = Math.floor(this.context.viewport.zoom) + const z = Math.floor(this.props.zoom) if (rebuildIndex || z !== this.state.z) { this.setState({ data: this.state.index.getClusters([-180, -85, 180, 85], z), diff --git a/src/components/poi-map/index.js b/src/components/poi-map/index.js index c5684056..2cb69178 100644 --- a/src/components/poi-map/index.js +++ b/src/components/poi-map/index.js @@ -85,7 +85,7 @@ const MapContainer = styled('div', forwardRef)` const INIT_VIEW_STATE = { pitch: 25, bearing: 0, - transitionDuration: 3000, + transitionDuration: 2000, transitionInterpolator: new FlyToInterpolator(), latitude: 52, longitude: -100, @@ -450,11 +450,24 @@ const POIMap = ({ onHover, mode, POIType, + zoom, selectedFeatureIndexes, } }) } return [] - }, [mapLayers, layerPool, mapProps, data, updatePOI, onClick, onHover, mode, POIType, selectedFeatureIndexes]) + }, [ + mapLayers, + layerPool, + mapProps, + data, + updatePOI, + onClick, + onHover, + mode, + POIType, + zoom, + selectedFeatureIndexes, + ]) const getCurrentCursor = getCursor({ layers }) diff --git a/src/components/poi-map/utils.js b/src/components/poi-map/utils.js index 0b89530b..4918afb5 100644 --- a/src/components/poi-map/utils.js +++ b/src/components/poi-map/utils.js @@ -46,7 +46,7 @@ export const isClusterZoomLevel = ({ layerVisibleData, viewportBBOX, zoom }) => return elem.objects ? [...agg, ...elem.objects] : [...agg, elem.object] }, []) - if (visiblePOIs?.length) { + if (visiblePOIs.length) { const getPosition = d => d.geometry.coordinates const index = new Supercluster({ maxZoom: SUPERCLUSTER_ZOOM, From 73a2aabb3d8be050af2c95199fe50c0c74a3470e Mon Sep 17 00:00:00 2001 From: Erika Szabo Date: Fri, 1 Oct 2021 15:41:13 -0400 Subject: [PATCH 24/24] package - change version to v0.7.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a593246a..c8ed9639 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@eqworks/react-maps", - "version": "0.7.2-alpha.6", + "version": "0.7.2", "description": "React maps", "author": "EQ Inc.", "license": "UNLICENSED",