"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(px, py); if (e.shiftKey) { new Box(px, py, 50, 50); draw_all(); return; } if (!b) return; if (e.ctrlKey) { link = {b}; return; } get_box(px, py).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}"<br>`; } $("#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.tx, link.ty); 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; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div> <canvas id="can" width="300" height="300"> This text is displayed if your browser does not support HTML5 Canvas. </canvas> </div> <hr>MouseMove -- ΠΏΠ΅ΡΠ΅ΠΌΠ΅ΡΠ΅Π½ΠΈΠ΅ ΠΊΠΎΡΠΎΠ±ΠΎΠΊ. <br>Shift + Click -- Π΄ΠΎΠ±Π°Π²ΠΈΡΡ ΠΊΠΎΡΠΎΠ±ΠΊΡ. <br>Ctrl (Π½Π° ΠΊΠΎΡΠΎΠ±ΠΊΠ΅) + MouseMove -- ΠΏΡΠΎΠ²Π΅ΡΡΠΈ Π»ΠΈΠ½ΠΈΡ. <br> <hr> <button id="getlinks">ΠΠΎΠ»ΡΡΠΈΡΡ Π²ΡΠ΅ ΡΠ²ΡΠ·ΠΈ</button> <p id="res"></p>