Skip to content

Instantly share code, notes, and snippets.

@anxieux
Created June 20, 2016 13:34
Show Gist options
  • Save anxieux/eb87576db5884d6d2be7bc8a3f5afbe1 to your computer and use it in GitHub Desktop.
Save anxieux/eb87576db5884d6d2be7bc8a3f5afbe1 to your computer and use it in GitHub Desktop.
Canvas Example
<html>
<head>
<script src="script.js"></script>
<style type="text/css">
canvas { border: 1px dotted black; }
</style>
</head>
<body onload="onload();">
<p> Hi! </p>
<canvas id="canvas" width="500" height="500">
</canvas>
</body>
<html>
var StageMode = Object.freeze({
cNone: "none",
cDragPt: "drag",
cSelPt: "select",
cAddPt: "add"
});
var stage = {
polygon: [[100,100], [120,100], [120, 400], [300, 200]],
line: [[50, 50], [500, 800]],
hlPt: undefined,
selPt: undefined,
ctx: undefined,
mode: StageMode.cNone,
draw: function() {
if (this.ctx !== undefined) {
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
if (this.hlPt !== undefined) {
drawPt(this.polygon[this.hlPt], this.ctx, 4, "gray");
}
if (this.selPt !== undefined && this.selPt !== this.hlPt) {
drawPt(this.polygon[this.selPt], this.ctx, 4, "blue");
}
drawPolygon(this.polygon, this.ctx, "black");
drawPolygon(this.line, this.ctx, "blue");
drawPolygon(reflectPolygon(this.polygon, this.line), this.ctx, "green");
drawPolygon(shiftPolygon(this.polygon, [-10, 30]), this.ctx, "orange");
}
},
findHLPt: function(x, y) {
var newHLPt = undefined;
for (var i=0; i < this.polygon.length; ++i) {
if (dist2(this.polygon[i], [x, y]) <= 9) {
newHLPt = i;
break;
}
}
if (newHLPt !== this.hlPt) {
this.hlPt = newHLPt;
this.draw();
}
},
moveSelPt: function(x, y) {
if (this.selPt !== undefined) {
this.polygon[this.selPt][0] = x;
this.polygon[this.selPt][1] = y;
this.draw();
}
},
beginDragPt: function() {
if (this.hlPt !== undefined) {
this.mode = StageMode.cDragPt;
this.selPt = this.hlPt;
}
},
endDragPt: function() {
if (this.mode === StageMode.cDragPt) {
this.mode = StageMode.cNone;
this.selPt = undefined;
}
},
selectPt: function() {
this.mode = (this.hlPt !== undefined) ? StageMode.cSelPt : StageMode.cNone;
this.selPt = this.hlPt;
this.draw();
},
deletePt: function() {
if (this.mode === StageMode.cSelPt && this.selPt !== undefined) {
this.polygon.splice(this.selPt, 1);
if (this.hlPt === this.selPt) {
this.hlPt = undefined;
} else if (this.hlPt > this.selPt) {
--this.hlPt;
}
this.selPt = undefined;
this.draw();
}
},
insertPt: function() {
}
};
function onload() {
var canvas = document.getElementById('canvas');
canvas.addEventListener("mousemove", mouseMoveHandler, false);
canvas.addEventListener("mousedown", mouseDownHandler, false);
canvas.addEventListener("click", mouseClickHandler, false);
document.addEventListener("mouseup", mouseUpHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
stage.ctx = canvas.getContext('2d');
stage.draw();
}
function drawPt(pt, ctx, radius, color) {
ctx.beginPath();
ctx.arc(pt[0], pt[1], radius, 0, Math.PI*4);
ctx.fillStyle = color;
ctx.fill();
}
function drawPolygon(pts, ctx, color) {
for (var i=0; i < pts.length; ++i) {
drawPt(pts[i], ctx, 2, color);
}
ctx.beginPath();
ctx.moveTo(pts[0][0], pts[0][1]);
for (var i=1; i < pts.length; ++i) {
ctx.lineTo(pts[i][0], pts[i][1]);
}
ctx.lineTo(pts[0][0], pts[0][1]);
ctx.strokeStyle = color;
ctx.stroke();
}
function apply(pts, op) {
var result = [];
for (var i=0; i < pts.length; ++i) {
result[i] = op(pts[i]);
}
return result;
}
function shiftPt(pt, shift) {
return [pt[0] + shift[0], pt[1] + shift[1]];
}
function shiftPolygon(pts, shift) {
return apply(pts,
function(pt) {return shiftPt(pt, shift)});
}
function opPt(pt) {
return [-pt[0], -pt[1]];
}
function sq(x) {
return x*x;
}
function dist2(pt1, pt2) {
if (pt2 === undefined) {
pt2 = [0, 0];
}
var pt = shiftPt(pt1, opPt(pt2));
return sq(pt[0]) + sq(pt[1]);
}
function reflectPt(pt, line) {
var lineDir = shiftPt(line[1], opPt(line[0]));
var lineDirDist2 = dist2(lineDir);
var c1 = 2*lineDir[0]*lineDir[1] / lineDirDist2;
var c2 = (sq(lineDir[0]) - sq(lineDir[1])) / lineDirDist2;
var pt1 = shiftPt(pt, opPt(line[0]));
var pt2 = [
pt1[0] * c2 + pt1[1] * c1,
pt1[0] * c1 - pt1[1] * c2
];
return shiftPt(pt2, line[0]);
}
function reflectPolygon(pts, line) {
return apply(pts,
function(pt) {return reflectPt(pt, line)});
}
function mouseMoveHandler(e) {
if (stage.mode === StageMode.cDragPt) {
stage.moveSelPt(e.offsetX, e.offsetY);
} else {
stage.findHLPt(e.offsetX, e.offsetY);
}
}
function mouseDownHandler(e) {
stage.beginDragPt();
}
function mouseUpHandler(e) {
stage.endDragPt();
}
function mouseClickHandler(e) {
stage.selectPt();
}
function keyUpHandler(e) {
if (e.key === "Delete") {
stage.deletePt();
} else if (e.key === "Insert") {
stage.insertPt();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment