Last active
July 25, 2023 19:33
-
-
Save autioch/8b4ac4135ad2e17f5c100aab1f050d55 to your computer and use it in GitHub Desktop.
Millimeter paper creator
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 lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Document</title> | |
<style> | |
html, | |
body { | |
margin: 0; | |
padding: 0; | |
border: 0; | |
width: 99vw; | |
height: 99vh; | |
color: #ff8f3f; | |
background-color: #aaa; | |
} | |
canvas { | |
background-color: #fff; | |
} | |
button { | |
position: fixed; | |
top: 1vh; | |
left: 1vh; | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id="can"></canvas> | |
<button id="btn" onclick="saveImage()">Save Image</button> | |
<script> | |
// dimensions that need to be drawn | |
const expectedWidth = 211; | |
const expectedHeight = 268; | |
const DRAW_MM = false; | |
// canvas | |
const canvas = can; | |
const ctx = canvas.getContext('2d'); | |
// constants | |
const MARGIN = 20; | |
const MM_PIXEL = 10; | |
const ANTIALIAS = 0.5; | |
const space = 4; | |
const cmWidthCount = Math.ceil(expectedWidth / 10); | |
const cmHeightCount = Math.ceil(expectedHeight / 10); | |
const gridWidth = cmWidthCount * 10 * MM_PIXEL; | |
const gridHeight = cmHeightCount * 10 * MM_PIXEL; | |
console.log(expectedWidth, gridWidth, expectedHeight, gridHeight); | |
// set proper sizes | |
can.width = gridWidth + MARGIN + MARGIN; | |
can.height = gridHeight + MARGIN + MARGIN; | |
can.style.width = document.documentElement.style.width = document.body.style.width = can.width + 'px'; | |
can.style.height = document.documentElement.style.height = document.body.style.height = can.height + 'px'; | |
// background | |
ctx.fillStyle = '#fff'; | |
ctx.fillRect(0, 0, can.width, can.height); | |
ctx.strokeStyle = '#ff8f3f'; // orange | |
ctx.fillStyle = '#000'; | |
ctx.textAlign = "center"; | |
ctx.textBaseline = "middle"; | |
ctx.font = (3 * MM_PIXEL) + "px Arial"; | |
//helper functions | |
const lineH = (at) => { | |
ctx.moveTo(MARGIN - ANTIALIAS, MARGIN + at); | |
ctx.lineTo(MARGIN + ANTIALIAS + gridWidth, MARGIN + at); | |
} | |
const lineV = (at) => { | |
ctx.moveTo(MARGIN + at, MARGIN - ANTIALIAS); | |
ctx.lineTo(MARGIN + at, MARGIN + ANTIALIAS + gridHeight); | |
} | |
function saveImage() { | |
const link = document.createElement("a"); | |
link.download = "millimeter.png"; | |
link.href = canvas.toDataURL(); | |
link.click(); | |
} | |
// horizontal lines | |
for (let i = 0; i < cmHeightCount; i++) { | |
// Top strong line | |
ctx.beginPath(); | |
ctx.lineWidth = 3; | |
lineH(i * MM_PIXEL * 10 - ANTIALIAS); | |
ctx.stroke(); | |
// middle semi-strong line | |
ctx.beginPath(); | |
ctx.lineWidth = DRAW_MM ? 2 : 1; | |
lineH(i * MM_PIXEL * 10 + MM_PIXEL * 5 - 1 + (DRAW_MM ? 0 : 0.5)); | |
ctx.stroke(); | |
// mm small line | |
if (DRAW_MM) { | |
ctx.beginPath(); | |
ctx.lineWidth = 1; | |
for (let j = 0; j < 5; j++) { | |
lineH(i * MM_PIXEL * 10 + MM_PIXEL * 5 + j * MM_PIXEL - ANTIALIAS); | |
} | |
for (let j = 0; j < 5; j++) { | |
lineH(i * MM_PIXEL * 10 + j * MM_PIXEL - ANTIALIAS); | |
} | |
ctx.stroke(); | |
} | |
} | |
ctx.beginPath(); | |
ctx.lineWidth = 3; | |
lineH(cmHeightCount * MM_PIXEL * 10 - ANTIALIAS); | |
ctx.stroke(); | |
// vertical lines | |
for (let i = 0; i < cmWidthCount; i++) { | |
// Left strong line | |
ctx.beginPath(); | |
ctx.lineWidth = 3; | |
lineV(i * MM_PIXEL * 10 - ANTIALIAS); | |
ctx.stroke(); | |
// middle semi-strong line | |
ctx.beginPath(); | |
ctx.lineWidth = DRAW_MM ? 2 : 1; | |
lineV(i * MM_PIXEL * 10 + MM_PIXEL * 5 - 1 + (DRAW_MM ? 0 : 0.5)); | |
ctx.stroke(); | |
// mm small line | |
if (DRAW_MM) { | |
ctx.beginPath(); | |
ctx.lineWidth = 1; | |
for (let j = 0; j < 5; j++) { | |
lineV(i * MM_PIXEL * 10 + MM_PIXEL * 5 + j * MM_PIXEL - ANTIALIAS); | |
} | |
for (let j = 0; j < 5; j++) { | |
lineV(i * MM_PIXEL * 10 + j * MM_PIXEL - ANTIALIAS); | |
} | |
ctx.stroke(); | |
} | |
} | |
ctx.beginPath(); | |
ctx.lineWidth = 3; | |
lineV(cmWidthCount * MM_PIXEL * 10 - ANTIALIAS); | |
ctx.stroke(); | |
// texts | |
ctx.beginPath(); | |
for (let i = 2; i < cmHeightCount; i = i + 2) { //horizontal lines text | |
ctx.fillText(i.toString(), MARGIN, gridHeight - i * MM_PIXEL * 10 + MARGIN); | |
} | |
for (let i = 2; i < cmWidthCount; i = i + 2) { // vertical lines text | |
ctx.fillText(i.toString(), i * MM_PIXEL * 10 + MARGIN, gridHeight + MARGIN); | |
} | |
ctx.stroke(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment