在html5画布中创建形状时创建了太多对象



我正在用html5画布和JavaScript创建一个简单的绘画应用程序,它可以创建可变大小的三角形。我刚刚想好了如何做到这一点,现在正试图拖动和移动已经创建的三角形。为此,我使用了一个";三角形";数组来存储所有三角形对象。

当我试图将一个三角形中的一个对象推入数组时,会创建太多对象。我该如何解决这个问题?我只想要每个三角形一个物体。

我的代码:

HTML:

<body>
<h1>Simple Paint App</h1>
<div id="canvs">
<canvas id="paint-canvas" width="800" height="400"></canvas>
<button id="buttn" >Clear/Reset</button>
</div>

<noscript>This site requires JavaScript to be activated.</noscript>
</body>

JavaScript:

let canvas = document.querySelector("#paint-canvas");
let context = canvas.getContext("2d");
let triangles = []
let offsetX = canvas.getBoundingClientRect().left;
let offsetY = canvas.getBoundingClientRect().top;
let startX, startY;
let dragOk = false;
let imageData;
function getCoordinates(e){
const X = parseInt(e.clientX - offsetX);
const Y = parseInt(e.clientY - offsetY);

return {x: X, y: Y};
}
function getRandomColor(){
const colors = 
["#DFFF00", "#FFBF00", "#FF7F50", "#DE3163", "#9FE2BF", "#40E0D0", "#6495ED", "#CCCCFF"];
return colors[Math.floor(Math.random() * colors.length)];
}
canvas.onmousedown = mouseDown;
canvas.onmouseup = mouseUp;
canvas.onmousemove = mouseMove;
document.querySelector("#buttn").addEventListener("click", () => resetCanvas());

function mouseDown(e){
dragOk = true;
const start = getCoordinates(e);
startX = start.x;
startY = start.y;
storeImageData();
}
function mouseUp(e){
dragOk = false;
restoreImageData();
let position = getCoordinates(e);
drawTriangle(position);
console.log(triangles);
}
function mouseMove(e){
if (!dragOk) {
return;
}
let position;
restoreImageData()
position = getCoordinates(e);
drawTriangle(position);
}
function storeImageData() {
imageData = context.getImageData(0, 0, canvas.width, canvas.height);
}
function restoreImageData() {
context.putImageData(imageData, 0, 0);
}
function drawTriangle(position) {
let tri = { x:startX, y:startY, points: [{x:0,y:0},{x:0,y:0},{x:0,y:0}], outline: "#000000", fill:"#000000", dragOk: false };
const radius = Math.sqrt(Math.pow((startX - position.x), 2) + Math.pow((startY - position.y), 2));
let i = 0;
let angle = 100;
// 3 because triangle has 3 sides
for (i = 0; i < 3; i++) {
tri.points[i].x = startX + radius * Math.cos(angle);
tri.points[i].y = startY - radius * Math.sin(angle);        
angle += (2 * Math.PI) / 3;
}
context.beginPath();
context.moveTo(tri.points[0].x, tri.points[0].y);
for (i = 1; i < 3; i++) {
context.lineTo(tri.points[i].x, tri.points[i].y);
}
context.closePath();
// the outline
context.lineWidth = 5;
tri.outline = "#000000"
context.strokeStyle = tri.outline;
context.stroke();
// the fill color
tri.fill = getRandomColor();
context.fillStyle = tri.fill;
context.fill();
triangles.push(tri)
}
function resetCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}

编辑:我正在drawTriangle函数中推动新创建的三角形。JSFiddle:代码

问题是您的drawTriangle函数被链接到onMouseMove事件。当然,这个事件是调整三角形大小所必需的,但您不应该使用它来填充三角形数组中的对象,因为这意味着只要鼠标在移动,您就可以创建被推入数组的新对象。

最好这样做:

  • 创建全局变量tempTriangle
  • 在drawTriangle函数中,将tri分配给tempTriangle
  • 如果释放鼠标按钮,则将tempTriangle推入triangles阵列

下面是一个基于您的代码的示例:

let canvas = document.querySelector("#paint-canvas");
let context = canvas.getContext("2d");
let triangles = []
let offsetX = canvas.getBoundingClientRect().left;
let offsetY = canvas.getBoundingClientRect().top;
let startX, startY;
let dragOk = false;
let imageData;
let tempTriangle;
function getCoordinates(e) {
const X = parseInt(e.clientX - offsetX);
const Y = parseInt(e.clientY - offsetY);
return {
x: X,
y: Y
};
}
function getRandomColor() {
const colors = ["#DFFF00", "#FFBF00", "#FF7F50", "#DE3163", "#9FE2BF", "#40E0D0", "#6495ED", "#CCCCFF"];
return colors[Math.floor(Math.random() * colors.length)];
}
canvas.onmousedown = mouseDown;
canvas.onmouseup = mouseUp;
canvas.onmousemove = mouseMove;

function mouseDown(e) {
dragOk = true;
const start = getCoordinates(e);
startX = start.x;
startY = start.y;
storeImageData();
}
function mouseUp(e) {
dragOk = false;
restoreImageData();
let position = getCoordinates(e);
drawTriangle(position);
triangles.push(tempTriangle)
console.log(triangles, triangles.length);
}
function mouseMove(e) {
if (!dragOk) {
return;
}
let position;
restoreImageData()
position = getCoordinates(e);
drawTriangle(position);
}
function storeImageData() {
imageData = context.getImageData(0, 0, canvas.width, canvas.height);
}
function restoreImageData() {
context.putImageData(imageData, 0, 0);
}
function drawTriangle(position) {
let tri = {
x: startX,
y: startY,
points: [{
x: 0,
y: 0
}, {
x: 0,
y: 0
}, {
x: 0,
y: 0
}],
outline: "#000000",
fill: "#000000",
dragOk: false
};
const radius = Math.sqrt(Math.pow((startX - position.x), 2) + Math.pow((startY - position.y), 2));
let i = 0;
let angle = 100;
// 3 because triangle has 3 sides
for (i = 0; i < 3; i++) {
tri.points[i].x = startX + radius * Math.cos(angle);
tri.points[i].y = startY - radius * Math.sin(angle);
angle += (2 * Math.PI) / 3;
}
context.beginPath();
context.moveTo(tri.points[0].x, tri.points[0].y);
for (i = 1; i < 3; i++) {
context.lineTo(tri.points[i].x, tri.points[i].y);
}
context.closePath();
// the outline
context.lineWidth = 5;
tri.outline = "#000000"
context.strokeStyle = tri.outline;
context.stroke();
// the fill color
tri.fill = getRandomColor();
context.fillStyle = tri.fill;
context.fill();
tempTriangle = tri;
}
function resetCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
h1 {
display: flex;
justify-content: center;
font-family: 'Roboto', sans-serif;
}
#paint-canvas {
border: 1vh solid black;
}
#canvs {
display: flex;
flex-flow: column;
align-items: center;
}
#buttn {
margin: 5vh 0 0 0;
}
<div id="canvs">
<canvas id="paint-canvas" width="800" height="400"></canvas>
<button id="buttn" onclick="resetCanvas()">Clear/Reset</button>
</div>

最新更新