remove all 3d effects and functionality and any related to 3d properties. convert this code into a 2d drawing plane. remove all uneccesarry elements. make simple schematics line drawing editor with snapable properre grid. make some menu at top to set grid size in units and dimension in px em etc…:
<html lang=“en”>
<head>
<meta charset=“UTF-8”>
<title>drawacube</title>
<style>
canvas {
display: block;
margin: auto;
}
</style>
</head>
<body>
<canvas id=“canvas”></canvas>
<script>
const canvas = document.getElementById(“canvas”);
const ctx = canvas.getContext(“2d”);

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

const rotationSpeed = 0.1;
const gridSize = 50;
const gridSpacing = 25;
const zoomStep = 10;
const minZoom = 100;
const maxZoom = 2000;
const centerFocus = 100;

let grid = [];
for (let x = -gridSize; x <= gridSize; x += gridSpacing) {
for (let y = -gridSize; y <= gridSize; y += gridSpacing) {
for (let z = -gridSize; z <= gridSize; z += gridSpacing) {
grid.push({ x, y, z });
}
}
}

let lastClickedPoint = null;
const clickedPoints = [];
let angleX = 95.03;
let angleY = 119.99;
let zoom = 100;
let dragStart = null;

let offset = {
x: gridSpacing / 25,
y: gridSpacing / 25,
z: 0
};

function rotate(point, angleX, angleY) {
const { x, y, z } = point;

let centeredX = x - offset.x;
let centeredY = y - offset.y;
let centeredZ = z - offset.z;

const cosX = Math.cos(angleX);
const sinX = Math.sin(angleX);
const cosY = Math.cos(angleY);
const sinY = Math.sin(angleY);

const newY = centeredY * cosX - centeredZ * sinX;
const newZ = centeredY * sinX + centeredZ * cosX;
const newX = centeredX * cosY - newZ * sinY;
const newZ2 = centeredX * sinY + newZ * cosY;

return {
x: newX + offset.x,
y: newY + offset.y,
z: newZ2 + offset.z
};
}


function project(point, width, height) {
const { x, y, z } = point;

const scale = zoom / (centerFocus + z);
const newX = x * scale + width / 2;
const newY = y * scale + height / 2;

return { x: newX, y: newY, scale };
}

function findClosestPoint(point) {
const threshold = 20;
let minDist = Infinity;
let minIndex = -1;

for (let i = 0; i < grid.length; i++) {
const projected = project(rotate(grid[i], angleX, angleY), canvas.width, canvas.height);
const dx = point.x - projected.x;
const dy = point.y - projected.y;
const dist = Math.sqrt(dx * dx + dy * dy);

if (dist < minDist && dist <= threshold) {
minDist = dist;
minIndex = i;
}
}

return minIndex !== -1 ? grid[minIndex] : null;
}

let mouseDown = false;
let activeLine = null;
const lines = [];

canvas.addEventListener(“wheel”, (e) => {
e.preventDefault();
zoom += e.deltaY * -0.1 * zoomStep;
zoom = Math.min(Math.max(zoom, minZoom), maxZoom); // Limit zoom to min and max thresholds
});

canvas.addEventListener(“mousedown”, (e) => {
dragStart = { x: e.clientX, y: e.clientY };
});

canvas.addEventListener(“mousemove”, (e) => {
if (dragStart) {
const deltaX = e.clientX - dragStart.x;
const deltaY = e.clientY - dragStart.y;
angleX += deltaY * 0.01;
angleY += deltaX * 0.01;
dragStart = { x: e.clientX, y: e.clientY };
}
});

canvas.addEventListener(“mouseup”, (e) => {
mouseDown = false;
dragStart = null;
if (activeLine !== null) {
const canvasRect = canvas.getBoundingClientRect();
const mouseX = e.clientX - canvasRect.left;
const mouseY = e.clientY - canvasRect.top;
const endPoint = findClosestPoint({ x: mouseX, y: mouseY });

if (endPoint !== activeLine[activeLine.length - 1]) {
activeLine.push(endPoint);
lines.push(activeLine);
}
activeLine = null;
}

if (lastClickedPoint !== null) {
const canvasRect = canvas.getBoundingClientRect();
const mouseX = e.clientX - canvasRect.left;
const mouseY = e.clientY - canvasRect.top;
const clickedPoint = findClosestPoint({ x: mouseX, y: mouseY });

if (clickedPoint !== null) {
if (lastClickedPoint === clickedPoint) {
lastClickedPoint = null;
} else {
lines.push([lastClickedPoint, clickedPoint]);
clickedPoints.push(clickedPoint);
lastClickedPoint = null;
}
}
} else {
const canvasRect = canvas.getBoundingClientRect();
const mouseX = e.clientX - canvasRect.left;
const mouseY = e.clientY - canvasRect.top;
const clickedPoint = findClosestPoint({ x: mouseX, y: mouseY });

if (clickedPoint !== null) {
lastClickedPoint = clickedPoint;
clickedPoints.push(clickedPoint);
}
}
});
function drawLine(line) {
ctx.beginPath();

for (let i = 0; i < line.length - 1; i++) {
const projectedStart = project(rotate(line[i], angleX, angleY), canvas.width, canvas.height);
const projectedEnd = project(rotate(line[i + 1], angleX, angleY), canvas.width, canvas.height);

ctx.moveTo(projectedStart.x, projectedStart.y);
ctx.lineTo(projectedEnd.x, projectedEnd.y);
}

ctx.strokeStyle = “rgba(25,200,25,0.2)”;
ctx.lineWidth = 2;
ctx.stroke();
}

function calculateGridCenter(grid) {
let totalX = 0;
let totalY = 0;
let totalZ = 0;
const pointsCount = grid.length;

for (const point of grid) {
totalX += point.x;
totalY += point.y;
totalZ += point.z;
}

return {
x: totalX / pointsCount,
y: totalY / pointsCount,
z: totalZ / pointsCount,
};
}

function draw() {
ctx.fillStyle = “rgba(1,2,1,0.8)”;
ctx.fillRect(0, 0, canvas.width, canvas.height);

for (const point of grid) {
const rotated = rotate(point, angleX, angleY);
const projected = project(rotated, canvas.width, canvas.height);

ctx.beginPath();
if (projected.scale > 0) {
ctx.arc(projected.x, projected.y, 2 * projected.scale, 0, Math.PI * 2);
ctx.closePath();
const gradient = ctx.createRadialGradient(projected.x, projected.y, 0, projected.x, projected.y, 2 * projected.scale);
gradient.addColorStop(0, “rgba(255,155,255,0.5)”);
gradient.addColorStop(0.5, “rgba(55,255,25,0.8)”);
gradient.addColorStop(1, “rgba(55,25,255,0.2)”);
ctx.fillStyle = gradient;
ctx.fill();
}
}

// Drawing clicked points in green
ctx.fillStyle = “rgba(255,200,50,0.5)”;
for (const clickedPoint of clickedPoints) {
const rotated = rotate(clickedPoint, angleX, angleY);
const projected = project(rotated, canvas.width, canvas.height);

ctx.beginPath();
if (projected.scale > 0) {
ctx.arc(projected.x, projected.y, 4 * projected.scale, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
}
}

for (const line of lines) {
drawLine(line);
}

if (activeLine !== null) {
drawLine(activeLine);
}

angleX += rotationSpeed;
angleY += 0;

requestAnimationFrame(draw);
}


draw();
</script>
</body>
</html>