Skip to content

Instantly share code, notes, and snippets.

@clehner
Created June 23, 2011 04:56
Show Gist options
  • Save clehner/1041928 to your computer and use it in GitHub Desktop.
Save clehner/1041928 to your computer and use it in GitHub Desktop.
Draw simple shapes with points.
<!doctype html>
<html>
<head>
<title>Shape Maker</title>
<style type="text/css">
body {
font-family: Helvetica, Arial, sans-serif;
line-height: 1.5em;
font-size: 14px;
}
#canvas {
display: block;
width: 100%;
height: 70%;
border: 1px solid black;
}
#instructions {
float: left;
width: 40%;
}
#options1 {
float: left;
width: 30%;
}
#options2 {
float: left;
}
#grid-size {
width: 2em;
}
</style>
</head>
<body>
<canvas id="canvas" width="640" height="480"></canvas>
<p id="instructions">Click to drag points.<br>
Control-click to add points.<br>
Shift-click to remove points.</p>
<p id="options1">
Snap to grid: <input type="checkbox" id="snap-to-grid"><br>
Grid size: <input id="grid-size" value="12">
</p>
<p id="options2">
<button id="export-btn">Export</button>
<pre id="export-data"></pre>
</p>
<script>
function $(id) {
return document.getElementById(id);
}
var canvas = $("canvas");
var ctx = canvas.getContext("2d");
//ctx.translate(.5, .5);
var points = [];
ctx.fillStyle = "#cc0000";
var pointSize = 4;
var radius = pointSize / 2;
var snapToGrid = false;
var gridSize = 12;
function redraw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (points[0]) ctx.moveTo(points[0][0], points[0][1]);
ctx.beginPath();
points.forEach(function (point) {
ctx.lineTo(point[0], point[1]);
ctx.fillRect(point[0] - radius,
point[1] - radius, pointSize, pointSize);
});
ctx.closePath();
ctx.stroke();
}
function pointAt(x, y) {
for (var i = 0; i < points.length; i++) {
var point = points[i];
if (Math.abs(point[0] - x) <= radius &&
Math.abs(point[1] - y) <= radius) {
return point;
}
}
}
function addPoint(point) {
points.push(point);
redraw();
}
function removePoint(point) {
var i = points.indexOf(point);
if (~i) {
points.splice(i, 1);
}
redraw();
}
function snap(x, y) {
if (snapToGrid) {
x = Math.round(x / gridSize) * gridSize;
y = Math.round(y / gridSize) * gridSize;
}
return [x, y];
}
var dragTarget; // point being tragged
canvas.addEventListener("mousedown", function (e) {
var x = e.offsetX;
var y = e.offsetY;
if (e.ctrlKey) {
var point = snap(x, y);
addPoint(point);
startDraggingPoint(point);
} else if (e.shiftKey) {
var point = pointAt(x, y);
if (point) {
removePoint(point);
}
} else {
var point = pointAt(x, y);
if (point) {
startDraggingPoint(point);
}
}
}, false);
canvas.addEventListener("contextmenu", function (e) {
e.preventDefault();
}, false);
function startDraggingPoint(point) {
dragTarget = point;
canvas.addEventListener("mousemove", mouseMoveWithPoint, false);
window.addEventListener("mouseup", mouseUpWithPoint, false);
}
function mouseMoveWithPoint(e) {
var snapped = snap(e.offsetX, e.offsetY);
dragTarget[0] = snapped[0];
dragTarget[1] = snapped[1];
redraw();
}
function mouseUpWithPoint(e) {
dragTarget = null;
canvas.removeEventListener("mousemove", mouseMoveWithPoint, false);
window.removeEventListener("mouseup", mouseUpWithPoint, false);
}
function updateSize() {
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
redraw();
}
updateSize();
window.addEventListener("resize", updateSize);
$("snap-to-grid").addEventListener("change", function (e) {
snapToGrid = !!this.value;
}, false);
$("grid-size").addEventListener("keyup", function (e) {
gridSize = ~~this.value;
}, false);
$("export-btn").addEventListener("click", function (e) {
$("export-data").innerHTML = JSON.stringify(points);
}, false);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment