Что хочу получить:
Картинка для визуализации. Задача состоит в том что бы связывать блоки (динамически протянуть стрелку от одного блок к другому) и в конце получить структуру для дальнейшей работы. Например:
a link to b
b link to c
Так же у одного блок может быть несколько связей. Прошу подсказать направление, как сделать связи.
перетаскивания сделал так:
Ответ
Рабочий вариант, но код не в лучшем виде. Ссылка на plunker.
"use strict";
var can = $("#can").get(0), ctx = can.getContext('2d');
var boxes = [];
function get_box(x, y) {
for (var box of boxes) {
if (x >= box.x && x < box.x + box.w && y >= box.y && y < box.y + box.h) {
return box;
}
}
return null;
}
function getxy(e) { return {x:e.clientX, y:e.clientY}; }
class Box {
constructor(x, y, w, h) {
this.x = x; this.y = y;
this.w = w; this.h = h;
this.drag = null;
this.name = String.fromCharCode("A".charCodeAt() + boxes.length);
boxes.push(this);
}
on_mouse_down(e) {
this.drag = {
oldx: this.x, oldy: this.y, // old position of box
msx: e.clientX, msy: e.clientY // mouse start x, y
};
}
on_mouse_move(e) {
if (!this.drag) return;
var dx = e.clientX - this.drag.msx, dy = e.clientY - this.drag.msy;
this.x = this.drag.oldx + dx;
this.y = this.drag.oldy + dy;
draw_boxes();
}
on_mouse_up(e) {
this.drag = null;
}
draw() {
ctx.save();
ctx.fillRect(this.x, this.y, this.w, this.h);
ctx.font = "30px Georgia";
ctx.fillStyle = "white";
ctx.fillText(this.name, this.x + 10, this.y + 30);
ctx.restore();
}
center() {
return {x: this.x + Math.floor(this.w/2), y: this.y + Math.floor(this.h/2) };
}
}
var link = null, links = [];
function on_mouse_event(method_name) {
return function (e) { for (var box of boxes) box[method_name](e); }
}
$("#can").mousedown(function (e) {
var p = getxy(e), b = get_box(p.x, p.y);
if (e.shiftKey) {
new Box(p.x, p.y, 50, 50);
draw_all();
return;
}
if (!b) return;
if (e.ctrlKey) {
link = {b};
return;
}
get_box(p.x, p.y).on_mouse_down(e);
});
$("#can").mousemove((e) => {
if (link) {
link.t = getxy(e);
} else {
for (var box of boxes) box.on_mouse_move(e);
}
draw_all();
});
$("#can").mouseup((e) => {
var x = e.clientX, y = e.clientY, b = get_box(x, y);
if (link) {
if (link.b == b || !b) {
link = null;
return;
}
links.push({from:link.b, to:b});
} else {
for (var box of boxes) box.on_mouse_up(e);
}
link = null;
});
$("#getlinks").click((e) => {
var msg = "";
for (var l of links) {
msg += `Box "${l.from.name}" свзяан с Box "${l.to.name}"
`;
}
$("#res").html(msg);
});
new Box(10, 10, 50, 50);
new Box(150, 150, 50, 50);
function draw_boxes() {
for (var box of boxes) {
box.draw();
}
}
function draw_links() {
for (var l of links) {
var bc1 = l.from.center(), bc2 = l.to.center();
ctx.beginPath();
ctx.moveTo(bc1.x, bc1.y);
ctx.lineTo(bc2.x, bc2.y);
ctx.stroke();
}
}
function draw_link() {
var bc = link.b.center();
ctx.beginPath();
ctx.moveTo(bc.x, bc.y);
ctx.lineTo(link.t.x, link.t.y);
ctx.stroke();
}
function draw_all() {
ctx.clearRect(0, 0, can.width, can.height);
draw_links();
draw_boxes();
if (link) draw_link();
}
draw_all();
html,
body {
margin: 0;
padding: 0;
}
MouseMove -- перемещение коробок.
Shift + Click -- добавить коробку.
Ctrl (на коробке) + MouseMove -- провести линию.
Комментариев нет:
Отправить комментарий