Drawing a rectangle with rounded corners can be done using arcs instead:
The arc takes the arguments:
arc(x, y, radius, startAngle, endAngle [,ccw]); // we won't need counter-clockwise
For example:
var pi2 = Math.PI * 2; // 360 deg.
var r = this.radius, w = this.width, h = this.height;
// ...
// draw rounded rectangle
ctx.beginPath();
ctx.arc(r, r, r, pi2*0.5, pi2*0.75); // top-left
ctx.arc(r+w-r*2, r, r, pi2*0.75, pi2); // top-right
ctx.arc(r+w-r*2, r+h-r*2, r, 0, pi2*0.25); // bottom-right
ctx.arc(r, r+h-r*2, r, pi2*0.25, pi2*0.5); // bottom-left
This simply draws four arc in each corner using radius and start and end angle. Since we use a single path lines will be drawn between each arc from the end of the previous arc to the beginning of the new one - which is why the order matters.
Simply fill()
to close the path and fill the shape. If you want to stroke()
it as well remember to use closePath()
first. If you have paths added later via other objects etc., also remember to use beginPath()
before you add them.
The line setting radius will also clamp it to the minimum size possible:
this.radius = Math.min(radius, Math.min(width, height)/2);
First the minimum of height and width is used divided on two. Then the minimum of radius and this result. This makes sure the radius can't be larger then half of the shortest side which would be "impossible".
A note on the setTransform()
usage below - if you don't have accumulated transforms this should work fine. If you do and can't easily change it replace the setTransform()
s with ctx.translate(this.x, this.y)
and after finished reverse it by calling ctx.translate(-this.x, -this.y);
. I would recommend using setTransforms for all your objects hover if they are transformed (rotated, scaled etc.) somehow.
Demo
var GameArena = {context: c.getContext("2d")}; // dummy
var PaintBrush = new component(200, 100, "#37f", 10, 10, 16);
PaintBrush.update();
function component(width, height, color, x, y, radius) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.radius = Math.min(radius, Math.min(width, height)/2); // clamp radius
this.color = color;
this.update = function() {
var pi2 = Math.PI * 2; // 360 deg.
var r = this.radius, w = this.width, h = this.height;
ctx = GameArena.context;
ctx.fillStyle = this.color;
ctx.setTransform(1,0,0,1,this.x, this.y); // transform (absolute here)
// draw rounded rectangle
ctx.beginPath();
ctx.arc(r , r , r, pi2*0.5 , pi2*0.75); // top-left
ctx.arc(w-r, r , r, pi2*0.75, pi2); // top-right
ctx.arc(w-r, h-r, r, 0 , pi2*0.25); // bottom-right
ctx.arc(r , h-r, r, pi2*0.25, pi2*0.5); // bottom-left
ctx.fill();
ctx.setTransform(1,0,0,1,0,0); // reset transform
}
}
<canvas id=c></canvas>