Skip to content

Commit dcb656b

Browse files
Add files via upload
1 parent ff5a864 commit dcb656b

1 file changed

Lines changed: 295 additions & 0 deletions

File tree

drawing.html

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<!-- TO DO
4+
colour switch?
5+
retrieve uploaded images
6+
7+
-->
8+
<head>
9+
<meta charset="UTF-8">
10+
<title>Best Drawing</title>
11+
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
12+
<style>
13+
html, body {
14+
background-color: white;
15+
margin: 0; padding: 0; height: 100%;
16+
overflow: hidden;
17+
}
18+
body {
19+
display: grid;
20+
place-items: center;
21+
}
22+
button {
23+
margin: 0 5px;
24+
font-size: 1rem;
25+
}
26+
</style>
27+
</head>
28+
<body>
29+
<canvas id="c" width="600" height="600" style="border: 1px solid black; width: 600px; height: 600px; image-rendering: pixelated; touch-action: none; cursor: crosshair;"></canvas>
30+
<div id="buttons" style="display: flex; justify-content: center; align-items: center;">
31+
<img onclick="undo()" id="dogState" src="https://files.reimage.dev/filesghs/1fe80cbebf47/original" width="60" height="60">
32+
<img onclick="toggleBrushSize()" id="brushsize" src="https://files.reimage.dev/filesghs/e291bce2b8ae/original" width="60" height="60">
33+
<img onclick="toggleEraser()" id="toolpic" src="https://files.reimage.dev/filesghs/a459809638ee/original" width="60" height="60">
34+
<img onclick="upload()" id="savepic" src="https://files.reimage.dev/filesghs/ae4d320d50bb/original" width="60" height="60">
35+
<img onclick="clearCanvas()" id="clearState" src="https://files.reimage.dev/filesghs/1ffb5bbb8772/original" width="60" height="60">
36+
</div>
37+
<img src="https://files.reimage.dev/filesghs/d293f3c9c999/original" width="60" height="60" onclick="alert('designed by dr. art, M.D. in toronto ontario. press Z-X-C-V-B on your keyboard to activate functions remotely')">
38+
</div>
39+
<script>
40+
const API_KEY = "9c66638c1adf8ae793f0237f52f2b26355de5045da146f606322f966925a3625";
41+
const canvas = document.getElementById("c");
42+
const ctx = canvas.getContext("2d");
43+
ctx.imageSmoothingEnabled = false;
44+
45+
let undoStack = [];
46+
let drawing = false, x = 0, y = 0, lastX = 0, lastY = 0, lastTime = 0;
47+
let maxSize = 10;
48+
let currentBrushIndex = 0;
49+
let currentToolIndex = 0;
50+
let currentClearIndex = 0;
51+
let currentDogIndex = 0;
52+
let currentSaveIndex = 0;
53+
let isEraser = false;
54+
55+
56+
//brush size pics
57+
const brushSources = [
58+
"https://files.reimage.dev/filesghs/e291bce2b8ae/original", // large
59+
"https://files.reimage.dev/filesghs/f88f8323042b/original", // medium
60+
"https://files.reimage.dev/filesghs/a5509d0a4c71/original", // small
61+
"https://files.reimage.dev/filesghs/32535a74784d/original" // x-large
62+
];
63+
64+
//tool pics
65+
const toolSources = [
66+
"https://files.reimage.dev/filesghs/a459809638ee/original", // pencil
67+
"https://files.reimage.dev/filesghs/f277250a14fb/original", // eraser
68+
];
69+
70+
//clear pics
71+
const clearSources = [
72+
"https://files.reimage.dev/filesghs/1ffb5bbb8772/original", // clear!
73+
"https://files.reimage.dev/filesghs/7144fa6f69d2/original", // you sure?
74+
];
75+
76+
//dog pics
77+
const dogSources = [
78+
"https://files.reimage.dev/filesghs/1fe80cbebf47/original", // rest dog
79+
"https://files.reimage.dev/filesghs/4c91ab000b44/original", // barf dog
80+
];
81+
82+
//save pics
83+
const saveSources = [
84+
"https://files.reimage.dev/filesghs/ae4d320d50bb/original", // save icon
85+
"https://files.reimage.dev/filesghs/b7f26beb6c54/original", // save successful
86+
];
87+
88+
// Upload function
89+
function upload() {
90+
canvas.toBlob(async blob => {
91+
const formData = new FormData();
92+
formData.append("file", blob, "drawing.png");
93+
formData.append("tags", JSON.stringify(["drawing"]));
94+
95+
try {
96+
const res = await fetch("https://api.reimage.dev/upload/", {
97+
method: "POST",
98+
headers: { Authorization: `Bearer ${API_KEY}` },
99+
body: formData
100+
});
101+
const data = await res.json();
102+
} catch (err) {
103+
console.error("Upload failed.");
104+
alert("Upload failed.");
105+
}
106+
}, "image/png");
107+
const saveElement = document.getElementById('savepic');
108+
currentSaveIndex = (currentSaveIndex + 1) % saveSources.length;
109+
saveElement.src = saveSources[currentSaveIndex];
110+
if (currentSaveIndex === 1) {
111+
setTimeout(() => {
112+
currentSaveIndex = 0;
113+
saveElement.src = saveSources[0];
114+
}, 5000);}
115+
}
116+
117+
//undo Function
118+
function undo() {
119+
if (undoStack.length > 0) {
120+
const imageData = undoStack.pop();
121+
ctx.putImageData(imageData, 0, 0);
122+
}
123+
const dogElement = document.getElementById('dogState');
124+
currentDogIndex = (currentDogIndex + 1) % dogSources.length;
125+
dogElement.src = dogSources[currentDogIndex];
126+
if (currentDogIndex === 1) {
127+
setTimeout(() => {
128+
currentDogIndex = 0;
129+
dogElement.src = dogSources[0];
130+
}, 175);
131+
}
132+
}
133+
134+
// UNDO LIMIT
135+
if (undoStack.length > 3) {
136+
undoStack.shift();
137+
}
138+
139+
//clear canvas function
140+
function clearCanvas() {
141+
if (currentClearIndex === 1) {
142+
ctx.clearRect(0, 0, canvas.width, canvas.height);
143+
currentClearIndex = 0;
144+
document.getElementById('clearState').src = clearSources[0];
145+
} else {
146+
preClear();
147+
}
148+
}
149+
//confirmation for clearing
150+
function preClear() {
151+
undoStack.push(ctx.getImageData(0, 0, canvas.width, canvas.height));
152+
if (undoStack.length > 10) undoStack.shift(); // optional limit
153+
const clearElement = document.getElementById('clearState');
154+
currentClearIndex = (currentClearIndex + 1) % clearSources.length;
155+
clearElement.src = clearSources[currentClearIndex];
156+
if (currentClearIndex === 1) {
157+
setTimeout(() => {
158+
currentClearIndex = 0;
159+
clearElement.src = clearSources[0];
160+
}, 2000);
161+
}
162+
}
163+
164+
// Function to toggle brush size between 6, 10, and 3
165+
function toggleBrushSize() {
166+
maxSize = (maxSize === 10) ? 6 :
167+
(maxSize === 6) ? 3 :
168+
(maxSize === 3) ? 20 : 10;
169+
const brushElement = document.getElementById('brushsize');
170+
currentBrushIndex = (currentBrushIndex + 1) % brushSources.length;
171+
brushElement.src = brushSources[currentBrushIndex];
172+
}
173+
174+
// Function to toggle between drawing and erasing mode
175+
function toggleEraser() {
176+
isEraser = !isEraser;
177+
const toolElement = document.getElementById('toolpic');
178+
currentToolIndex = (currentToolIndex + 1) % toolSources.length;
179+
toolElement.src = toolSources[currentToolIndex];
180+
}
181+
182+
// Function to calculate velocity-based brush size
183+
function calculateBrushSize(newX, newY) {
184+
const now = performance.now();
185+
const deltaTime = now - lastTime;
186+
const dx = newX - lastX;
187+
const dy = newY - lastY;
188+
const distance = Math.sqrt(dx * dx + dy * dy);
189+
const speed = distance / (deltaTime || 1);
190+
191+
const minSize = 0;
192+
const velocity = Math.min(speed, 100); // clamp max speed
193+
const size = maxSize - (velocity / 2) * (maxSize - minSize);
194+
195+
lastX = newX;
196+
lastY = newY;
197+
lastTime = now;
198+
199+
return size;
200+
}
201+
202+
203+
204+
// Drawing function
205+
206+
function drawLine(newX, newY,) {
207+
const size = calculateBrushSize(newX, newY,);
208+
ctx.lineWidth = size;
209+
ctx.beginPath();
210+
ctx.moveTo(x, y);
211+
ctx.lineTo(newX, newY);
212+
ctx.stroke();
213+
ctx.lineCap = "square";
214+
}
215+
216+
// Mouse events for drawing
217+
218+
219+
220+
canvas.onmousedown = e => {
221+
undoStack.push(ctx.getImageData(0, 0, canvas.width, canvas.height));
222+
if (undoStack.length > 10) undoStack.shift(); // optional limit
223+
drawing = true;
224+
x = e.offsetX;
225+
y = e.offsetY;
226+
lastX = x;
227+
lastY = y;
228+
lastTime = performance.now();
229+
};
230+
231+
232+
canvas.onmouseup = () => { drawing = false; };
233+
canvas.onmousemove = e => {
234+
if (drawing) {
235+
if (isEraser) {
236+
ctx.clearRect(e.offsetX - maxSize / 2, e.offsetY - maxSize / 2, (maxSize*2), (maxSize*2));
237+
} else {
238+
drawLine(e.offsetX, e.offsetY);
239+
}
240+
x = e.offsetX;
241+
y = e.offsetY;
242+
}};
243+
244+
// Mobile touch events for drawing
245+
canvas.addEventListener('touchstart', e => {
246+
e.preventDefault();
247+
undoStack.push(ctx.getImageData(0, 0, canvas.width, canvas.height));
248+
if (undoStack.length > 10) undoStack.shift(); // optional limit
249+
const touch = e.touches[0];
250+
const rect = canvas.getBoundingClientRect();
251+
x = touch.clientX - rect.left;
252+
y = touch.clientY - rect.top;
253+
lastX = x;
254+
lastY = y;
255+
lastTime = performance.now();
256+
drawing = true;
257+
});
258+
canvas.addEventListener('touchmove', e => {
259+
if (!drawing) return;
260+
e.preventDefault();
261+
const touch = e.touches[0];
262+
const rect = canvas.getBoundingClientRect();
263+
const newX = touch.clientX - rect.left;
264+
const newY = touch.clientY - rect.top;
265+
if (isEraser) {
266+
ctx.clearRect(newX - maxSize / 2, newY - maxSize / 2, (maxSize*2), (maxSize*2));
267+
} else {
268+
drawLine(newX, newY);
269+
}
270+
x = newX;
271+
y = newY;
272+
});
273+
canvas.addEventListener('touchend', () => { drawing = false; });
274+
275+
addEventListener("keydown", (event) => {
276+
if (event.key === "b" || event.key === "B") {
277+
clearCanvas();
278+
}
279+
if (event.key === "v" || event.key === "V") {
280+
upload();
281+
}
282+
if (event.key === "x" || event.key === "X") {
283+
toggleBrushSize();
284+
}
285+
if (event.key === "c" || event.key === "C") {
286+
toggleEraser();
287+
}
288+
if (event.key === "z" || event.key === "Z") {
289+
undo();
290+
}
291+
292+
});
293+
</script>
294+
</body>
295+
</html>

0 commit comments

Comments
 (0)