I outlined the corners of a rectangle:
class DrawingTool
{
constructor(drawArea)
{
this.drawArea = drawArea;
this.canvasContext = drawArea.getContext('2d');
this.shapes = [];
drawArea.addEventListener('click', this.handleMouseClick.bind(this), false);
}
draw()
{
this.canvasContext.clearRect(0, 0, 700, 700);
this.shapes.forEach((shape) => shape.draw());
}
drawRectangle(x, y, width, height)
{
this.shapes.push(new RectangleShape(this.canvasContext, x, y, width, height));
}
handleMouseClick(event)
{
var xCoord = event.pageX - this.drawArea.offsetLeft + this.drawArea.clientLeft;
var yCoord = event.pageY - this.drawArea.offsetTop + this.drawArea.clientTop;
this.shapes.forEach((shape) =>
{
if (yCoord > shape.y && yCoord < shape.y + shape.height && xCoord > shape.x && xCoord < shape.x + shape.width)
{
shape.selected = !shape.selected;
}
});
this.draw();
}
}
class RectangleShape
{
constructor(context, x, y, width, height)
{
this.context = context;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.cornerSize = 10;
this.selected = false;
}
draw()
{
this.context.beginPath();
this.context.rect(this.x, this.y, this.width, this.height);
this.context.closePath();
this.context.stroke();
if(!this.selected)
return;
this.context.beginPath();
this.context.fillStyle = "#FFFFFF";
this.context.strokeStyle = "#000000";
// Corner rectangles
this.context.rect(
this.x - this.cornerSize / 2,
this.y - this.cornerSize / 2,
this.cornerSize,
this.cornerSize
);
this.context.rect(
this.x + this.width - this.cornerSize / 2,
this.y - this.cornerSize / 2,
this.cornerSize,
this.cornerSize
);
this.context.rect(
this.x + this.width - this.cornerSize / 2,
this.y + this.height - this.cornerSize / 2,
this.cornerSize,
this.cornerSize
);
this.context.rect(
this.x - this.cornerSize / 2,
this.y + this.height - this.cornerSize / 2,
this.cornerSize,
this.cornerSize
);
this.context.closePath();
this.context.fill();
this.context.stroke();
}
}
var drawArea = document.getElementById('draw_area');
let drawingTool = new DrawingTool(drawArea);
drawingTool.drawRectangle(50, 50, 100, 100);
drawingTool.drawRectangle(200, 50, 100, 100);
drawingTool.draw();
#draw_area{
background-color: lightgrey;
}
<div>
<canvas id="draw_area" height="700", width="700"> </canvas>
</div>
Examining the drawRectangle function:
function drawRectangle(x, y, width, height){
const cornerSize = 10;
var object = drawArea.getContext('2d');
object.beginPath();
object.rect(x, y, width, height);
object.closePath();
object.stroke();
object.beginPath();
object.fillStyle = "#FFFFFF";
object.strokeStyle = "#000000";
// Corner rectangles
object.rect(
x - cornerSize / 2,
y - cornerSize / 2,
cornerSize,
cornerSize
);
object.rect(
x + width - cornerSize / 2,
y - cornerSize / 2,
cornerSize,
cornerSize
);
object.rect(
x + width - cornerSize / 2,
y + height - cornerSize / 2,
cornerSize,
cornerSize
);
object.rect(
x - cornerSize / 2,
y + height - cornerSize / 2,
cornerSize,
cornerSize
);
object.closePath();
object.fill();
object.stroke();
};
These lines are initially for outlining the main rectangle:
object.beginPath();
object.rect(x, y, width, height);
object.closePath();
object.stroke();
Calling closePath here is crucial so that the canvas distinguishes the main rectangle from the corner rectangles.
Subsequently, calculations are made to accurately position and draw the corner rectangles:
// top-left corner
object.rect(
x - cornerSize / 2,
y - cornerSize / 2,
cornerSize,
cornerSize
);
The use of closePath
and fill
at the end ensures adherence to coloring guidelines mentioned previously:
object.fillStyle = "#FFFFFF";
object.strokeStyle = "#000000";
Note that manual handling is required when using pure canvas without frameworks like Fabric.js; even with libraries, manual calculation of small rectangle positions per shape may still be necessary.