Страницы

Поиск по вопросам

вторник, 28 января 2020 г.

Как можно провести линию между двумя блоками, если зажать мышь на одном и отпустить на другом?

#javascript #html #css #jquery #svg


К примеру, между .span1 и .span2

1
2


Ответы

Ответ 1



Вот собрал что-то похожее из 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 || '') } }) —— UPD: похожий ответ с использованием d3.js

Комментариев нет:

Отправить комментарий