mirror of
https://github.com/DOI-DO/j40-cejst-2.git
synced 2025-02-22 09:41:26 -08:00
Attempt to add map bounds
- Basic animation (standard ball bounce) was placed on the parent of the map - A state MapBoundReached tracks which bound (N, S, W or E) was reached - This state variable was then used to conditionally apply the CSS animation - How could we detect the end of the animation to remove it from the DOM after the animation played once? - try and add an eventListener on the parent of the map using ref and useEffect ❌ - try and use the onAnimationEnd prop the territory shortcuts seem to trigger this animationEnd event ❌ - try and differentiate between territory shortcut animation and map bound animation using use isPanning ❌ - use isDragging ✅ - Now that the animation end event is being detected properly and its not interfering with the territory shortcuts, moving back to - Getting the bounds to work for all directions (N, S, W, E) - clunky feel and can’t get it to trigger accurately - Making the animation feel real (right not it’s just a random bounce) - Decided to attempt to use the transition built-into the ReactMapGL API, this was also not leading to reliable results.
This commit is contained in:
parent
f5f4330919
commit
38ab640f4e
4 changed files with 168 additions and 10 deletions
|
@ -1,6 +1,16 @@
|
||||||
@use '../styles/design-system.scss' as *;
|
@use '../styles/design-system.scss' as *;
|
||||||
@import "./utils.scss";
|
@import "./utils.scss";
|
||||||
|
|
||||||
|
.scrollDownBounce {
|
||||||
|
animation: bounce2 2s ease 1;
|
||||||
|
clip-path: inset(30px 0 0 0);
|
||||||
|
|
||||||
|
@keyframes bounce2 {
|
||||||
|
0%, 20%, 50%, 80%, 100% {transform: translateY(0);}
|
||||||
|
40% {transform: translateY(-30px);}
|
||||||
|
60% {transform: translateY(-15px);}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.j40Map {
|
.j40Map {
|
||||||
// width < 1024
|
// width < 1024
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
declare namespace J40MapModuleScssNamespace {
|
declare namespace J40MapModuleScssNamespace {
|
||||||
export interface IJ40MapModuleScss {
|
export interface IJ40MapModuleScss {
|
||||||
|
scrollDownBounce: string;
|
||||||
|
|
||||||
// main J40 map style
|
// main J40 map style
|
||||||
j40Map: string;
|
j40Map: string;
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,8 @@ import ReactMapGL, {
|
||||||
Popup,
|
Popup,
|
||||||
FlyToInterpolator,
|
FlyToInterpolator,
|
||||||
FullscreenControl,
|
FullscreenControl,
|
||||||
MapRef} from 'react-map-gl';
|
MapRef,
|
||||||
|
LinearInterpolator} from 'react-map-gl';
|
||||||
import {useIntl} from 'gatsby-plugin-intl';
|
import {useIntl} from 'gatsby-plugin-intl';
|
||||||
import bbox from '@turf/bbox';
|
import bbox from '@turf/bbox';
|
||||||
import * as d3 from 'd3-ease';
|
import * as d3 from 'd3-ease';
|
||||||
|
@ -58,6 +59,8 @@ export interface IDetailViewInterface {
|
||||||
properties: constants.J40Properties,
|
properties: constants.J40Properties,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type MapBoundaryReached = 'top' | 'right' | 'bottom' | 'left' | '';
|
||||||
|
|
||||||
const J40Map = ({location}: IJ40Interface) => {
|
const J40Map = ({location}: IJ40Interface) => {
|
||||||
/**
|
/**
|
||||||
* Initializes the zoom, and the map's center point (lat, lng) via the URL hash #{z}/{lat}/{long}
|
* Initializes the zoom, and the map's center point (lat, lng) via the URL hash #{z}/{lat}/{long}
|
||||||
|
@ -81,6 +84,10 @@ const J40Map = ({location}: IJ40Interface) => {
|
||||||
zoom: zoom && parseFloat(zoom) ? parseFloat(zoom) : constants.GLOBAL_MIN_ZOOM,
|
zoom: zoom && parseFloat(zoom) ? parseFloat(zoom) : constants.GLOBAL_MIN_ZOOM,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map selection state variables:
|
||||||
|
*/
|
||||||
const [selectedFeature, setSelectedFeature] = useState<MapboxGeoJSONFeature>();
|
const [selectedFeature, setSelectedFeature] = useState<MapboxGeoJSONFeature>();
|
||||||
const [detailViewData, setDetailViewData] = useState<IDetailViewInterface>();
|
const [detailViewData, setDetailViewData] = useState<IDetailViewInterface>();
|
||||||
const [transitionInProgress, setTransitionInProgress] = useState<boolean>(false);
|
const [transitionInProgress, setTransitionInProgress] = useState<boolean>(false);
|
||||||
|
@ -88,6 +95,28 @@ const J40Map = ({location}: IJ40Interface) => {
|
||||||
const [isMobileMapState, setIsMobileMapState] = useState<boolean>(false);
|
const [isMobileMapState, setIsMobileMapState] = useState<boolean>(false);
|
||||||
const [censusSelected, setCensusSelected] = useState<boolean>(true);
|
const [censusSelected, setCensusSelected] = useState<boolean>(true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map Boundary reached state variables:
|
||||||
|
*/
|
||||||
|
// const mapContainerRef = useRef(null);
|
||||||
|
// const [mapBoundaryReached, setMapBoundaryReached] = useState<MapBoundaryReached>('');
|
||||||
|
const [isMapBeingDragged, setIsMapBeingDragged] = useState<boolean>(false);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// const onAnimationEnd = () => {
|
||||||
|
// setMapBoundaryReached('');
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const mapContainer = mapContainerRef.current;
|
||||||
|
|
||||||
|
// mapContainer.addEventListener('animationend', onAnimationEnd);
|
||||||
|
|
||||||
|
// return () => {
|
||||||
|
// mapContainer.removeEventListener('animationend', onAnimationEnd);
|
||||||
|
// };
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
|
||||||
// In order to detect that the layer has been toggled (between census and tribal),
|
// In order to detect that the layer has been toggled (between census and tribal),
|
||||||
// this state variable will hold that information
|
// this state variable will hold that information
|
||||||
const [layerToggled, setLayerToggled] = useState<boolean>(false);
|
const [layerToggled, setLayerToggled] = useState<boolean>(false);
|
||||||
|
@ -324,11 +353,67 @@ const J40Map = ({location}: IJ40Interface) => {
|
||||||
setGeolocationInProgress(true);
|
setGeolocationInProgress(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function will set the map boundaries during the dragging of the map. If a user attempts to
|
||||||
|
* drag the map past the boundaries, an animation will play to mimic the end of the end has been
|
||||||
|
* reached.
|
||||||
|
*
|
||||||
|
* @param {ViewportProps} viewState
|
||||||
|
* @return {} setViewport
|
||||||
|
*/
|
||||||
|
const onViewportChange = (viewState:ViewportProps) => {
|
||||||
|
// console.log('🚀 ~ file: J40Map.tsx ~ line 355 ~ onViewportChange ~ viewState', viewState);
|
||||||
|
let mapBoundaryReached:MapBoundaryReached = '';
|
||||||
|
|
||||||
|
if (isMapBeingDragged) {
|
||||||
|
if (
|
||||||
|
viewState.longitude &&
|
||||||
|
viewState.longitude > constants.MAP_BOUND_MIN_LONGITUDE &&
|
||||||
|
viewState.longitude < 180 ) {
|
||||||
|
viewState.longitude = constants.MAP_BOUND_MIN_LONGITUDE;
|
||||||
|
mapBoundaryReached= 'left';
|
||||||
|
} else if ( viewState.longitude && viewState.longitude > constants.MAP_BOUND_MAX_LONGITUDE ) {
|
||||||
|
viewState.longitude = constants.MAP_BOUND_MAX_LONGITUDE;
|
||||||
|
mapBoundaryReached= 'right';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( viewState.latitude && viewState.latitude < constants.MAP_BOUND_MIN_LATITUDE ) {
|
||||||
|
mapBoundaryReached= 'bottom';
|
||||||
|
viewState.latitude = constants.MAP_BOUND_MIN_LATITUDE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( viewState.latitude && viewState.latitude > constants.MAP_BOUND_MAX_LATITUDE ) {
|
||||||
|
viewState.latitude = constants.MAP_BOUND_MAX_LATITUDE;
|
||||||
|
mapBoundaryReached= 'bottom';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapBoundaryReached ? setViewport({
|
||||||
|
...viewState,
|
||||||
|
transitionDuration: 1000,
|
||||||
|
transitionInterpolator: new LinearInterpolator(),
|
||||||
|
transitionEasing: d3.easeBounce,
|
||||||
|
}) : setViewport(viewState);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set mapbox base layer:
|
||||||
const mapBoxBaseLayer = 'tl' in flags ? `mapbox://styles/justice40/cl2qimpi2000014qeb1egpox8` : `mapbox://styles/justice40/cl5mp95tu000k14lpl21spgny`;
|
const mapBoxBaseLayer = 'tl' in flags ? `mapbox://styles/justice40/cl2qimpi2000014qeb1egpox8` : `mapbox://styles/justice40/cl5mp95tu000k14lpl21spgny`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Grid desktop={{col: 9}} className={styles.j40Map}>
|
<Grid
|
||||||
|
desktop={{col: 9}}
|
||||||
|
// className={mapBoundaryReached === 'bottom' ?
|
||||||
|
// `${styles.j40Map} ${styles.scrollDownBounce}` :
|
||||||
|
// styles.j40Map}
|
||||||
|
className={styles.j40Map}
|
||||||
|
// onAnimationEnd={(e) => {
|
||||||
|
// // Todo: Document how both animation types will trigger this callback
|
||||||
|
// // console.log('🚀 ~ file: J40Map.tsx ~ line 394 ~ J40Map ~ e', e);
|
||||||
|
// console.log('animation ended');
|
||||||
|
// setMapBoundaryReached('');
|
||||||
|
// }}
|
||||||
|
>
|
||||||
{/**
|
{/**
|
||||||
* Note:
|
* Note:
|
||||||
* The MapSearch component is no longer used in this location. It has been moved inside the
|
* The MapSearch component is no longer used in this location. It has been moved inside the
|
||||||
|
@ -361,8 +446,10 @@ const J40Map = ({location}: IJ40Interface) => {
|
||||||
process.env.MAPBOX_STYLES_READ_TOKEN ?
|
process.env.MAPBOX_STYLES_READ_TOKEN ?
|
||||||
process.env.MAPBOX_STYLES_READ_TOKEN : ''}
|
process.env.MAPBOX_STYLES_READ_TOKEN : ''}
|
||||||
|
|
||||||
// ****** Map state props: ******
|
/**
|
||||||
// http://visgl.github.io/react-map-gl/docs/api-reference/interactive-map#map-state
|
* ****** Map state props: ******
|
||||||
|
* https://github.com/visgl/react-map-gl/blob/6.1-release/docs/api-reference/interactive-map.md#map-state
|
||||||
|
*/
|
||||||
{...viewport}
|
{...viewport}
|
||||||
mapStyle={process.env.MAPBOX_STYLES_READ_TOKEN ? mapBoxBaseLayer : getOSBaseMap(censusSelected)}
|
mapStyle={process.env.MAPBOX_STYLES_READ_TOKEN ? mapBoxBaseLayer : getOSBaseMap(censusSelected)}
|
||||||
width="100%"
|
width="100%"
|
||||||
|
@ -371,9 +458,10 @@ const J40Map = ({location}: IJ40Interface) => {
|
||||||
height="100%"
|
height="100%"
|
||||||
mapOptions={{hash: true}}
|
mapOptions={{hash: true}}
|
||||||
|
|
||||||
|
/**
|
||||||
// ****** Interaction option props: ******
|
* ****** Interaction options: ******
|
||||||
// http://visgl.github.io/react-map-gl/docs/api-reference/interactive-map#interaction-options
|
* https://github.com/visgl/react-map-gl/blob/6.1-release/docs/api-reference/interactive-map.md#interaction-options
|
||||||
|
*/
|
||||||
maxZoom={constants.GLOBAL_MAX_ZOOM}
|
maxZoom={constants.GLOBAL_MAX_ZOOM}
|
||||||
minZoom={constants.GLOBAL_MIN_ZOOM}
|
minZoom={constants.GLOBAL_MIN_ZOOM}
|
||||||
dragRotate={false}
|
dragRotate={false}
|
||||||
|
@ -389,10 +477,17 @@ const J40Map = ({location}: IJ40Interface) => {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ****** Callback props: ******
|
||||||
|
* https://github.com/visgl/react-map-gl/blob/6.1-release/docs/api-reference/interactive-map.md#callbacks
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
onViewportChange={(viewState: ViewportProps) => onViewportChange(viewState)}
|
||||||
|
|
||||||
// ****** Callback props: ******
|
// Detect and set the state variable is map is dragging
|
||||||
// http://visgl.github.io/react-map-gl/docs/api-reference/interactive-map#callbacks
|
onInteractionStateChange={(interactionState: { isDragging: boolean; }) => {
|
||||||
onViewportChange={setViewport}
|
interactionState.isDragging ? setIsMapBeingDragged(true) : setIsMapBeingDragged(false);
|
||||||
|
}}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onLoad={onLoad}
|
onLoad={onLoad}
|
||||||
onTransitionStart={onTransitionStart}
|
onTransitionStart={onTransitionStart}
|
||||||
|
|
|
@ -301,6 +301,57 @@ export const SELECTED_FEATURE_BORDER_WIDTH = 5.0;
|
||||||
export const ALAKSA_POINTS_STROKE_WIDTH = 1.0;
|
export const ALAKSA_POINTS_STROKE_WIDTH = 1.0;
|
||||||
|
|
||||||
// Bounds - these bounds can be obtained by using the getCurrentMapBoundingBox() function in the map
|
// Bounds - these bounds can be obtained by using the getCurrentMapBoundingBox() function in the map
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ### Grab the lat/lon for the bounds of the map ###
|
||||||
|
*
|
||||||
|
* Alaska's coordinates:
|
||||||
|
* - latitude: 63.27827735223102
|
||||||
|
* - longitude: -162.3947525
|
||||||
|
*
|
||||||
|
* Hawaii's coordinates:
|
||||||
|
* - latitude: 20.657020350316177
|
||||||
|
* - longitude: -157.696737
|
||||||
|
*
|
||||||
|
* Mariana Islands coordinates:
|
||||||
|
* - latitude: 16.900917105280538
|
||||||
|
* - longitude: 145.47207349999974
|
||||||
|
*
|
||||||
|
* Guam's coordinates:
|
||||||
|
* - latitude: 14.366555855360668
|
||||||
|
* - longitude: 144.85327381019735
|
||||||
|
*
|
||||||
|
* USVI's coordinates:
|
||||||
|
* - latitude: 18.2017745170224
|
||||||
|
* - longitude: -64.77448172638938
|
||||||
|
*
|
||||||
|
* Maine's coordinates:
|
||||||
|
* - latitude: 42.52750243984539
|
||||||
|
* - longitude: -72.05693075466074
|
||||||
|
*
|
||||||
|
* ### Group the above by Lat/Lon ###
|
||||||
|
*
|
||||||
|
* - latitude: 63.27827735223102
|
||||||
|
* - latitude: 20.657020350316177
|
||||||
|
* - latitude: 16.900917105280538
|
||||||
|
* - latitude: 14.366555855360668
|
||||||
|
* - latitude: 18.2017745170224
|
||||||
|
* - latitude: 42.52750243984539
|
||||||
|
*
|
||||||
|
* - longitude: -162.3947525
|
||||||
|
* - longitude: -157.696737
|
||||||
|
* - longitude: 145.47207349999974
|
||||||
|
* - longitude: 144.85327381019735
|
||||||
|
* - longitude: -64.77448172638938
|
||||||
|
* - longitude: -72.05693075466074
|
||||||
|
*
|
||||||
|
* Set min/max lat/lon:
|
||||||
|
*/
|
||||||
|
export const MAP_BOUND_MIN_LATITUDE = 13;
|
||||||
|
export const MAP_BOUND_MAX_LATITUDE = 65;
|
||||||
|
export const MAP_BOUND_MIN_LONGITUDE = 150;
|
||||||
|
export const MAP_BOUND_MAX_LONGITUDE = -65;
|
||||||
|
|
||||||
export const GLOBAL_MAX_BOUNDS: LngLatBoundsLike = [
|
export const GLOBAL_MAX_BOUNDS: LngLatBoundsLike = [
|
||||||
[-180.118306, 5.499550],
|
[-180.118306, 5.499550],
|
||||||
[-65.0, 83.162102],
|
[-65.0, 83.162102],
|
||||||
|
|
Loading…
Add table
Reference in a new issue