Autumn ๐Ÿ‚

3 min read

#30DayMapChallenge Day 2. Lines

Autumn – coloring streams by their flow order in QGIS ๐Ÿ‚

lines

Here’s one of the maps I have made for the #30DayMapChallenge on Twitter in 2021. You can find out more about the challenge and my other maps in this post.

Goal: A map with lines.

Live: https://maptheclouds.com/playground/30-day-map-challenge/lines/

Tweet: https://twitter.com/maptheclouds/status/1455593450720595984

Code: https://github.com/alexaac/map-challenges/tree/master/lines

Description:

The visualization shows the Yosemite Valley river network and catchment area, and is made by coloring streams by their flow order in QGIS.

Data: OpenTopography

Tags: #D3js #QGIS #mapshaper #canvas #LiDAR #hidrology #river #channels

Inspiration:

https://observablehq.com/@jipexu/chinese-rivers
https://www.youtube.com/watch?v=xwiHQlmEEjw
https://angrytools.com/gradient/

Challenges: For this map, I already had a elevation model surface for Yosemite derived from LiDAR files downloaded from OpenTopography.

I got the chance to make some GIS analysis in QGIS, play with styling and gradients in JavaScript and CSS, and display the result in the browser.

I have used QGIS to extract the river network (you can watch a tutorial that explains how to do this, ‘Deriving River Network & Catchments from a DEM using QGIS’), and mapped it in the browser using D3.js and Canvas.

What is interesting about the map is the leaves effect, from setting a fillStyle to the river lines, and the sky gradient. I have coloured the leaves by stream order, except for the main river.

// Color scale
colorScale = d3
  .scaleQuantile()
  .domain([0, 1, 2, 3, 4, 5, 6, 7])
  .range([
    '#1b251d',
    '#403310',
    '#8e6035',
    '#99700a',
    '#ad8a38',
    '#be903b',
    '#feef8b',
  ]);

[...]

    if (river.properties.ORDER > 1) {
      context.fillStyle = colorScale(river.properties.ORDER);
      context.fill();
    }

I have created gradients for three elements on the page, in the title, for the legend and as a background for the map.

Here’s how I have obtained the gradient in the title, as background for the unicode symbol, with CSS:

.sky {
  padding: 0.5rem;

  /* ff 3.6+ */
  background: -moz-radial-gradient(
    ellipse at 91% 15%,
    #67afee 0%,
    #158fc2 25%,
    #288ce2 50%,
    #096cc4 75%,
    #1262ad 100%
  );

  /* safari 5.1+,chrome 10+ */
  background: -webkit-radial-gradient(
    ellipse at 91% 15%,
    #67afee 0%,
    #158fc2 25%,
    #288ce2 50%,
    #096cc4 75%,
    #1262ad 100%
  );

  /* opera 11.10+ */
  background: -o-radial-gradient(
    ellipse at 91% 15%,
    #67afee 0%,
    #158fc2 25%,
    #288ce2 50%,
    #096cc4 75%,
    #1262ad 100%
  );

  /* ie 10+ */
  background: -ms-radial-gradient(
    ellipse at 91% 15%,
    #67afee 0%,
    #158fc2 25%,
    #288ce2 50%,
    #096cc4 75%,
    #1262ad 100%
  );

  /* global 92%+ browsers support */
  background: radial-gradient(
    ellipse at 91% 15%,
    #67afee 0%,
    #158fc2 25%,
    #288ce2 50%,
    #096cc4 75%,
    #1262ad 100%
  );
}

Here is the code for creating the gradient for the legend, with D3.js:

// Add sky gradient
  const defs = svg.append('defs');

  const gradient = defs
    .append('radialGradient')
    .attr('id', 'svgGradient')
    .attr('cx', '50%')
    .attr('cy', '50%')
    .attr('r', '50%')
    .attr('y1', '0%');

  gradient
    .append('stop')
    .attr('offset', '0%')
    .attr('style', 'stop-color:rgb(21,143,194);stop-opacity:1.00');
  gradient
    .append('stop')
    .attr('offset', '50%')
    .attr('style', 'stop-color:rgb(40,140,226);stop-opacity:1.00');

  mapLegend
    .append('rect')
    .attr('x', 0)
    .attr('y', -20)
    .attr('width', 150)
    .attr('height', 300)
    .style('fill', 'url(#svgGradient)')
    .style('stroke', '#dddddd');

And here is the code for creating the map background:

  // Background
  const grad = context.createRadialGradient(408, 216, 0, 408, 216, 427.8);

  grad.addColorStop(0, 'rgba(103, 175, 238, 1)');
  grad.addColorStop(0.25, 'rgba(21, 143, 194, 1)');
  grad.addColorStop(0.5, 'rgba(40, 140, 226, 1)');
  grad.addColorStop(0.75, 'rgba(9, 108, 196, 1)');
  grad.addColorStop(1, 'rgba(18, 98, 173, 1)');

  context.fillStyle = grad;
  context.fillRect(0, 0, width, height);

Initially, you could zoom and pan, but because the file was too large, it was loading slowly, and I didn’t want to handle this, I have added a fallback static image on the page. If you have patience, maybe you will se the interactive map on the page, too, after a while. ๐Ÿ™‚

TODO: create tiles and show details by zoom level, fix pan.

Leave a Reply

Your email address will not be published. Required fields are marked *