react-simple-maps
react-simple-maps copied to clipboard
animating map markers with stagger/delay so they don't render at the same time?
Hello again community! I really love react-simple-maps, but I've been hitting a wall for a few days now! I have another issue (marked as solved), but have a work project to make an interactive map to show a marker everytime makes a booking with our software. To make it more interesting, we want to show the location of the customer who made the booking as a separate marker, with a line connecting to our client (you can see how I did this here: https://github.com/zcreativelabs/react-simple-maps/issues/115)
So the issue - not a bad problem to have - is that our booking software is very popular, and we have a booking almost every second! The plan is to run a report every 15 minutes, which will pass in data for several hundred bookings - all of which render at the same time! The map will be VERY cluttered with lines and markers if we don't stagger them somehow.
So, using the .map method to render your markers, per the docs:
Has anyone found a way add a delay or timer here?
To get the best control, a javascript animation library is my top choice. GSAP in particular has excellent timeline features for animations, but does not want to be friends with the marker components!
- Notice inside the Marker this line of code --> ref={this.clientRef} which you will define in your constructor:
constructor(props) { super(props); this.clientRef = React.createRef(); ...
Per the React documentation, createRef is the latest way to create a reference to a DOM node...however, it is not finding the true DOM node due to use of a 3rd party component library like react-simple-maps to generate the marker component? (https://reactjs.org/docs/refs-and-the-dom.html)
- Meanwhile, other animation libraries like react-motion, or helper libraries like react-transition-group want you to put your mapped elements or components into some kind of wrapper such as:
and I've also tried <StaggeredMotion> from the react-motion library. Wrapping the marker component inside another component causes the map to break, giving a 'projection is not a function' error. From what I can tell, adding any sort of
Any help is appreciated! My backup plan, which I'm hoping to avoid, is to rebuild the map in vanilla D3-geo so I can create and control the components and DOM nodes directly! Any ideas or other experimentation, let me know!
Hi @Unionindesign,
There is a problem currently with the way markers are handled by react-simple-maps. I made an example codesandbox with staggered custom markers using react-pose for the animation. To get around the projection issue, you can pass a custom projection to ComposableMap
and then use that projection on any circle
or g
inside of ZoomableGroup
.
Hope this helps...
A quick update - I do have the Greensock animation platform (GSAP) up and running! A few bugs to sort out since I did use the react-motion example for zoom and panning on the map, and the two are not working together at the moment...
Good news! While the createRefs API (see the link above) sounds like your only option (At the moment) for a 3rd party component library where the creator does not expose the DOM node, react-simple-maps does give you a
To update this post, I've unfortunately hit another roadblock :-( While working with a set of test data, my approach listed above was doing just fine for several weeks! This worked - only because the data was static and hardcoded into the app. As we move toward a production build and we're querying our database(s), fetching the data and converting it to json, this is once again breaking the animations. I believe this is a 'best-practice' issue of fetching data in a container component using the componentDidMount method, and then passing it down as props to its children...meanwhile in the child component where the map and markers live, I am also calling the animations inside componentDidMount...no animations? Seems like the map and markers have already rendered, and I haven't found a way to trigger a re-render?
I've attempted to recreate the codesandbox above but find myself stumbling through D3 tutorials - the geoAlbers projection (especially the one with counties as well as states) does not plugin so easily! I've created a custom topojson file but still getting it in the map...but once that renders my data is ready to go, animations are there, and I should be able to connect GSAP again using react transition group? Fingers crossed! Any support or ideas are much appreciated!
Without revealing too much company code :-) here,s a few snippets. In particular I was getting an error that the geoAlbers projection was not being exported from d3-geo-projection, so I imported from D3 geo...not sure if that's the issue? Here is that section of code:
`import { geoAlbers } from "d3-geo"; //import { geoAlbers } from "d3-geo-projection";
const geoPaths = "../../../data/statesAndCountiesUSA.json"; const width = 1280; const height = 700; const customProjection = () => geoAlbers() .translate([width / 2, height / 2]) .scale(1280); `
And then further down the page...
<ComposableMap //width={1440} //height={700} projection={customProjection} projectionConfig={{ scale: 1440 }} style={mapStyles}> <ZoomableGroup center={[x, y]} zoom={zoom}> <Graticule /> <Geographies geography={geoPaths}> {(geos, proj) => geos.map( (geo, i) => console.log(geo) || ( <Geography key={geo.id + i} cacheId={geo.properties.ID_1} geography={geo} projection={proj} style={{ default: { fill: "#E5F1FC", .....etc
Thank you! Love this library! Very disappointed to lose my animations at this late stage :-(