Created
June 20, 2016 13:34
-
-
Save anxieux/eb87576db5884d6d2be7bc8a3f5afbe1 to your computer and use it in GitHub Desktop.
Canvas Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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