ArcGIS Blog

Mapping

ArcGIS Maps SDK for JavaScript

How to create a sparkline map with the ArcGIS API for JavaScript

By John Nelson and Jinnan Zhang

Witten with Jinnan Zhang

CovidPulse presents a massive amount of data as a simple collection of wiggly local coronavirus trends. More recently, this symbology was used to visualize unemployment trends in UnemploymentPulse.

Local unemployment rates normalized by the national rate.

The sparkline symbol has many uses beyond this one, for sure, so we’ll share the steps taken to render the Johns Hopkins US County cases data as this interesting and data-dense visual mechanism. We hope that this will be a helpful resource for creating applications of your own with data of your own.

Here is how to render data as a sparkline in ArcGIS API for JavaScript. Specifically, we’ll be pouring sparklines into the CIMSymbol. Prepare yourself emotionally for a lot of links and snippets. But first, warm up the reverse-engineering part of your brain by disassembling and then reassembling the nearest handy Lego creation. Jinnan and I will wait. Ok, ready?

The CIMSymbol

Yes, the humble, unassuming, CIM. Never heard of it? It’s heard of you. CIM stands for Cartographic Information Model. That alone should give you shivers. But what is it?

The Cartographic Information Model is an energy field created by all living things. It surrounds us and penetrates us; it binds the galaxy together.

Originating as the model that accommodates ArcGIS Pro’s advanced symbology capabilities, the CIM is an open spec used for all sorts of mapping. It has recently been brought into the ArcGIS API for JavaScript to support mapping there.

Let’s start with this code snippet blatantly stolen from the generous CIMSymbol section of the JSAPI Doc. It shows an example of creating a triangle marker comprised of a CIMPointSymbol (a point symbol used to draw point features/graphics) containing a CIMVectorMarker (a vector marker which can represent vector graphics)…

Here’s a snapshot if you want to give your mental compiler a rest and just, like, see it.

You can try it for yourself here, if you like.

Drawing Lines in a CIMSymbol

Now let’s turn that triangle into something a bit more sparkliney. We’ll tweak the code snippet above to show a polyline instead of polygon. It only takes a couple simple changes to the CIMMarkerGraphic; we can leave everything else the same. Instead of “rings” in the geometry, we’ll use “paths.” And we’ll change the symbol type from CIMPolygonSymbol to CIMLineSymbol.

Like so…

Alright, a line instead of a triangle. Here’s a codepen sandbox of you want to kick it around.

You have taken your first step into a larger world.

Formatting, and Fitting, a Custom Line

But how can we use it to plot our own data? Good question. Let’s further modify the code snippet, this time we’ll use a slightly more complex set of numbers representing some pretend data values:

5, 40, 15, 25, 10.

First, we’ll update the frame property with our new data in mind. for the sake of simplicity, we’ll just set the xmin and ymin to 0 for now. The maximum value in our data range is 40, so that can be the frame’s new ymax. We’ll also set the xmax to 40, which means we’re working in a 40×40 square frame —a little Cartesian coordinate space for the line geometry to live in.

The size property is the actual height into which the frame gets squeezed (or stretched, or whatever). Width is proportional.

 

Next we just create the path array with our data set up as coordinates. We’ll stick the data values in at the Y value and distribute the X values evenly across our 40 pixel frame. The API allows you to have multiple paths, but we only need one array of points for our sparkline paths.

Look, a sparkline!

Check it out in the codepen editor. Play around with the size, frame, and data values to get a sense for the pushing and pulling that it does to the rendering. There’s a few moving parts and you might at first feel like Peter Griffin struggling to open the blinds, but hang in there.

Dynamic Sparkline Data

Now let’s see how we can feed this suspiciously sparkline-like thing actual dynamic data. We’ll draw a sparkline for Los Angeles County representing “Total Confirmed Cases.”

We can get the Covid-19 timeseries data for each US County from this Feature Layer. And here is an example query to fetch all features for Los Angeles county from this feature layer.

After fetching all the features, we will loop through them and get the value we want to visualize from each feature and save them into a new array (like the array of numbers we made manually in the previous example).

Now we have a long list of numbers corresponding to confirmed coronavirus cases in Los Angeles County. But this data has many more numbers than we were dealing with in the fake data example, so we need a better way to find the max number from this list instead of picking it manually. Here’s a little doodad that does that for us…

Construct the path coordinates, just like in the sample above, and you get an honest to goodness sparkline.

Play with it here in this codepen sample.

If you are interested in creating a version of CovidPulse for your area, the full code is available here on GitHub: https://github.com/vannizhang/covid19-trend-map

Hopefully this is sufficient to get you going on using CIMSymbols to render sparkline maps. There are so many applications for sparklines to represent time series data as compact distilled visualizations of a dynamic geographic phenomenon. We’re excited to see the maps of time and space that you make.

Visit CovidPulse for an ongoing visualization of the pandemic and this video describing it and sparklines.

Map Well! Jinnan and John

Share this article

Subscribe
Notify of
1 Comment
Oldest
Newest
Inline Feedbacks
View all comments
Rohit Venkat Gandhi Mendadhala(@rohit-mendadhala_tfsgis)
October 1, 2020 9:49 am

Can you help us understand what are the variables ‘ses_iam_sk’ and ‘ses_iam_ak’ in your script? Are these the username and password for the email? I am guessing these to be simple email service access key and secret key from AWS? Wondering how we can use them in Azure platform. Thank you

Taylor Teske(@tteske)
October 9, 2020 6:07 am

Hey Rohit, that is correct. Those are the SES access and secret keys from AWS. Azure does not provide a SES and requires third-party solutions, like Twilio’s SendGrid: https://docs.microsoft.com/en-us/azure/architecture/aws-professional/messaging.

Ahjung Kim(@ahjung-kimstantec-com_stantec)
October 9, 2020 5:54 am

@Taylor Teske This is very helpful – thank you so much for posting this. Any chance we can find a repository for your sample code used in this article? That would help out beginners like myself greatly.

Taylor Teske(@tteske)
October 9, 2020 6:10 am
Reply to  Ahjung Kim

Hey Ahjung, I don’t have anything in GitHub currently, but that is certainly a great idea! When I get some time, I’ll try to get something in GitHub. The first example was developed from a script for a customer, so I may need to modify it a bit.

Taylor Teske(@tteske)
October 15, 2020 5:30 am
Reply to  Taylor Teske

Hey Ahjung, the following repo includes the sample code: https://github.com/tatornator12/Azure-Functions-ArcGIS-Examples. As mentioned, I had to remove most of the Timer Trigger code.

Julian Inskip(@jxi-2)
June 4, 2022 12:58 pm

Hi Taylor. Is it possible to get the payload coming from the Survey123 entry? I would like to access the information being submitted in the form within my python Azure Function.

Thanks, Julian

Daniel Mallett(@dmallett)
September 26, 2022 1:15 pm

i can’t seem to post a link here in the comments but if you are having issues publishing see community.esri.com and search for suddenly can’t build and deploy python azure