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",...