JSFiddle - React, Tailwind, and code Playground

by Alexandru Gatea

HTML

<div class="container">
<div id="svgContainer">
  <svg id="svg1" width="0" height="0">
    <path id="path1" d="M0 0" stroke="black" stroke-width="4px" fill="none"/>
    <path id="path2" d="M0 0" stroke="black" stroke-width="4px" fill="none"/>
    <path id="path3" d="M0 0" stroke="black" stroke-width="4px" fill="none"/>
    <path id="path4" d="M0 0" stroke="black" stroke-width="4px" fill="none"/>
  </svg>
</div>
  <div class="connect-these">
    <div id="res"></div>
    <div id="act"></div>
    <div id="mkt"></div>
    <div id="prod"></div>
  </div>
  <div class="to-this">
    <div id="output"></div>
  </div>
</div>

<!-- zi-mi daca vezi commentu asta -->

SCSS

.container {
  display: flex;
  height: 130vh;
  flex-direction: column;
  position: relative;
  
  .connect-these {
    display: flex;
    width: 420px;
    flex-wrap: wrap;
    position: sticky;
    top: 0;
}

svg {
  overflow: visible;
}

  .connect-these div {
    width: 100px;
    height: 100px;
    border: 4px solid black;
    margin: 20px;
    background: white;
    border-radius: 10px;
    position: relative;
    
    &::after {
      content: "";
      width: 20px;
      height: 20px;
      background: #fff;
      border-radius: 32px;
      border: 4px solid #000;
      position: absolute;
      top: 100%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    
    &:nth-child(3) {
      margin-left: 100px;
    }
  }

  .to-this {
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    margin-top: 600px;
    margin-right: 100px;
      
    #output {
      width: 100px;
      height: 100px;
      border: 4px solid black;
      margin: 20px;
      background: white;
      border-radius: 10px;
      position: absolute;
      
      &::after {
        content: "";
        width: 20px;
        height: 20px;
        background: #fff;
        border-radius: 32px;
        border: 4px solid #000;
        position: absolute;
        top: 0%;
        left: 50%;
        transform: translate(-50%, -50%);
      }
    }
  }
}

#svgContainer {
	z-index: -10;
	position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

JavaScript

function drawPath(svg, path, LTop, bez, startX, startY, endX, endY) {
  var stroke = parseFloat(path.attr("stroke-width"));
  if (svg.attr("height") < endY) svg.attr("height", endY);
  if (svg.attr("width") < (startX + stroke)) svg.attr("width", (startX + stroke));
  if (svg.attr("width") < (endX + stroke)) svg.attr("width", (endX + stroke));

  path.attr("d", "M "  + startX + " " + startY +
    "L " + startX + " " + LTop +
    "C " + startX + " " + (startY + bez) + ", " + endX + " " + (endY - 300) + ", " + endX + " " + (endY - 10) +
    "L " + endX + " " + endY);

}


function connectElements(svg, path, off, bezier, startElem, endElem) {
	var svgContainer = $("#svgContainer");
  if (startElem.offset().top > endElem.offset().top) {
    var temp = startElem;
    startElem = endElem;
    endElem = temp;
  }

  var svgTop = svgContainer.offset().top;
  var svgLeft = svgContainer.offset().left;
  var startCoord = startElem.offset();
  var endCoord = endElem.offset();
  var startX = startCoord.left + 0.5 * startElem.outerWidth() - svgLeft;
  var startY = startCoord.top + (startElem.outerHeight() / 2) - svgTop;
  var endX = endCoord.left + 0.5 * endElem.outerWidth() - svgLeft;
  var endY = endCoord.top - svgTop;
  var LTop = startY + off;
  var bez = bezier;

  drawPath(svg, path, LTop, bez, startX, startY, endX, endY);

}

function connectAll() {
  // connect all the paths you want!
  connectElements($("#svg1"), $("#path1"), 250, 500, $("#res"), $("#output"));
  connectElements($("#svg1"), $("#path2"), 200, 400, $("#act"), $("#output"));
  connectElements($("#svg1"), $("#path3"), 100, 300, $("#mkt"), $("#output"));
  connectElements($("#svg1"), $("#path4"), 80, 200, $("#prod"), $("#output"));

}

$(document).ready(function() {
  $("#svg1").attr("height", "0").attr("width", "0");
  connectAll();
});

$(window).resize(function() {
  $("#svg1").attr("height", "0").attr("width", "0");
  connectAll();
});

$(window).scroll(function() {
  $("#svg1").attr("height",...