Created
September 1, 2015 21:26
-
-
Save bsparks/e8e19910c15e6caa2dea to your computer and use it in GitHub Desktop.
http://tommaitland.net/2012/07/online-graph-paper-tool/ couldn't find the source saved...
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Graph Paper</title> | |
<script type="text/javascript"> | |
/* Declare global variables */ | |
var spacing = 18; | |
var canvas; | |
var ctx; | |
var line; | |
var actions; | |
var popup; | |
var toolset_coord; | |
/* Called when everything is ready */ | |
function BodyLoad() { | |
/* Assign elements to variables */ | |
popup = document.getElementById('popup'); | |
canvas = document.getElementById('canvas'); | |
toolset_coord = document.getElementById('coord'); | |
/* Set up the canvas context (ctx) */ | |
ctx = canvas.getContext('2d'); | |
/* Set some canvas properties */ | |
canvas.width = window.innerWidth; | |
canvas.height = window.innerHeight; | |
canvas.w = canvas.width; // short-hand | |
canvas.h = canvas.height; // short-hand | |
canvas.mousedown = false; | |
/* Update the coordinates in the toolset */ | |
toolset_coord.update = function(x,y) { | |
this.innerHTML = x+','+y; | |
} | |
/* For keeping up with what we've done */ | |
actions = { | |
data: [], // empty on start | |
/* Store to the array */ | |
save: function() { | |
this.data[this.data.length] = { | |
x1: line.x1, | |
y1: line.y1, | |
x2: line.x2, | |
y2: line.y2, | |
type: 'line', | |
color: line.color, | |
width: line.width | |
} | |
}, | |
/* Loop through the array and re-draw lines */ | |
restore: function() { | |
for(var i=0;i<this.data.length;i++) | |
line.draw(this.data[i].x1, this.data[i].y1, this.data[i].x2, this.data[i].y2, 'restore', this.data[i].color, this.data[i].width); | |
}, | |
/* Remove the last action */ | |
undo: function() { | |
this.data.splice(this.data.length-1,1); | |
canvas.redraw(); | |
this.restore(); | |
}, | |
/* Wipe the slate clean */ | |
purge: function() { | |
for(var i=0;i<this.data.length;i++) | |
this.undo(); | |
}, | |
/* Export to PNG */ | |
png: function() { | |
alert('This will open the image in a new window. Right-click and choose Save As to download the image.'); | |
window.open(canvas.toDataURL('image/png'), 'Save as PNG'); | |
} | |
} | |
/* Draw lines with this */ | |
line = { | |
snap: true, // Snap to grid is enabled by default | |
color: 'blue', // Default color is blue | |
width: 2, // Default width is 2 | |
x1: 0, y1: 0, x2: 0, y2: 0, // Default coordinates are all 0,0 | |
/* Record our starting x,y */ | |
start: function(x,y) { | |
this.x1 = this.snap_to_grid(x); | |
this.y1 = this.snap_to_grid(y); | |
}, | |
/* Record our stopping x,y and draw */ | |
stop: function(x,y) { | |
this.x2 = this.snap_to_grid(x); | |
this.y2 = this.snap_to_grid(y); | |
this.draw(this.x1,this.y1,this.x2,this.y2,'line'); | |
}, | |
/* Draw a line */ | |
draw: function(x1,y1,x2,y2,type,color,width) { | |
/* If we don't know what type, let's assume it's a plain old line */ | |
if(type==undefined) | |
type = 'line'; | |
/* Only get the options if it's a plain old line */ | |
if(type=='line') | |
this.update_options(); | |
/* No color? It's this color! */ | |
if(color==undefined) | |
ctx.strokeStyle = this.color; | |
else | |
ctx.strokeStyle = color; | |
/* Even skinny people have width */ | |
if(width==undefined) | |
ctx.lineWidth = this.width; | |
else | |
ctx.lineWidth = width; | |
/* Draw the line */ | |
ctx.beginPath(); // Set up the path | |
ctx.moveTo(x1,y1); // The start of the line | |
ctx.lineTo(x2,y2); // The end of the line | |
ctx.closePath(); // Close the path | |
ctx.stroke(); // Draw it | |
/* If it's a plain line, save it and clean up and guide lines */ | |
if(type=='line') { | |
actions.save(); | |
canvas.redraw(); | |
actions.restore(); | |
} | |
}, | |
/* For drawing a handy guide line */ | |
guide: function(x,y) { | |
this.update_options(); | |
canvas.redraw(); | |
actions.restore(); | |
this.draw(this.x1,this.y1,this.snap_to_grid(x),this.snap_to_grid(y),'guide'); | |
}, | |
/* Calculate the nearest snap point (calculated by spacing) */ | |
snap_to_grid: function(p) { | |
if(!this.snap) | |
return false; | |
var p2; | |
for(var i=p-(spacing/2);i<p+(spacing/2);i++) | |
if(i%spacing==0) | |
p2 = i; | |
return p2; | |
}, | |
/* Get all the set options from the toolset */ | |
update_options: function() { | |
if(canvas.in_restore) | |
return false; | |
this.snap = document.getElementById('snap_to_grid').checked; | |
this.color = document.getElementById('line_color').value; | |
this.width = document.getElementById('line_width').value; | |
} | |
} | |
/* Clear out everything */ | |
canvas.clear = function() { | |
ctx.clearRect(0,0,this.width,this.height); | |
} | |
/* Redraw everything */ | |
canvas.redraw = function() { | |
this.clear(); | |
/* Prepare to draw the grid */ | |
ctx.beginPath(); | |
ctx.strokeStyle = 'lightblue'; | |
ctx.lineWidth = 1; | |
/* Vertical rule */ | |
for(var y=spacing;y<this.h;y=y+spacing) { | |
ctx.moveTo(0,y); | |
ctx.lineTo(this.w,y); | |
} | |
/* Horizontal rule */ | |
for(var x=spacing;x<this.w;x=x+spacing) { | |
ctx.moveTo(x,0); | |
ctx.lineTo(x,this.h); | |
} | |
/* Draw the grid */ | |
ctx.closePath(); | |
ctx.stroke(); | |
/* Restore any saved actions */ | |
actions.restore(); | |
} | |
/* When the user moves the mouse */ | |
canvas.onmousemove = function(e) { | |
if(!e) var e = window.event; | |
var x = e.clientX; | |
var y = e.clientY; | |
/* Update the coordinates */ | |
toolset_coord.update(x,y); | |
popup.show(x,y); | |
/* If we're drawing a line, show the guide line */ | |
if(this.mousedown) | |
line.guide(x,y); | |
} | |
/* When the clicker goes down (but not back up) */ | |
canvas.onmousedown = function(e) { | |
if(!e) var e = window.event; | |
/* Confirm it's down (handy for later) */ | |
this.mousedown = true; | |
var x = e.clientX; | |
var y = e.clientY; | |
/* Set the start of the line and show the pop-up */ | |
line.start(x,y); | |
popup.show(x,y); | |
} | |
/* When the clicker comes back up */ | |
canvas.onmouseup = function(e) { | |
if(!e) var e = window.event; | |
/* We're no longer holding down */ | |
this.mousedown = false; | |
var x = e.clientX; | |
var y = e.clientY; | |
/* Set the stop point and hide the pop-up */ | |
line.stop(x,y); | |
popup.hide(); | |
} | |
/* Show the pop-up */ | |
popup.show = function (x,y) { | |
if(!canvas.mousedown) | |
return false; | |
/* Offset it from the cursor a little bit */ | |
this.style.left = (x+30)+'px'; | |
this.style.top = (y+30)+'px'; | |
/* Display coordinates and distance */ | |
this.innerHTML = x+', '+y; | |
this.innerHTML += ', '+this.distance(line.x1,line.y1,line.snap_to_grid(x),line.snap_to_grid(y))+"cm"; | |
/* Show the pop-up */ | |
this.style.display = 'block'; | |
} | |
/* Use Pythagora's theorem to calculate distance */ | |
popup.distance = function(x1,y1,x2,y2) { | |
var scale_in = document.getElementById('scale_in').value; | |
var scale_frac = document.getElementById('scale_frac').value; | |
var scale = parseFloat(scale_in)+parseFloat(scale_frac); | |
var a = x1-x2; | |
var b = y1-y2; | |
if(a<0) a *= -1; | |
if(b<0) b *= -1; | |
var retval = Math.sqrt(Math.pow(a,2)+Math.pow(b,2)); | |
retval = Math.round(parseFloat(retval*scale/spacing)*100)/100; | |
return retval; | |
} | |
/* Hide the pop-up */ | |
popup.hide = function() { | |
this.style.display = 'none'; | |
} | |
/* Now that all functions and objects are set, draw the grid */ | |
canvas.redraw(); | |
} | |
function getDocumentPPI() { | |
var elem = document.createElement('div'); | |
elem.style.width = '1in'; | |
document.body.appendChild(elem); | |
var ppi = elem.offsetWidth; | |
//document.body.removeChild(elem); | |
return ppi; | |
} | |
</script> | |
<style type="text/css">body{margin:0;overflow:hidden;}#canvas{z-index:1;}#toolset{z-index:2;position:absolute;bottom:10px;right:10px;border:1px solid #000;background-color:#fff;font-family:sans-serif;font-size:90%;padding:10px;}#toolset p{margin:0;clear:both;line-height:2em;}#toolset p label{font-weight:bold;width:7em;float:left;display:inline-block;}#toolset p select{float:left;border:1px solid #000;color:blue;display:inline-block;}#toolset input[type=checkbox]{position:relative;top:0.5em;float:left;display:inline-block;}#popup{display:none;position:absolute;top:-100px;left:-100px;z-index:100;background-color:#fff;border:1px solid #000;padding:0.5em;}</style> | |
</head> | |
<body onload="BodyLoad();"> | |
<script> | |
var ppi = getDocumentPPI(); | |
</script> | |
<canvas id="canvas"></canvas> | |
<div id="popup"></div> | |
<div id="toolset"> | |
<p> | |
<button onclick="actions.undo()">Undo</button> | |
<button onclick="actions.purge()">Start Over</button> | |
<button onclick="actions.png()">Save</button> | |
</p> | |
<p> | |
<label>Coordinates</label> | |
<span id="coord">0,0</span> | |
</p> | |
<p> | |
<label>Snap to grid</label> | |
<input type="checkbox" id="snap_to_grid" checked /> | |
</p> | |
<p> | |
<label>Line Color</label> | |
<select id="line_color"> | |
<option>Black</option> | |
<option>Red</option> | |
<option>Orange</option> | |
<option>Yellow</option> | |
<option>Green</option> | |
<option selected>Blue</option> | |
<option>Purple</option> | |
</select> | |
</p> | |
<p> | |
<label>Line Width</label> | |
<select id="line_width"> | |
<option>1</option> | |
<option selected>2</option> | |
<option>3</option> | |
<option>4</option> | |
<option>5</option> | |
<option>6</option> | |
<option>7</option> | |
<option>8</option> | |
<option>9</option> | |
<option>10</option> | |
</select> | |
</p> | |
<p> | |
<label>Scale</label> | |
<select id="scale_in"> | |
<option>0</option> | |
<option selected>1</option> | |
<option>2</option> | |
<option>3</option> | |
<option>4</option> | |
<option>5</option> | |
<option>6</option> | |
<option>7</option> | |
<option>8</option> | |
<option>9</option> | |
<option>10</option> | |
<option>11</option> | |
<option>12</option> | |
</select> | |
<span style="float: left">.</span> | |
<select id="scale_frac"> | |
<option>0</option> | |
<option value=".25">25</option> | |
<option value=".5">5</option> | |
<option value=".75">75</option> | |
</select> | |
" | |
</p> | |
<p> | |
<label>Graph Rule</label> | |
<select id="spacing" onchange="spacing=(this.value*72)/2.5;canvas.redraw()"> | |
<option value=".25">2.5mm</option> | |
<option value=".5">5mm</option> | |
<option value=".75">7.5mm</option> | |
<option value="1">10mm</option> | |
</select> | |
</p> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment