JSFiddle - React, Tailwind, and code Playground

by Shawn Allen

HTML

<svg></svg>

CSS

html, body {
    height: 100%;
    overflow: hidden;
}

svg {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

line {
    stroke-linecap: round;
}

JavaScript

var svg = d3.select("svg"),
    path = svg.append("path"),
    lines = [],
    maxLines = 360,
    grid = 1,
    draw = drawLines;

var strokeScale = d3.scale.linear()
  .domain([0, 200])
  .range([20, 5])
  .clamp(true);

var strokeWidth = function(line) {
  return strokeScale(distance(line.start, line.end));
};

var strokeColor = function(line, i) {
  return d3.hsl(i / maxLines * 360, 1, .5);
};

function drawPath() {
  var points = [];
  lines.forEach(function(line) {
    points.push(line.start, line.end);
  });
  path.datum(points)
    .attr("d", d3.svg.line()
      .interpolate(interpolate)
      .x(function(d) { return round(d.x); })
      .y(function(d) { return round(d.y); }));
}

function drawLines() {
  var line = svg.selectAll("line")
    .data(lines);
  line.exit().remove();
  line.enter().append("line");
  line.attr({
    x1: function(d) { return round(d.start.x); },
    y1: function(d) { return round(d.start.y); },
    x2: function(d) { return round(d.end.x); },
    y2: function(d) { return round(d.end.y); }
  })
  .attr("stroke", strokeColor)
  .attr("stroke-width", 20);
}

svg.on("mousedown", function(e) {
  var mouse = getPosition();

  svg.on("mousemove", function(e) {
    var pos = getPosition(),
        line = {
          start: mouse,
          end: pos
        };
    mouse = pos;
    lines.push(line);
    if (lines.length > maxLines) {
      lines.shift();
    }
    draw();
  });
});

svg.on("mouseup", function() {
  svg.on("mousemove", null);
});

svg.on("dblclick", clear);

function clear() {
  lines = [];
  draw();
}

function getPosition() {
  var e = d3.event;
  return {
    x: e.offsetX,
    y: e.offsetY,
    time: Date.now()
  };
}

function round(n) {
  return grid * Math.round(n / grid);
}

function distance(a, b) {
  var dx = b.x - a.x,
      dy = b.y - a.y;
  return Math.sqrt(dx * dx + dy * dy);
}