JSFiddle - React, Tailwind, and code Playground

HTML

<body>
    <div id="debug" style="position: absolute">
    </div>
    
    <svg id="template" viewBox="0 0 10 10"/>
</body>

CSS

body {
    background-color: white;
}

#template {
    position: absolute;
    width: 100vmin;
    height: 100vmin;
}

line {
    stroke: red;
    stroke-width: 0.2;
}

.approach {
    fill: transparent;
}

.active {
    fill: red;
}

JavaScript

// positions of the dots that can be connected
var nodes = [
    [5,1],
    [1,3],
    [9,3],
    [3,4],
    [7,4],
    [5,5],
    [3,6],
    [7,6],
    [1,7],
    [9,7],
    [5,9]
];
var strokes = []; // not used yet
var openStroke = []; // stroke that's currently drawn
var template;

// helper function from http://stackoverflow.com/questions/3642035/jquerys-append-not-working-with-svg-element
function makeSVG(tag, attrs) {
    var el= document.createElementNS('http://www.w3.org/2000/svg', tag);
    for (var k in attrs)
        el.setAttribute(k, attrs[k]);
    return el;
}

$(document).ready(function() {
    document.addEventListener('touchstart', prevent);
    document.addEventListener('touchmove', prevent);

    template = document.getElementById('template');

    template.addEventListener('mouseup', endStroke);
    template.addEventListener('mouseleave', endStroke);
    template.addEventListener('touchend', endStroke);
    template.addEventListener('touchcancel', endStroke);

    // so the desktop browser doesn't let the user drag the image
    template.addEventListener('dragstart', prevent);

    // create circles
    nodes.forEach(function(node) {
        var touchCircle = makeSVG('circle', {
            cx: node[0], cy: node[1], r: 0.5,
            class: 'approach'
        });

        var circle = makeSVG('circle', {
            cx: node[0], cy: node[1], r: 0.2,
            class: "node"
        });
        template.appendChild(circle);

        touchCircle.addEventListener('mousedown', function () {return startStroke(node, circle);});
        touchCircle.addEventListener('touchstart', function () {return startStroke(node, circle);});

        touchCircle.addEventListener('mouseover', function () {return continueStroke(node, circle);});
        touchCircle.addEventListener('touchmove', function () {return continueStroke(node, circle);});

        template.appendChild(touchCircle);
    });
});

function prevent(e) {
    e.preventDefault();
}

function...