Skip to content

Instantly share code, notes, and snippets.

@kevinfjbecker
Last active April 28, 2020 16:53
Show Gist options
  • Save kevinfjbecker/1606223 to your computer and use it in GitHub Desktop.
Save kevinfjbecker/1606223 to your computer and use it in GitHub Desktop.
Draggable Graph Nodes

This example use HTML5 Canvas to draw a simple graph.

The Node can be dragged to new positions on the canvas.

<!DOCTYPE html>
<html>
<head>
<script
class="jsbin"
src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<meta
charset=utf-8
/>
<title>Drag
a
Node</title>
<!--[if IE]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style>
article, aside, figure, footer, header, hgroup, menu, nav, section {
display: block;
}
</style>
</head>
<body>
<canvas
id="viewer"
width="800"
height="500"></canvas>
<script
src="graph-bfs.js"></script>
</body>
<script>
var graph = {
vertices: [{
edges: [1, 4],
x: 25,
y: 25
}, {
edges: [0, 2, 3, 4],
x: 75,
y: 25
}, {
edges: [1, 3],
x: 125,
y: 75
}, {
edges: [1, 2, 4],
x: 75,
y: 125
}, {
edges: [0, 1, 3],
x: 25,
y: 125
}]
};
graph.edgelist = (function (G) {
var i, j, edges = [],
e;
var contains = function (a, e) {
var i;
for (i = 0; i < a.length; i += 1) {
if (a[i].n === e.n && a[i].m === e.m) {
return true;
}
if (a[i].m === e.n && a[i].n === e.m) {
return true;
}
}
return false;
};
for (i = 0; i < G.vertices.length; i += 1) {
for (j = 0; j < G.vertices[i].edges.length; j += 1) {
e = {
n: i,
m: G.vertices[i].edges[j]
};
if (!contains(edges, {
n: i,
m: G.vertices[i].edges[j]
})) {
edges.push(e);
}
}
}
return edges;
})(graph);
graph.draw = function (ctx) {
var i;
var n, m;
for (i = 0; i < this.edgelist.length; i += 1) {
n = this.vertices[this.edgelist[i].n];
m = this.vertices[this.edgelist[i].m];
drawEdge(ctx, n.x, n.y, m.x, m.y);
}
for (i = 0; i < this.vertices.length; i += 1) {
n = this.vertices[i];
drawNode(ctx, n.x, n.y, n.isGrabbed ? 'black' : 'white');
}
};
var drawNode = function (ctx, x, y, color) {
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, 10, 0, Math.PI * 2, true);
ctx.fill();
ctx.stroke();
};
var drawEdge = function (ctx, x0, y0, x1, y1) {
ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.lineTo(x1, y1);
ctx.stroke();
};
graph.getTarget = function (x, y) {
var i;
for (i = 0; i < this.vertices.length; i += 1) {
if (contains(this.vertices[i], x, y)) {
return this.vertices[i];
}
}
return undefined;
};
var contains = function (vertex, x, y) {
var dx, dy;
dx = x - vertex.x;
dy = y - vertex.y;
return (Math.sqrt(dx * dx + dy * dy) < 10);
};
var x_grabOffset, y_grabOffset;
$('#viewer').mousedown(function () {
var offset, x, y, circle, target, search, ctx;
offset = $(this).offset();
x = event.pageX - offset.left;
y = event.pageY - offset.top;
target = graph.getTarget(x, y);
if (target !== undefined) {
target.isGrabbed = true;
}
x_grabOffset = target.x - x;
y_grabOffset = target.y - y;
ctx = $('#viewer')[0].getContext("2d");
ctx.clearRect(0, 0, 800, 500);
graph.draw(ctx);
}).mouseup(function () {
var i;
for (i = 0; i < graph.vertices.length; i += 1) {
graph.vertices[i].isGrabbed = false;
}
ctx = $('#viewer')[0].getContext("2d");
ctx.clearRect(0, 0, 800, 500);
graph.draw(ctx);
}).mousemove(function () {
var i, v, grabbed, offset, x, y;
for (i = 0; i < graph.vertices.length; i += 1) {
v = graph.vertices[i];
if (v.isGrabbed && v.isGrabbed === true) {
grabbed = v;
}
if (grabbed !== undefined) {
offset = $(this).offset();
x = event.pageX - offset.left;
y = event.pageY - offset.top;
grabbed.x = x - x_grabOffset;
grabbed.y = y - y_grabOffset;
}
ctx = $('#viewer')[0].getContext("2d");
ctx.clearRect(0, 0, 800, 500);
graph.draw(ctx);
}
});
(function () {
var canvas = document.getElementById("viewer");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
graph.draw(ctx);
}
})();
</script>
</html>
@sivatumma
Copy link

Well written. nothing less nothing more.

@PriyankaRose
Copy link

how to make it work in mobile?
I'm using it in phonegap application. Above code works great in chrome but not in firefox or mobile device.
Is there any alteration to be made in the code to make it work in all platforms?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment