]>
Commit | Line | Data |
---|---|---|
1 | // App Config | |
2 | ||
3 | const kEntrypoint = "breadsticks"; | |
4 | const kGap = 50; | |
5 | const kDrawDelay = 100; | |
6 | const kDarkDrawingColor = '#fff'; | |
7 | const kLightDrawingColor = '#000'; | |
8 | ||
9 | /*********************************************** | |
10 | * Breadstick generates a matrix of points | |
11 | * and assigns a vector to each entry | |
12 | * and then draws them | |
13 | ***********************************************/ | |
14 | ||
15 | /* | |
16 | * Generate field of points in which to draw | |
17 | */ | |
18 | ||
19 | // Updates the field object using a canvas | |
20 | ||
21 | const updateFieldFromCanvas = (field, canvas) => { | |
22 | updateFieldFromRect(field, canvas.getBoundingClientRect()); | |
23 | ||
24 | canvas.width = window.innerWidth; | |
25 | canvas.height = window.innerHeight; | |
26 | ||
27 | window.addEventListener('resize', () => { | |
28 | canvas.width = window.innerWidth; | |
29 | canvas.height = window.innerHeight; | |
30 | updateFieldFromRect(field, canvas.getBoundingClientRect()); | |
31 | }); | |
32 | }; | |
33 | ||
34 | // Updates a field object using a rect | |
35 | ||
36 | const updateFieldFromRect = (field, rect) => { | |
37 | field.width = rect.width; | |
38 | field.height = rect.height; | |
39 | } | |
40 | ||
41 | /* | |
42 | * Generate the matrix of vectors | |
43 | */ | |
44 | ||
45 | // Updates a matrix for a given field using the mouse | |
46 | ||
47 | ||
48 | const updateFieldMatrixFromMouse = (field, matrix, gap = 50) => { | |
49 | const mousePosition = { | |
50 | x: 0, | |
51 | y: 0 | |
52 | }; | |
53 | ||
54 | fillMatrix(matrix, mousePosition.x, mousePosition.y, field.width, field.height, gap); | |
55 | ||
56 | const updateMousePosition = document.addEventListener('mousemove', (event) => { | |
57 | mousePosition.x = event.offsetX; | |
58 | mousePosition.y = event.offsetY; | |
59 | fillMatrix(matrix, mousePosition.x, mousePosition.y, field.width, field.height, gap); | |
60 | }); | |
61 | }; | |
62 | ||
63 | // Gets a matrix by calculating the offset between position and field. | |
64 | ||
65 | const fillMatrix = (matrix, x, y, w, h, gap = 50) => { | |
66 | for (let i = 0; i < w / gap; ++i) { | |
67 | matrix[i] = []; | |
68 | for (let j = 0; j < h / gap; ++j) { | |
69 | let targetX = i * gap; | |
70 | let targetY = j * gap; | |
71 | matrix[i][j] = calculateOffsetVector(x, y, targetX, targetY, w, h); | |
72 | } | |
73 | } | |
74 | }; | |
75 | ||
76 | // Calculates the offset vector of a point | |
77 | const calculateOffsetVector = (sourceX, sourceY, targetX, targetY, w, h) => { | |
78 | const xOffset = targetX - sourceX; | |
79 | const yOffset = targetY - sourceY; | |
80 | ||
81 | return { | |
82 | position: { | |
83 | x: targetX, | |
84 | y: targetY | |
85 | }, | |
86 | angle: Math.atan2(xOffset, yOffset), | |
87 | magnitude: Math.sqrt(Math.pow(xOffset, 2) + Math.pow(yOffset, 2)) | |
88 | }; | |
89 | }; | |
90 | ||
91 | ||
92 | /* | |
93 | * Drawing | |
94 | */ | |
95 | ||
96 | // draw a vector from center | |
97 | const drawVector = (context, i, j, vector) => { | |
98 | const origin = { | |
99 | x: context.canvas.width / 2, | |
100 | y: context.canvas.height / 2 | |
101 | }; | |
102 | const x = origin.x - vector.magnitude * Math.cos(vector.angle); | |
103 | const y = origin.y - vector.magnitude * Math.sin(vector.angle); | |
104 | context.beginPath(); | |
105 | context.moveTo(vector.position.x, vector.position.y); | |
106 | context.lineTo(Math.round(x), Math.round(y)); | |
107 | context.stroke(); | |
108 | }; | |
109 | ||
110 | // Gets the color depending on the team | |
111 | ||
112 | const getColor = () => { | |
113 | if (window.matchMedia('(prefers-color-scheme: dark)').matches) { | |
114 | return kDarkDrawingColor; | |
115 | } | |
116 | ||
117 | return kLightDrawingColor; | |
118 | }; | |
119 | ||
120 | ||
121 | // Draws field on canvas | |
122 | ||
123 | const drawFieldMatrixOnCanvas = (matrix, context) => { | |
124 | ||
125 | context.strokeStyle = getColor(); | |
126 | context.clearRect(0, 0, context.canvas.width, context.canvas.height); | |
127 | ||
128 | for (let i = 0; i < matrix.length; ++i) { | |
129 | const row = matrix[i]; | |
130 | for (let j = 0; j < row.length; ++j) { | |
131 | const vector = row[j] | |
132 | ||
133 | if (vector) { | |
134 | drawVector(context, i, j, vector); | |
135 | } | |
136 | } | |
137 | } | |
138 | }; | |
139 | ||
140 | /* | |
141 | * Entrypoint | |
142 | */ | |
143 | ||
144 | const run = () => { | |
145 | ||
146 | const field = { | |
147 | width: 0, | |
148 | height: 0 | |
149 | }; | |
150 | const canvas = document.getElementById(kEntrypoint); | |
151 | ||
152 | updateFieldFromCanvas(field, canvas); | |
153 | ||
154 | const matrix = [[]]; | |
155 | updateFieldMatrixFromMouse(field, matrix, kGap); | |
156 | ||
157 | const context = canvas.getContext('2d'); | |
158 | const drawFunction = () => { | |
159 | drawFieldMatrixOnCanvas(matrix, context); | |
160 | setTimeout(drawFunction, kDrawDelay); | |
161 | } | |
162 | ||
163 | setTimeout(drawFunction, 0); | |
164 | }; | |
165 | ||
166 | window.addEventListener('load', run); |