Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
332 views
in Technique[技术] by (71.8m points)

html5 canvas - Give a Javascript made object a radius

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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...