JSFiddle - React, Tailwind, and code Playground

by Zevan

HTML

drag circles around

CSS

*{
 font-family : sans-serif;
 font-size : 12px;
}
svg{
 
 cursor : pointer;   
}

JavaScript

var r = new Raphael(0, 0, 500, 500);

var CIRCLE_NUM = 4;
var circles = [];
var lines = [];

// make some randomly positioned circles
for (var i = 0; i < CIRCLE_NUM; i++){
circles.push(r.circle(Math.random() * 150 + 150, 
                      Math.random() * 150 + 150, 
                      60)
              .attr({fill: "rgba(81, 121, 200, 0.3)"}));
}

var line = r.path();
var path = "";

render();
dragAndDrop();

function render() {
    path = "";
    redPath = "";
    lines = [];
    var leng = circles.length;
    for (var i = 0; i<leng; i++){
        for (var j = i + 1; j<leng; j++){
            circleIntersection(circles[i], circles[j]);
        }
    }
}

// easy to understand explanation here:
// http://paulbourke.net/geometry/2circle/
function circleIntersection(a, b) {
    var a, h, cx, cy, px, py;
    var ax = a.attr("cx");
    var ay = a.attr("cy");
    var bx = b.attr("cx");
    var by = b.attr("cy");
    var ra = a.attr("r");
    var rb = b.attr("r");

    var dx = Math.abs(ax - bx);
    var dy = Math.abs(ay - by);

    var d = Math.sqrt(dx * dx + dy * dy);

    if (d > (ra + rb)) {
        // no solutions
    } else if (d < Math.abs(ra - rb)) {
        // no collisions, one inside other
    } else if (d == 0 && ra == rb) {
        // circles are coincident   
    } else {
        // there is a collision
        a = (ra * ra - rb * rb + d * d) / (2 * d);
        h = Math.sqrt(ra * ra - a * a);
        cx = ax + a * (bx - ax) / d;
        cy = ay + a * (by - ay) / d;

        // point c (draw here)
        
        var tx = h * (by - ay) / d;
        var ty = h * (bx - ax) / d;
        px = cx + tx;
        py = cy - ty;
  
        var ln = {a:{x:px, y:py}};
            
        path += "M " + px + " " + py + " ";

        px = cx - tx;
        py = cy + ty;

        ln.b = {x:px, y:py};
        
        path += "L " + px + " " + py + " ";

        line.attr({path: path});
        
        lines.push(ln);
    }
}
 
function dragAndDrop(){
    var...