Slope chart

슬로프 차트

Shows the change between exactly two points in time as a single tilted line — rising and falling lines split apart at a glance.

Also known as: Slopegraph기울기 차트
···
html
<div class="viz">
  <svg id="svg"></svg>
</div>
css
body{display:block}
.viz{position:relative;width:100%;height:100%}
svg{display:block;width:100%;height:100%;overflow:visible}
.axis{stroke:var(--line);stroke-width:1}
.tick{fill:var(--muted);font-weight:600}
.minor{display:none}
@media (min-width:460px){.minor{display:inline}}
.bg-line{stroke:var(--muted);stroke-width:1.4;opacity:.38;fill:none}
.hl-line{stroke:var(--accent);stroke-width:2.6;fill:none}
.bg-dot{fill:var(--muted);opacity:.5}
.hl-dot{fill:var(--accent)}
js
var svg = document.getElementById('svg');
var NS = 'http://www.w3.org/2000/svg';
function se(t){ return document.createElementNS(NS,t); }
function sa(e,o){ for (var k in o) e.setAttribute(k,o[k]); }
function R(a,b){ return a + Math.random()*(b-a); }

var CATS = ['제품 A','제품 B','제품 C','제품 D','제품 E'];
var HL = 2;
function genVals(){ return CATS.map(function(){ return { a:R(18,88), b:R(18,88) }; }); }
var cur = genVals();
var W=300, H=200;

function measure(){
  var r = svg.getBoundingClientRect();
  W = Math.max(r.width,10); H = Math.max(r.height,10);
  sa(svg,{ viewBox: '0 0 ' + W + ' ' + H });
}

function draw(){
  svg.innerHTML = '';
  var padL=54, padR=54, padT=16, padB=18;
  var pw=W-padL-padR, ph=H-padT-padB;
  var x0=padL, x1=W-padR;
  function Y(v){ return padT+ph-(v/100)*ph; }
  var fs = Math.max(8, Math.min(11, W/95));

  ['이전','이후'].forEach(function(lab,i){
    var t = se('text');
    sa(t,{x:i===0?x0:x1,y:H-4,'text-anchor':'middle',class:'tick','font-size':fs});
    t.textContent = lab;
    svg.appendChild(t);
  });

  cur.forEach(function(v,i){
    var isHL = i===HL;
    var y0=Y(v.a), y1=Y(v.b);
    var line = se('line');
    sa(line,{x1:x0,y1:y0,x2:x1,y2:y1,class:isHL?'hl-line':'bg-line'});
    svg.appendChild(line);
    [ [x0,y0], [x1,y1] ].forEach(function(p){
      var d = se('circle');
      sa(d,{cx:p[0],cy:p[1],r:isHL?3.4:2.2,class:isHL?'hl-dot':'bg-dot'});
      svg.appendChild(d);
    });
    if (isHL){
      var lab0 = se('text');
      sa(lab0,{x:x0-8,y:y0+fs*0.32,'text-anchor':'end',fill:'var(--fg)','font-size':fs,'font-weight':700});
      lab0.textContent = CATS[i];
      svg.appendChild(lab0);
      var lab1 = se('text');
      sa(lab1,{x:x1+8,y:y1+fs*0.32,'text-anchor':'start',fill:'var(--fg)','font-size':fs,'font-weight':700});
      lab1.textContent = Math.round(v.b);
      svg.appendChild(lab1);
    } else {
      var m = se('text');
      sa(m,{x:x1+8,y:y1+fs*0.32,'text-anchor':'start',class:'tick minor','font-size':fs-1});
      m.textContent = CATS[i];
      svg.appendChild(m);
    }
  });
}

function animate(target){
  var from = cur;
  var t0 = performance.now();
  function step(t){
    var p = Math.min(1,(t-t0)/800);
    var e = 1-Math.pow(1-p,3);
    cur = from.map(function(v,i){ var to=target[i]; return { a:v.a+(to.a-v.a)*e, b:v.b+(to.b-v.b)*e }; });
    draw();
    if (p<1) requestAnimationFrame(step); else cur = target;
  }
  requestAnimationFrame(step);
}

new ResizeObserver(function(){ measure(); draw(); }).observe(svg);
measure();
draw();
setInterval(function(){ animate(genVals()); }, 3700);

Time 1 sits on the left, time 2 on the right, and one line connects the same item between them. A line rising means growth, falling means decline, and a steeper slope means a bigger change — reading "what went up, what went down" is faster here than scanning two side-by-side bar charts.

Edward Tufte formalized this shape. With many items, lines start overlapping and crossing until it's hard to follow any one of them — the common fix is to color the one (or few) items you want to make the point about, and gray out the rest as background context.

With three or more time points, this isn't the right form anymore — reach for a line chart instead. A slope chart is purpose-built for exactly a two-point comparison.

When to use

Use it to compare many items’ change between exactly two points in time, especially when highlighting one of them.