我刚刚开始编程,这是我的第二个项目——它是一个绘画应用程序。我在 YouTube 上看到了这个项目,并以自己的方式克隆了它。然而,当我遇到问题时,我会参考视频,就像初学者应该做的那样。但该视频并没有涵盖我想到的许多功能,比如我如何在画布内移动物体并在单击按钮后更改其大小。 这是我的代码
const canvas = document.querySelector(".canvas");
const ctx = canvas.getContext("2d");
const tools = document.querySelectorAll(".tool");
const fullColor = document.querySelector("#fill-color");
const brushSize = document.querySelector("#size-of-brush");
const colorBtns = document.querySelectorAll(".color .option");
const colorPicker = document.querySelector("#color-picker");
const clearCanvas = document.querySelector(".clear-canvas");
const saveCanvas = document.querySelector(".save-img");
// global variable
let method = "brush";
let draw = false;
let pervCorX;
let pervCorY;
let brushWidth = 5;
let oneDraw;
let color = "rgb(0, 0, 0)";
//canvas width and height
window.addEventListener("load", () => {
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
});
// confirm mouse down and change the color and size of brush and ships
const mousedown = (event) => {
draw = true;
ctx.strokeStyle = color;
ctx.fillStyle = color;
pervCorX = event.offsetX;
pervCorY = event.offsetY;
ctx.beginPath();
ctx.lineWidth = brushWidth;
oneDraw = ctx.getImageData(0, 0, canvas.width, canvas.height);
};
// witch shape and width is clicked
tools.forEach((toolsBtn) => {
toolsBtn.addEventListener("click", () => {
document.querySelector(".active").classList.remove("active");
toolsBtn.classList.add("active");
method = toolsBtn.id;
// console.log(method);
});
});
// confirmation of stooping drawing
const mouseup = () => {
draw = false;
};
// drawing rectangle circle triangle
const rectangle = (event) => {
const x = event.offsetX;
const y = event.offsetY;
const width = pervCorX - event.offsetX;
const height = pervCorY - event.offsetY;
if (fullColor.checked) return ctx.fillRect(x, y, width, height);
ctx.strokeRect(x, y, width, height);
};
const circle = (event) => {
ctx.beginPath();
console.log("hihi");
const width = pervCorX - event.offsetX;
const height = pervCorY - event.offsetY;
let radius = Math.sqrt(width ** 2 + height ** 2);
ctx.arc(pervCorX, pervCorY, radius, 0, 2 * Math.PI);
if (fullColor.checked) return ctx.fill();
ctx.stroke();
};
const triangle = (event) => {
ctx.beginPath();
ctx.moveTo(pervCorX, pervCorY);
ctx.lineTo(event.offsetX, event.offsetY);
ctx.lineTo(pervCorX * 2 - event.offsetX, event.offsetY);
ctx.closePath();
fullColor.checked ? ctx.fill() : ctx.stroke();
};
//checking what ship to draw
const startDrawing = (event) => {
if (!draw) return;
ctx.putImageData(oneDraw, 0, 0);
if (method == "brush" || method == "eraser") {
ctx.strokeStyle = method == "eraser" ? "#fff" : color;
ctx.lineTo(event.offsetX, event.offsetY);
ctx.stroke();
} else if (method == "rectangle") {
rectangle(event);
} else if (method == "circle") {
circle(event);
} else if (method == "triangle") {
triangle(event);
}
};
colorBtns.forEach((btn) => {
console.log(btn);
btn.addEventListener("click", () => {
document.querySelector(".selected").classList.remove("selected");
btn.classList.add("selected");
color = window.getComputedStyle(btn).backgroundColor;
});
});
//changing color of ships and brush
colorPicker.addEventListener("change", () => {
colorPicker.parentElement.style.background = colorPicker.value;
colorPicker.parentElement.click();
});
// checking if mouse down in canvas and give brush size
brushSize.addEventListener("change", () => (brushWidth = brushSize.value));
canvas.addEventListener("mousemove", startDrawing);
canvas.addEventListener("mousedown", mousedown);
canvas.addEventListener("mouseup", mouseup);
//save and clear canvas
clearCanvas.addEventListener("click", () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
});
saveCanvas.addEventListener("click", () => {
const a = document.createElement("a");
a.href = canvas.toDataURL("image/png");
a.download = "canvas_image.png";
a.click();
});
就像我如何在画布内移动物体并在单击按钮后更改其大小
但是,我假设您正在谈论类似于Figma/Adobe XD/等的功能,您可以在其中绘制一堆形状,然后可以使用鼠标/键盘来移动它们。
对于此类应用程序,您可以使用
Model View Controller (MVC)
架构。
随着时间的推移,随着您不断添加更多功能,您的代码设计将变得更加复杂。这就是面向对象编程的用武之地。您可以通过在 Github 上查看开源软件的代码来探索开源软件的设计方式。
这是您可以如何做的草稿。
// This is the model. It stores an array of objects.
// Each object contains information for rendering it.
// Notice how each type has different types of data.
const objectList = [
{ id: 0, type: 'rect', data: { x: 10, y: 5, w: 2, h: 4 } },
{ id: 1, type: 'circle', data: { x: 10, y: 5, r: 3.5 } },
{ id: 2, type: 'line', data: { x0: 10, y0: 5, x1: 2, y1: 4 } },
];
// This is the view. It basically renders everything in the objectList
const renderObjects = () => {
objectList.forEach(obj => {
if (obj.type === 'rect') {
// code to draw rectangle
}
if (obj.type === 'circle') {
// code to draw rectangle
}
if (obj.type === 'line') {
// code to draw rectangle
}
})
}
// Controllers
// These will be methods to modify items in objectList based on event handlers, etc.
const buttonEventHandler1 = (params) => {
// ... update some item from objectList based on params.
// redraw everything. Important for UI to update
renderObjects();
}
const buttonEventHandler2 = (params) => {
// ... update some item from objectList based on params.
// redraw everything. Important for UI to update
renderObjects();
}
您甚至可以更进一步,将
JSON.stringify(objectList)
写入文件,然后读取文件以填充 objectList
的初始值,就像绘画应用程序一样。