I work on a React app with a Google Maps component (using the awesome react-google-maps package). The map displays a bunch of real-time data, and it is important that the marker icons are dynamic. Unfortunately, Google Maps doesn’t make it easy. The marker object expects an image, not a dynamic React component, so I needed a workaround to get the marker icons to reflect the changing data.
The map marker accepts an image as a parameter, typically a path to a raster image. To be dynamic, it needed to be a SVG image, but it didn’t seem like that was an option. However, my coworker then told me to look into data URIs. After some research, I learned that I could use data URIs to ‘trick’ the map marker into accepting an SVG.
A data URI is a string that defines an image in a specified format. The format is specified right in the string. The string looks something like this:
data:image/svg;base64,REQFUfju93$T…
From CSS Tricks, the format of the string should be:
data:[<mime type>][;charset=<charset>][;base64],<encoded data>
You can use any type of data encoding, or none. A simple SVG data URI could be defined:
data:image/svg+xml;utf8,<svg><rect stroke='black' fill='black' width='50' height='25'/></svg>
It’s that simple! Data URIs are awesome for a lot of reasons, one being that they can make displaying images a lot faster, because the page doesn’t have to make so many HTTP requests. Instead, the image is just defined in code.
For my purpose, I needed the image to be in the form of a string, so this seemed like a perfect solution. However, I still needed a way to convert a React SVG node into a string. Luckily, React provides an easy function to convert a React component into a string. Actually, they provide two: One called renderToString
, which returns the HTML that React would create from that component, and another called renderToStaticMarkup
, which does the same, but without all the extra React-specific attributes. I didn’t want any extra data-attributes, so I used renderToStaticMarkup.
From there, it’s pretty simple to define a dynamic SVG, run it through the renderToStaticMarkup
function, and create the data URI string. If you want, you could also encode that string, but don’t forget to specify which encoding you used in the URI.
The marker component ends up looking like this:
<Marker icon={"data:image/svg+xml;utf8,<svg><rect stroke='black' fill='black' width='50' height='25'/></svg>"} />
One other issue that I ran into is forgetting to add xmlns=http://www.w3.org/2000/svg
to the SVG. Usually this attribute isn’t necessary to display an SVG in an HTML5 document, but when serving the image as a data URI, it still is. Don’t forget!
I’m still pretty new with SVGs, so if I got something wrong, let me know! I’d love the feedback. It’s taken me a little while to get used to them, but I am having lots of fun figuring them out.
If you are interested, here is a CodePen of the SVG icon I was working on. And here is an article about data URIs. And here’s an article about SVG data URIs.
Thanks for reading!
Top comments (0)