Как соединить два div-a линией в приложении с drag & drop
У меня есть приложение, написанное с помощью React-dnd, окно, в котором я могу свободно перемещать блоки. Проблема в том, что нужно соединять эти блоки линиями (стрелочками). Находил много вариантов в интернете, но у меня линии должен делать сам пользователь. Это не должна быть анимация или статическая линия, нужно чтобы пользователь мог соединить прямой линией два любых блока, где бы они не находились, и так же мог линии убирать, если они ему не нужны. Буду благодарен за любые варианты. Смотрел примеры с canvas, svg, разными библиотеками, как например jsPlumb, но нигде не видел примера, где прямые линии проводит сам пользователь своей рукой.
Ответы (1 шт):
Набросал примитивный пример на SVG, где можно от одного квадрата провести линию к другому. До идеала доводить не стал, основная идея думаю понятна.
let from = document.querySelector('.from'),
to = document.querySelector('.to'),
mousePressed = false,
pointFrom,
pointTo,
svg;
from.addEventListener( 'mousedown', e => {
mousePressed = true;
pointFrom = {
x: e.clientX,
y: e.clientY,
};
});
document.addEventListener( 'mousemove', e => {
if( !mousePressed ) return;
pointTo = {
x: e.clientX,
y: e.clientY,
};
updateLine();
});
document.addEventListener( 'mouseup', e => {
if( !mousePressed ) return;
mousePressed = false;
});
function updateLine(){
if(svg) svg.remove();
let width = pointTo.x - pointFrom.x,
height = pointTo.y - pointFrom.y;
svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' );
svg.style.left = pointFrom.x + 'px';
svg.style.top = pointFrom.y + 'px';
svg.setAttribute( 'width', pointTo.x - pointFrom.x );
svg.setAttribute( 'height', pointTo.y - pointFrom.y );
svg.setAttribute( 'viewBox', `0 0 ${width} ${height}` );
let path = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' );
path.setAttribute( 'stroke', 'red' );
path.setAttribute( 'd', `M 0,0 L ${width},${height}` );
svg.appendChild(path);
document.body.appendChild(svg);
}
.from, .to {
width: 100px;
height: 100px;
position: absolute;
background-color: gray;
}
.from {
left: 0;
top: 0;
}
.to {
left: 200px;
top: 30px;
}
svg {
position: absolute;
}
<div class="from"></div>
<div class="to"></div>