Difficulty recreating heatmap renderer with time slider in ArcGIS JS API

12-26-2020 08:47 PM
New Contributor III

The Goal

I am trying to recreate what I created in ArcGIS online using the ArcGIS JS API.  I have this webmap which uses a heatmap to visualize COVID numbers by country, with a time slider, as this is a time aware layer:


I love the distribution of colors from the low end to the high end, and how it evolves over time.

What I've Tried

I am trying to code this from scratch using the api.  I'm having a hard time.  In order to get the map to show the right data according to the current timeslider timeextent, I followed the advice from this GIS stack exhange question , and the layer's definitionExpression is updated with each timeslider change:



timeSlider.watch('timeExtent', function (value) {

function updateDefintionExpression(timeExtent) {
	const start = toDateString(timeExtent.start);
	const end = toDateString(timeExtent.end);
	covidLayer.definitionExpression = `Date >= DATE '${start}' AND Date <= DATE '${end}'`;



I came up with a heatmap renderer from scratch, but it doesn't show off the low end as well as I'd like.  Here is the renderer code:



renderer: {
			type: 'heatmap',
			field: 'Confirmed',
			colorStops: [
				{ ratio: 0, color: 'rgba(255, 255, 255, 0)' },
				{ ratio: 0.06, color: 'rgba(255, 255, 255, 1)' },
				{ ratio: 0.15, color: 'rgba(255, 255, 0, 1)' },
				{ ratio: 0.25, color: 'rgba(255, 140, 0, 1)' },
				{ ratio: 0.55, color: 'rgba(255, 0, 0, 1)' },
			minPixelIntensity: 1,
			maxPixelIntensity: 150000000,
			blurRadius: 12,



You can see this in action here: https://codepen.io/slutske22/pen/poEdqEz

I played endlessly with the stops and the pixelIntensities, and I couldn't get a good range across the low end and high end (low numbers in the data vs high numbers in the data).

I looked into the JSON for the arcgis webmap I initially cereated, and this is the renderer it shows:



renderer: {
      type: "heatmap",
      blurRadius: 10,
      colorStops: [
          ratio: 0,
          color: [212, 227, 245, 0]
          ratio: 0.01,
          color: [212, 227, 245, 0]
        // ... more color stops
          ratio: 0.9175000000000001,
          color: [204, 211, 51, 255]
          ratio: 1,
          color: [255, 255, 0, 255]
      maxPixelIntensity: 9566880,
      minPixelIntensity: 0,
      field: "Confirmed"


Using that, I get this result: https://codepen.io/slutske22/pen/eYdebdp

Also not quite right - the low end looks nice, but the high end looks blown out, like the heatmap is overflowing against an invisible square border.  Take a look - here is my goal:

Screen Shot 2020-12-26 at 9.10.04 PM.png

But here is what I'm getting with the JS API:

Screen Shot 2020-12-26 at 9.10.00 PM.png

I'm not sure why in my handcoded app, the heatmap looks "cut off"...if I can fix this, then the renderer from JSON will probably work just fine.  (And how to get that nice fade-out effect?)


I also tried using the smartmapping heatmap renderer:


  timeSlider.watch("timeExtent", function (value) {

    const params = {
       layer: covidLayer,
       field: "Confirmed",
       fadeToTransparent: true,
       minRatio: 0.05

    .then(result => {
       covidLayer.renderer = result.renderer



You can see the result here: https://codepen.io/slutske22/pen/VwKrqKr

This is also not correct.  This seems to re-evaluate the total range of values on each timeslider update, and distribute the heatmap accordingly, making each timestep look very similar.


How can I achieve the effect that I have in the arcgis online web map, using the JS API?  I feel I am close but struggling to see the right way.

0 Replies