-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathframe-grid-generator.html
120 lines (99 loc) · 4.8 KB
/
frame-grid-generator.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form>
Width: <select name="width"><option>8</option><option>16</option><option>32</option><option>64</option><option>128</option><option selected>256</option><option>512</option><option>1024</option></select>
Height: <select name="height"><option>8</option><option>16</option><option>32</option><option>64</option><option>128</option><option selected>256</option><option>512</option><option>1024</option></select>
Columns: <select name="columns"><option>1</option><option>2</option><option>3</option><option selected>4</option><option>5</option><option>6</option><option>7</option><option>8</option><option>9</option><option>10</option></select>
Rows: <select name="rows"><option>1</option><option>2</option><option>3</option><option selected>4</option><option>5</option><option>6</option><option>7</option><option>8</option><option>9</option><option>10</option></select>
Type: <select name="type"><option selected>frame</option><option>safe-rotate</option><option>checkerboard</option><option>numbered</option></select>
<a id="download" style="cursor: pointer"><u>Download image</u></a>
</form>
<br><canvas id="output" style="width: 512px; height: 512px"></canvas>
<script>
const viewWidth = 512
const viewHeight = 512
let formEl = document.querySelector("form")
formEl.addEventListener("change", generateFrame)
const widthEl = document.querySelector("[name=width]")
const heightEl = document.querySelector("[name=height]")
const columnsEl = document.querySelector("[name=columns]")
const rowsEl = document.querySelector("[name=rows]")
const typeEl = document.querySelector("[name=type]")
let canvasEl = document.querySelector("#output")
let ctx = canvasEl.getContext("2d")
document.getElementById("download").addEventListener("click", function() { downloadCanvas(this) })
generateFrame()
function generateFrame() {
const w = parseInt(widthEl.value, 10)
const h = parseInt(heightEl.value, 10)
const cols = parseInt(columnsEl.value, 10)
const rows = parseInt(rowsEl.value, 10)
const type = typeEl.value
const safeModifier = 0.58578643762 // 2 - sqrt(2) = 0.5857...
canvasEl.width = w
canvasEl.height = h
switch (type) {
case "safe-rotate":
ctx.fillStyle = "black"
ctx.fillRect(0, 0, w, h)
drawRectangles(w, h, rows, cols, Math.min(w/cols - 2, w/cols*safeModifier), Math.min(h/cols - 2, h/rows*safeModifier), "cut")
break
case "checkerboard":
case "numbered":
drawCheckerBoard(w, h, rows, cols, type === "numbered")
break
case "frame":
default:
drawRectangles(w, h, rows, cols, w/cols, h/rows)
break
}
}
function drawRectangles(w, h, rows, cols, rw, rh, op) {
const dw = w/cols
const dh = h/rows
ctx.strokeStyle = "black"
ctx.fillStyle = "black"
const oldGlobalCompositeOperation = ctx.globalCompositeOperation
if (op === "cut") { ctx.globalCompositeOperation = "destination-out" }
for (let c = 0; c < cols; c++) {
for (let r = 0; r < rows; r++) {
// offset the draw by 0.5 for better pixel alignment
// subtract 1 from rw,rh so we draw within the bounds
ctx.rect(Math.ceil((c + 0.5)*dw - rw*0.5) + 0.5, Math.ceil((r + 0.5)*dh - rh*0.5) + 0.5, Math.floor(rw - 1), Math.floor(rh - 1))
}
}
ctx.stroke()
if (op === "cut") { ctx.fill() }
ctx.globalCompositeOperation = oldGlobalCompositeOperation
}
function drawCheckerBoard(w, h, rows, cols, showNumbers) {
const dw = w/cols
const dh = h/rows
const factor = 0.6
ctx.font = Math.floor( Math.min(dw, dh)*factor ) + "px arial black"
ctx.textAlign = "center"
ctx.textBaseline = "middle"
for (let c = 0; c < cols; c++) {
for (let r = 0; r < rows; r++) {
const col = ((r & 1) ^ (c & 1)) ? "#444" : "white"
ctx.strokeStyle = ctx.fillStyle = col
ctx.fillRect(c*dw, r*dh, dw, dh)
if (showNumbers) {
const textCol = ((r & 1) ^ (c & 1)) ? "white" : "#444"
ctx.strokeStyle = ctx.fillStyle = textCol
ctx.fillText(String.fromCharCode(65 + r) + (c + 1).toString(), (c + 0.5)*dw, (r + 0.5)*dh)
}
}
}
}
function downloadCanvas(link) {
const filename = typeEl.value + "_" + columnsEl.value + 'x' + rowsEl.value + '_' + widthEl.value + 'x' + heightEl.value + '.png'
link.href = canvasEl.toDataURL()
link.download = filename
}
</script>
</body>
</html>