JSFiddle - React, Tailwind, and code Playground

by Shawn Allen

HTML

<svg width="400" height="400"></svg>

CSS

svg {
    border: 1px solid #ccc;
}

line {
    /* stroke: black; */
    stroke-opacity: .8;
    stroke-linecap: round;
    /* stroke-width: 1; */
}

JavaScript

var svg = d3.select("svg"),
    bg = svg.append("rect")
        .attr({
            x: 0,
            y: 0,
            width: "100%",
            height: "100%",
            fill: "none"
        }),
    drawing = false,
    pos = {x: 0, y: 0},
    lines = [],
    lineIndex = 0,
    maxLines = 180;

svg.on("mousedown", function(d, i) {
    drawing = true;
    pos = getPosition();
});

svg.on("mousemove", function() {
    if (!drawing) return;
    var prev = pos;
    pos = getPosition();
    var dist = distance(prev, pos);
    var color = "hsl(" + [lineIndex++, "100%", "80%"] + ")";
    var line = {
        x1: prev.x,
        y1: prev.y,
        x2: pos.x,
        y2: pos.y,
        "stroke": color,
        "stroke-width": dist
    };
    svg.append("line")
        .datum(line)
        .attr(line);
    lines.push(line);
    if (lines.length > maxLines) {
        svg.select("line").remove();
        lines.shift();
    }
    bg.attr("fill", lines[0].stroke);
});

svg.on("mouseup", function() {
    drawing = false;
});

svg.on("dblclick", function() {
    svg.selectAll("line").remove();
});

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

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