К примеру, между .span1 и .span2
<span class="span1">1</span>
<div style="height:100px;"></div>
<span class="span2">2</span>
Вот собрал что-то похожее из svg
+js
, вообще я обычно такое делаю на d3.js
, тут ради исключения сделал на голом js
, на d3
листинг был бы не сильно длиннее, но все же лаконичнее...
Чтобы нарисовать прямоугольник, используйте перетаскивание левой кнопкой мыши на свободном месте.
Переместить прямоугольник можно так же перетаскиванием левой кнопкой.
Соединить прямоугольники можно при помощи перетаскивания правой кнопкой начиная на прямоугольнике
Двойное нажатие на прямоугольник позволяет добавить текст.
let x, y, shape, move, svg = document.querySelector('svg');
let attrs = (s, o) => Object.keys(o).forEach(p => s.setAttribute(p, o[p]))
let clampToCenter = e => [+e.getAttribute('x') + e.getAttribute('width')/2,
+e.getAttribute('y') + e.getAttribute('height')/2]
attrs(svg, {width: window.innerWidth, height: window.innerHeight});
function startDrawLink(e) {
shape = document.createElementNS('http://www.w3.org/2000/svg', 'line');
shape.source = e.target;
let p = clampToCenter(e.target);
attrs(shape,{x1: p[0], y1: p[1], x2: e.x, y2: e.y,
stroke: '#000', 'pointer-events': 'none'})
}
function startTranslateRect(e){
move = e.target;
move.px = +e.target.getAttribute('x');
move.py = +e.target.getAttribute('y');
move.ex = e.x;
move.ey = e.y;
}
function translateRect(e) {
attrs(move, {x: move.px + e.x - move.ex, y: move.py + e.y - move.ey})
let p = clampToCenter(move);
document.querySelectorAll('line').forEach(l => {
let isSrc = l.source === move
if (isSrc || l.target === move) {
l.setAttribute(isSrc ? 'x1' : 'x2', p[0])
l.setAttribute(isSrc ? 'y1' : 'y2', p[1])
}
})
e.target.text && attrs(e.target.text, {
x: move.px + e.x - move.ex + e.target.getAttribute('width')/2,
y: move.py + e.y - move.ey + e.target.getAttribute('height')/2
})
}
function doDrawRect(e){
attrs(shape, {
x: Math.min(e.x, shape.cx), y: Math.min(e.y, shape.cy),
width: Math.abs(e.x - shape.cx), height: Math.abs(e.y - shape.cy)
})
}
function doDrawLine(e){
if (e.target.nodeName === "rect" && e.target != shape.source) {
let p = clampToCenter(e.target)
attrs(shape, {x2: p[0], y2: p[1]})
shape.removeAttribute('stroke-dasharray')
} else {
attrs(shape, {x2: e.x, y2: e.y, 'stroke-dasharray': '10 10'})
}
}
addEventListener('mousedown', e => {
if (e.target.nodeName === "rect") {
if (e.button === 2)
startDrawLink(e)
if (e.button === 0)
startTranslateRect(e);
} else {
shape = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
shape.cx = e.x;
shape.cy = e.y;
attrs(shape, {fill: 'white', stroke: 'black'})
}
shape && svg.appendChild(shape);
})
addEventListener('mousemove', e => {
if (move)
translateRect(e);
if (shape)
if (shape.nodeName === "rect")
doDrawRect(e);
else
doDrawLine(e);
})
addEventListener('mouseup', e => {
if (shape && shape.nodeName === "line") {
shape.remove();
if (!shape.getAttribute('stroke-dasharray')) {
svg.insertBefore(shape, svg.firstChild)
shape.target = e.target;
}
}
shape = null;
move = null;
})
addEventListener('contextmenu', e => e.preventDefault())
addEventListener('click', e => {
if (e.detail == 2 && e.target.nodeName === "rect") {
if (!e.target.text) {
e.target.text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
let p = clampToCenter(e.target)
attrs(e.target.text, {x: p[0], y: p[1], 'text-anchor': 'middle',
'dominant-baseline': 'middle', 'pointer-events': 'none'})
svg.appendChild(e.target.text);
}
e.target.text.innerHTML = prompt('enter text', e.target.text.innerHTML || '')
}
})
<body style="margin:0;overflow:hidden;user-select:none"><svg style="background-color: wheat"></svg>
——
UPD: похожий ответ с использованием d3.js
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Есть контейнер содержимого в галерее, у него стоят display:flex и justify-content: center, так же у каждого элемента галереи есть эффект появления и исчезновенияВ...
Есть слайдер-ползунок, работающий с помощью jquery-uihttps://codepen
Написать структуру, которая обрабатывала бы входные данные следующим образомНа входе даётся целое число, указывающее количество операций
Есть ли какая нибудь замена, либо аналогия временной C++ библиотеки chrono (в ходящей в пространство имен std) в C ??