ThePlaceHolders/static/canvas.js

184 lines
5.1 KiB
JavaScript
Raw Normal View History

2024-10-09 23:18:42 -05:00
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
2024-11-05 11:51:17 -06:00
const CANVAS_SIZE = 500;
const DATA_SIZE = 200;
let scale = 1;
2024-11-06 02:02:36 -06:00
let offx = 0;
let offy = 0;
let clickx = 0;
let clicky = 0;
let mouseClicked = false;
2024-11-05 11:51:17 -06:00
// Array of [red, blue, green, transparency] * width * height
2024-11-06 02:02:36 -06:00
let image = new ImageData(DATA_SIZE, DATA_SIZE);
// Drawable image
let bitmap = null;
2024-11-13 18:29:40 -06:00
async function sendPixelData(x, y, color) {
try {
const response = await fetch("http://localhost:8080/savePixel", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ x: x, y: y, color: color })
});
if (response.ok) {
const updatedPixels = await response.json();
// Refresh the canvas with updated pixel data
updateCanvasWithData(updatedPixels);
} else {
console.error("Failed to send pixel data:", response.statusText);
}
} catch (error) {
console.error("Error sending pixel data:", error);
}
}
function updateCanvasWithData(pixelDataArray) {
// Clear the canvas image data
for (let x = 0; x < DATA_SIZE * DATA_SIZE * 4; x++) {
image.data[x] = 255; // Reset to white
}
// Set each pixel from the server data
pixelDataArray.forEach(pixel => {
setPixel(image.data, pixel.x, pixel.y, pixel.color);
});
// Redraw and update canvas
redraw();
draw();
}
canvas.addEventListener("mouseup", async (e) => {
if (e.button == 0 && mouseClicked) {
mouseClicked = false;
let mouse = mousePosition(e);
let cx = mouse.x;
let cy = mouse.y;
if (cx < 0 || cx > CANVAS_SIZE || cy < 0 || cy > CANVAS_SIZE) {
return;
}
const color = [0, 0, 255, 255];
setPixel(image.data, cx, cy, color);
// Send pixel data to the server
await sendPixelData(cx, cy, color);
}
});
2024-11-06 02:02:36 -06:00
window.addEventListener("load", async (e) => {
2024-11-06 18:02:08 -06:00
for (let x = 0; x < DATA_SIZE * DATA_SIZE * 4; x++) {
image.data[x] = 255;
}
2024-11-06 23:28:38 -06:00
ctx.imageSmoothingEnabled = false;
2024-11-06 02:02:36 -06:00
// Create drawable image, update it every half second
await redraw();
setInterval(redraw, 500);
setInterval(draw, 500);
});
async function redraw() {
2024-11-13 18:29:40 -06:00
// Create a new ImageBitmap based on the updated image data
2024-11-06 02:02:36 -06:00
bitmap = await createImageBitmap(image);
2024-11-13 18:29:40 -06:00
console.log("Redrawing canvas...");
2024-11-06 02:02:36 -06:00
}
2024-10-29 21:32:06 -05:00
2024-11-05 11:51:17 -06:00
// Color is an array of four numbers 0-255 (RGB + transparency)
function setPixel(data, x, y, color) {
let start = (y * DATA_SIZE + x) * 4;
for (let i = 0; i < 4; i++) {
data[start + i] = color[i];
2024-10-16 22:30:14 -05:00
}
}
2024-10-16 18:41:26 -05:00
2024-11-06 02:02:36 -06:00
function draw() {
2024-11-05 11:51:17 -06:00
ctx.fillStyle = "rgb(0 0 0 255)";
2024-11-06 23:28:38 -06:00
ctx.fillRect(0, 0, canvas.width, canvas.height);
2024-11-05 11:51:17 -06:00
let drawScale = CANVAS_SIZE / DATA_SIZE * scale;
ctx.scale(drawScale, drawScale);
2024-11-06 02:02:36 -06:00
ctx.drawImage(bitmap, offx, offy);
2024-11-05 11:51:17 -06:00
ctx.setTransform(1, 0, 0, 1, 0, 0);
2024-10-16 18:41:26 -05:00
}
2024-11-06 18:02:08 -06:00
function mousePosition(e) {
let x = e.clientX - canvas.getBoundingClientRect().left;
let y = e.clientY - canvas.getBoundingClientRect().top;
let cx = Math.round(x / (CANVAS_SIZE * scale) * DATA_SIZE - offx - 0.5);
let cy = Math.round(y / (CANVAS_SIZE * scale) * DATA_SIZE - offy - 0.5);
return {x: cx, y: cy};
}
2024-11-06 23:28:38 -06:00
function moveOffset(x, y) {
offx = Math.min(Math.max(x, -10 - DATA_SIZE / 2), DATA_SIZE + 10);
offy = Math.min(Math.max(y, -10 - DATA_SIZE / 2), DATA_SIZE + 10);
}
2024-11-05 11:51:17 -06:00
canvas.addEventListener("wheel", async (e) => {
2024-11-06 18:02:08 -06:00
let mouse = mousePosition(e);
2024-11-06 02:02:36 -06:00
let oldScale = scale;
2024-11-05 11:51:17 -06:00
if (e.deltaY < 0) {
scale += 0.1;
} else if (e.deltaY > 0) {
scale -= 0.1;
2024-10-30 16:30:24 -05:00
}
2024-11-06 23:28:38 -06:00
scale = Math.min(Math.max(scale, 0.5), 10);
2024-11-06 18:02:08 -06:00
let diff = (CANVAS_SIZE / oldScale) - (CANVAS_SIZE / scale);
let ratiox = (mouse.x - (CANVAS_SIZE / 2)) / CANVAS_SIZE;
let ratioy = (mouse.y - (CANVAS_SIZE / 2)) / CANVAS_SIZE;
2024-11-06 23:28:38 -06:00
moveOffset(diff * ratiox, diff* ratioy);
2024-11-06 02:02:36 -06:00
draw(image);
2024-10-30 16:30:24 -05:00
});
2024-11-05 11:51:17 -06:00
canvas.addEventListener("contextmenu", (e) => {
e.preventDefault();
})
2024-10-30 16:30:24 -05:00
2024-11-05 11:51:17 -06:00
canvas.addEventListener("mousedown", async (e) => {
// Left click
if (e.button == 0) {
2024-11-06 02:02:36 -06:00
mouseClicked = true;
setTimeout(() => {
mouseClicked = false;
}, 200);
}
});
canvas.addEventListener("mouseup", async (e) => {
if (e.button == 0 && mouseClicked) {
mouseClicked = false;
clickx = e.clientX;
clicky = e.clientY;
2024-11-06 18:02:08 -06:00
let mouse = mousePosition(e);
let cx = mouse.x;
let cy = mouse.y;
2024-11-05 11:51:17 -06:00
2024-11-06 02:02:36 -06:00
if (cx < 0 || cx > CANVAS_SIZE || cy < 0 || cy > CANVAS_SIZE) {
return;
}
2024-11-13 17:12:52 -06:00
setPixel(image.data, cx, cy, [0, 0, 255, 255]);
2024-11-06 02:02:36 -06:00
await redraw();
draw();
2024-10-30 16:30:24 -05:00
}
2024-10-23 18:09:48 -05:00
});
2024-11-06 02:02:36 -06:00
canvas.addEventListener("mousemove", async (e) => {
// `buttons` is a bitflag for some dumb reason
if (e.buttons & 1) {
offx += e.movementX * (1.0 / scale) * 0.45;
offy += e.movementY * (1.0 / scale) * 0.45;
2024-11-06 23:28:38 -06:00
moveOffset(
offx + e.movementX * (1.0 / scale) * 0.45,
offy + e.movementY * (1.0 / scale) * 0.45
);
2024-11-06 02:02:36 -06:00
draw(image);
}
});