JSFiddle - React, Tailwind, and code Playground
by Alexandru Gatea
HTML
<div class="container">
<div id="svgContainer">
<svg id="svg1" >
<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; width: 100%; height: 100%;
}
.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(path, goDown, bezieDown, startX, startY, endX, endY) {
path.attr("d", "M " + startX + ", " + startY +
"L " + startX + ", " + goDown +
"C " + startX + ", " + (startY + bezieDown) + " " + endX + ", " + (endY - 250) + " " + endX + ", " + (endY - 10) +
"L " + endX + ", " + endY);
}
function connectElements(path, offset, startElem, endElem) {
var svgContainer = $("#svgContainer");
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 goDown = startY + (startElem.outerHeight() * offset);
var bezieDown = goDown * 1.5;
drawPath(path, goDown, bezieDown, startX, startY, endX, endY);
}
function connectAll() {
connectElements($("#path1"), 2, $("#res"), $("#output"));
connectElements( $("#path2"), 1.5, $("#act"), $("#output"));
connectElements( $("#path3"), 0.75, $("#mkt"), $("#output"));
connectElements($("#path4"), 0.5, $("#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", "0").attr("width", "0");
connectAll();
});