I want to have it so that when i create a "component" i can set its radius to make it curved. Below is my code for component create:
function component(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.color = color;
this.update = function() {
ctx = GameArena.context;
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
as you can see it specifies the width height, color and x and y positions but i can't find a way to give it a radius. The other end of my code that uses this component function is here:
PaintBrush = new component(30, 30, "Blue", 30, 320);
Help would be appreciated!
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>