hoverable nodes and more
This commit is contained in:
parent
d4be01166c
commit
377cd8bcf1
2 changed files with 93 additions and 49 deletions
|
@ -1,12 +1,13 @@
|
||||||
var DiagramNode = /** @class */ (function () {
|
var DiagramNode = /** @class */ (function () {
|
||||||
function DiagramNode(x, y, width, height, label) {
|
function DiagramNode(x, y, width, height, label) {
|
||||||
|
this.hover = false;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
DiagramNode.prototype.pointInDiagram = function (x, y) {
|
DiagramNode.prototype.pointInNode = function (x, y) {
|
||||||
if (x < this.x) {
|
if (x < this.x) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +39,13 @@ function diagramOnMouseMove(ev) {
|
||||||
}
|
}
|
||||||
var Diagrams = /** @class */ (function () {
|
var Diagrams = /** @class */ (function () {
|
||||||
function Diagrams(canvasId) {
|
function Diagrams(canvasId) {
|
||||||
|
this.nodes = new Array();
|
||||||
|
this.connections = new Array();
|
||||||
|
this.cameraX = 0;
|
||||||
|
this.cameraY = 0;
|
||||||
|
this.panning = false;
|
||||||
|
this.nodeDragging = null;
|
||||||
|
this.nodeHover = null;
|
||||||
this.canvas = document.getElementById(canvasId);
|
this.canvas = document.getElementById(canvasId);
|
||||||
if (this.canvas === null) {
|
if (this.canvas === null) {
|
||||||
throw "Could not getElementById " + canvasId;
|
throw "Could not getElementById " + canvasId;
|
||||||
|
@ -48,28 +56,38 @@ var Diagrams = /** @class */ (function () {
|
||||||
}
|
}
|
||||||
_diagram = this;
|
_diagram = this;
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.ctx.font = "30px Arial";
|
this.ctx.font = "30px Helvetica";
|
||||||
this.canvas.onmousemove = diagramOnMouseMove;
|
this.canvas.onmousemove = diagramOnMouseMove;
|
||||||
this.canvas.onmousedown = diagramOnMouseDown;
|
this.canvas.onmousedown = diagramOnMouseDown;
|
||||||
this.canvas.onmouseup = diagramOnMouseUp;
|
this.canvas.onmouseup = diagramOnMouseUp;
|
||||||
window.onresize = diargramOnResize;
|
window.onresize = diargramOnResize;
|
||||||
this.nodes = new Array();
|
|
||||||
this.connections = new Array();
|
|
||||||
this.cameraX = 0;
|
|
||||||
this.cameraY = 0;
|
|
||||||
}
|
}
|
||||||
Diagrams.prototype.onmousemove = function (ev) {
|
Diagrams.prototype.onmousemove = function (ev) {
|
||||||
|
var canvasRect = this.canvas.getBoundingClientRect();
|
||||||
|
var mouseX = ev.x - canvasRect.left;
|
||||||
|
var mouseY = ev.y - canvasRect.top;
|
||||||
if (this.panning) {
|
if (this.panning) {
|
||||||
this.cameraX += ev.movementX;
|
this.cameraX += ev.movementX;
|
||||||
this.cameraY += ev.movementY;
|
this.cameraY += ev.movementY;
|
||||||
}
|
}
|
||||||
if (this.nodeDrag) {
|
else if (this.nodeDragging != null) {
|
||||||
if (this.nodeDragged === null) {
|
this.nodeDragging.x = mouseX - this.cameraX - this.nodeDragging.width / 2;
|
||||||
console.error("nodeDrag==true but nodeDragged==null");
|
this.nodeDragging.y = mouseY - this.cameraY - this.nodeDragging.height / 2;
|
||||||
return;
|
}
|
||||||
|
else if (this.nodeHover != null) {
|
||||||
|
if (!this.nodeHover.pointInNode(mouseX - this.cameraX, mouseY - this.cameraY)) {
|
||||||
|
this.nodeHover.hover = false;
|
||||||
|
this.nodeHover = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (var _i = 0, _a = this.nodes; _i < _a.length; _i++) {
|
||||||
|
var node = _a[_i];
|
||||||
|
if (node.pointInNode(mouseX - this.cameraX, mouseY - this.cameraY)) {
|
||||||
|
node.hover = true;
|
||||||
|
this.nodeHover = node;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.nodeDragged.x += ev.movementX;
|
|
||||||
this.nodeDragged.y += ev.movementY;
|
|
||||||
}
|
}
|
||||||
this.draw();
|
this.draw();
|
||||||
};
|
};
|
||||||
|
@ -82,9 +100,8 @@ var Diagrams = /** @class */ (function () {
|
||||||
var mouseY = ev.y - canvasRect.top;
|
var mouseY = ev.y - canvasRect.top;
|
||||||
for (var _i = 0, _a = this.nodes; _i < _a.length; _i++) {
|
for (var _i = 0, _a = this.nodes; _i < _a.length; _i++) {
|
||||||
var node = _a[_i];
|
var node = _a[_i];
|
||||||
if (node.pointInDiagram(mouseX, mouseY)) {
|
if (node.pointInNode(mouseX - this.cameraX, mouseY - this.cameraY)) {
|
||||||
this.nodeDrag = true;
|
this.nodeDragging = node;
|
||||||
this.nodeDragged = node;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,8 +109,7 @@ var Diagrams = /** @class */ (function () {
|
||||||
};
|
};
|
||||||
Diagrams.prototype.onmouseup = function (ev) {
|
Diagrams.prototype.onmouseup = function (ev) {
|
||||||
this.panning = false;
|
this.panning = false;
|
||||||
this.nodeDrag = false;
|
this.nodeDragging = null;
|
||||||
this.nodeDragged = null;
|
|
||||||
};
|
};
|
||||||
Diagrams.prototype.drawBackground = function () {
|
Diagrams.prototype.drawBackground = function () {
|
||||||
this.ctx.fillStyle = "#D8D8D8";
|
this.ctx.fillStyle = "#D8D8D8";
|
||||||
|
@ -105,13 +121,23 @@ var Diagrams = /** @class */ (function () {
|
||||||
Diagrams.prototype.draw = function () {
|
Diagrams.prototype.draw = function () {
|
||||||
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||||
this.drawBackground();
|
this.drawBackground();
|
||||||
|
var fullCircleRadians = Math.PI + (Math.PI * 3);
|
||||||
for (var _i = 0, _a = this.nodes; _i < _a.length; _i++) {
|
for (var _i = 0, _a = this.nodes; _i < _a.length; _i++) {
|
||||||
var node = _a[_i];
|
var node = _a[_i];
|
||||||
this.ctx.fillStyle = "gray";
|
this.ctx.fillStyle = node.hover ? "#303030" : "#161616";
|
||||||
this.ctx.fillRect(node.x + this.cameraX, node.y + this.cameraY, node.width, node.height);
|
this.ctx.fillRect(node.x + this.cameraX, node.y + this.cameraY, node.width, node.height);
|
||||||
this.ctx.fillStyle = "black";
|
this.ctx.fillStyle = "#D3D3D3";
|
||||||
this.ctx.font = "30px Arial";
|
this.ctx.font = "30px Helvetica";
|
||||||
this.ctx.fillText(node.label, node.x + this.cameraX + node.height / 2, node.y + this.cameraY + node.height / 1.5);
|
this.ctx.fillText(node.label, node.x + this.cameraX + node.height / 2, node.y + this.cameraY + node.height / 1.5);
|
||||||
|
this.ctx.strokeStyle = "red";
|
||||||
|
this.ctx.fillStyle = "red";
|
||||||
|
this.ctx.beginPath();
|
||||||
|
this.ctx.arc(node.x + this.cameraX, node.y + node.height / 2 + this.cameraY, node.height / 3, 0, fullCircleRadians);
|
||||||
|
this.ctx.fill();
|
||||||
|
this.ctx.moveTo(node.x + node.width + this.cameraX, node.y + node.height / 2 + this.cameraY);
|
||||||
|
this.ctx.arc(node.x + node.width + this.cameraX, node.y + node.height / 2 + this.cameraY, node.height / 3, 0, fullCircleRadians);
|
||||||
|
this.ctx.fill();
|
||||||
|
this.ctx.closePath();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Diagrams.prototype.addNode = function (x, y, label) {
|
Diagrams.prototype.addNode = function (x, y, label) {
|
||||||
|
|
|
@ -5,6 +5,8 @@ class DiagramNode {
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
|
|
||||||
|
hover: boolean = false;
|
||||||
|
|
||||||
parents: Array<DiagramNode>;
|
parents: Array<DiagramNode>;
|
||||||
children: Array<DiagramNode>;
|
children: Array<DiagramNode>;
|
||||||
|
|
||||||
|
@ -22,7 +24,7 @@ class DiagramNode {
|
||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointInDiagram(x: number, y: number){
|
pointInNode(x: number, y: number){
|
||||||
if (x < this.x){
|
if (x < this.x){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -57,17 +59,17 @@ class Diagrams {
|
||||||
canvas: HTMLCanvasElement;
|
canvas: HTMLCanvasElement;
|
||||||
ctx: CanvasRenderingContext2D;
|
ctx: CanvasRenderingContext2D;
|
||||||
|
|
||||||
nodes: Array<DiagramNode>;
|
nodes: Array<DiagramNode> = new Array();
|
||||||
|
|
||||||
connections: Array<[DiagramNode, DiagramNode]>;
|
connections: Array<[DiagramNode, DiagramNode]> = new Array();
|
||||||
|
|
||||||
cameraX: number;
|
cameraX: number = 0;
|
||||||
cameraY: number;
|
cameraY: number = 0;
|
||||||
|
|
||||||
panning: boolean;
|
panning: boolean = false;
|
||||||
|
|
||||||
nodeDrag: boolean;
|
nodeDragging: DiagramNode | null = null;
|
||||||
nodeDragged: DiagramNode | null;
|
nodeHover: DiagramNode | null = null;
|
||||||
|
|
||||||
constructor(canvasId: string){
|
constructor(canvasId: string){
|
||||||
this.canvas = document.getElementById(canvasId) as HTMLCanvasElement;
|
this.canvas = document.getElementById(canvasId) as HTMLCanvasElement;
|
||||||
|
@ -80,31 +82,39 @@ class Diagrams {
|
||||||
}
|
}
|
||||||
_diagram = this;
|
_diagram = this;
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.ctx.font = "30px Arial";
|
this.ctx.font = "30px Helvetica";
|
||||||
this.canvas.onmousemove = diagramOnMouseMove;
|
this.canvas.onmousemove = diagramOnMouseMove;
|
||||||
this.canvas.onmousedown = diagramOnMouseDown;
|
this.canvas.onmousedown = diagramOnMouseDown;
|
||||||
this.canvas.onmouseup = diagramOnMouseUp;
|
this.canvas.onmouseup = diagramOnMouseUp;
|
||||||
window.onresize = diargramOnResize;
|
window.onresize = diargramOnResize;
|
||||||
|
|
||||||
this.nodes = new Array();
|
|
||||||
this.connections = new Array();
|
|
||||||
|
|
||||||
this.cameraX = 0;
|
|
||||||
this.cameraY = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onmousemove(ev: MouseEvent){
|
onmousemove(ev: MouseEvent){
|
||||||
|
let canvasRect = this.canvas.getBoundingClientRect();
|
||||||
|
let mouseX = ev.x - canvasRect.left;
|
||||||
|
let mouseY = ev.y - canvasRect.top;
|
||||||
|
|
||||||
if (this.panning){
|
if (this.panning){
|
||||||
this.cameraX += ev.movementX;
|
this.cameraX += ev.movementX;
|
||||||
this.cameraY += ev.movementY;
|
this.cameraY += ev.movementY;
|
||||||
}
|
}
|
||||||
if (this.nodeDrag){
|
else if (this.nodeDragging != null){
|
||||||
if (this.nodeDragged === null){
|
this.nodeDragging.x = mouseX - this.cameraX - this.nodeDragging.width / 2;
|
||||||
console.error("nodeDrag==true but nodeDragged==null");
|
this.nodeDragging.y = mouseY - this.cameraY - this.nodeDragging.height / 2;
|
||||||
return
|
}
|
||||||
|
else if (this.nodeHover != null){
|
||||||
|
if (!this.nodeHover.pointInNode(mouseX - this.cameraX, mouseY - this.cameraY)){
|
||||||
|
this.nodeHover.hover = false;
|
||||||
|
this.nodeHover = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (let node of this.nodes){
|
||||||
|
if (node.pointInNode(mouseX - this.cameraX, mouseY - this.cameraY)){
|
||||||
|
node.hover = true;
|
||||||
|
this.nodeHover = node;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.nodeDragged.x += ev.movementX;
|
|
||||||
this.nodeDragged.y += ev.movementY;
|
|
||||||
}
|
}
|
||||||
this.draw();
|
this.draw();
|
||||||
}
|
}
|
||||||
|
@ -117,9 +127,8 @@ class Diagrams {
|
||||||
let mouseX = ev.x - canvasRect.left;
|
let mouseX = ev.x - canvasRect.left;
|
||||||
let mouseY = ev.y - canvasRect.top;
|
let mouseY = ev.y - canvasRect.top;
|
||||||
for (let node of this.nodes){
|
for (let node of this.nodes){
|
||||||
if (node.pointInDiagram(mouseX, mouseY)) {
|
if (node.pointInNode(mouseX - this.cameraX, mouseY - this.cameraY)) {
|
||||||
this.nodeDrag = true;
|
this.nodeDragging = node;
|
||||||
this.nodeDragged = node;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,8 +138,7 @@ class Diagrams {
|
||||||
|
|
||||||
onmouseup(ev: MouseEvent){
|
onmouseup(ev: MouseEvent){
|
||||||
this.panning = false;
|
this.panning = false;
|
||||||
this.nodeDrag = false;
|
this.nodeDragging = null;
|
||||||
this.nodeDragged = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drawBackground(){
|
drawBackground(){
|
||||||
|
@ -144,16 +152,26 @@ class Diagrams {
|
||||||
draw(){
|
draw(){
|
||||||
this.ctx.clearRect(0,0, this.canvas.width, this.canvas.height);
|
this.ctx.clearRect(0,0, this.canvas.width, this.canvas.height);
|
||||||
this.drawBackground();
|
this.drawBackground();
|
||||||
|
let fullCircleRadians = Math.PI + (Math.PI * 3);
|
||||||
for (let node of this.nodes){
|
for (let node of this.nodes){
|
||||||
this.ctx.fillStyle = "gray";
|
this.ctx.fillStyle = node.hover ? "#303030" : "#161616";
|
||||||
this.ctx.fillRect(node.x + this.cameraX, node.y + this.cameraY, node.width, node.height);
|
this.ctx.fillRect(node.x + this.cameraX, node.y + this.cameraY, node.width, node.height);
|
||||||
this.ctx.fillStyle = "black";
|
this.ctx.fillStyle = "#D3D3D3";
|
||||||
this.ctx.font = "30px Arial";
|
this.ctx.font = "30px Helvetica";
|
||||||
this.ctx.fillText(
|
this.ctx.fillText(
|
||||||
node.label,
|
node.label,
|
||||||
node.x + this.cameraX + node.height / 2,
|
node.x + this.cameraX + node.height / 2,
|
||||||
node.y + this.cameraY + node.height / 1.5
|
node.y + this.cameraY + node.height / 1.5
|
||||||
);
|
);
|
||||||
|
this.ctx.strokeStyle = "red";
|
||||||
|
this.ctx.fillStyle = "red";
|
||||||
|
this.ctx.beginPath()
|
||||||
|
this.ctx.arc(node.x + this.cameraX, node.y + node.height / 2 + this.cameraY, node.height / 3, 0, fullCircleRadians);
|
||||||
|
this.ctx.fill();
|
||||||
|
this.ctx.moveTo(node.x + node.width + this.cameraX, node.y + node.height / 2 + this.cameraY);
|
||||||
|
this.ctx.arc(node.x + node.width + this.cameraX, node.y + node.height / 2 + this.cameraY, node.height / 3, 0, fullCircleRadians);
|
||||||
|
this.ctx.fill();
|
||||||
|
this.ctx.closePath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue