d3:slope-chart

by Richard Hunter

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>
<div id="chart"></div>
<a href="https://observablehq.com/@d3/slope-chart/3">source</a>

JavaScript

const data = [{
  "1970": 46.9,
  "1979": 57.4,
  "country": "Sweden"
}, {
  "1970": 44,
  "1979": 55.8,
  "country": "Netherlands"
}, {
  "1970": 43.5,
  "1979": 52.2,
  "country": "Norway"
}, {
  "1970": 40.7,
  "1979": 39,
  "country": "Britain"
}, {
  "1970": 39,
  "1979": 43.4,
  "country": "France"
}, {
  "1970": 37.5,
  "1979": 42.9,
  "country": "Germany"
}, {
  "1970": 35.2,
  "1979": 43.2,
  "country": "Belgium"
}, {
  "1970": 35.2,
  "1979": 35.8,
  "country": "Canada"
}, {
  "1970": 34.9,
  "1979": 38.2,
  "country": "Finland"
}, {
  "1970": 30.4,
  "1979": 35.7,
  "country": "Italy"
}, {
  "1970": 30.3,
  "1979": 32.5,
  "country": "United States"
}, {
  "1970": 26.8,
  "1979": 30.6,
  "country": "Greece"
}, {
  "1970": 26.5,
  "1979": 33.2,
  "country": "Switzerland"
}, {
  "1970": 22.5,
  "1979": 27.1,
  "country": "Spain"
}, {
  "1970": 20.7,
  "1979": 26.6,
  "country": "Japan"
}]

// Specify the chart’s dimensions.
const width = 928;
const height = 600;
const marginTop = 40;
const marginRight = 50;
const marginBottom = 10;
const marginLeft = 50;
const padding = 3;

// Prepare the positional scales.
const x = d3.scalePoint()
  .domain([0, 1])
  .range([marginLeft, width - marginRight])
  .padding(0.5);

const y = d3.scaleLinear()
  .domain(d3.extent(data.flatMap(d => [d[1970], d[1979]])))
  .range([height - marginBottom, marginTop]);

const line = d3.line()
  .x((d, i) => {
    return x(i)
  })
  .y(y);

const formatNumber = y.tickFormat(100);

// Create the container SVG.
const svg = d3.create("svg")
  .attr("viewBox", [0, 0, width, height])
  .attr("style", "max-width: 100%; height: auto; font: 10px sans-serif;");

// Append the x axis.
svg.append("g")
  .attr("text-anchor", "middle")
  .selectAll("g")
  .data([0, 1])
  .join("g")
  .attr("transform", (i) => `translate(${x(i)},20)`)
  .call(g => g.append("text").text((i) => i ? 1979 : 1970))
  .call(g => g.append("line").attr("y1", 3).attr("y2", 9).attr("stroke", "currentColor"));

// Create a...