给Javascript制作的对象一个半径

时间:2017-03-15 07:58:53

标签: javascript html5-canvas

我想拥有它,以便当我创建一个"组件"我可以设置它的半径使其弯曲。下面是我的组件创建代码:

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);
  }
}

你可以看到它指定了宽度高度,颜色和x和y位置,但是我找不到给它一个半径的方法。我的代码的另一端使用了这个组件函数:

PaintBrush = new component(30, 30, "Blue", 30, 320);

帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

使用圆弧可以绘制一个带圆角的矩形:

arc采用参数:

arc(x, y, radius, startAngle, endAngle [,ccw]); // we won't need counter-clockwise

例如:

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

这只是使用半径和起点和终点角在每个角上绘制四个弧。由于我们使用单个路径,因此在每个弧之间绘制从前一个弧的末尾到新弧的开头的线 - 这就是顺序重要的原因。

只需fill()即可关闭路径并填充形状。如果您想要stroke(),请记住先使用closePath()。如果您稍后通过其他对象添加了路径,请记住在添加之前使用beginPath()

线设置半径也会将其限制为可能的最小尺寸:

this.radius = Math.min(radius, Math.min(width, height)/2);

首先使用高度和宽度的最小值除以2。然后是半径的最小值和这个结果。这确保半径不能大于最短边的一半,这将是“不可能的”。

关于下面setTransform()用法的说明 - 如果您没有累积转换,这应该可以正常工作。如果您这样做并且无法轻松更改,请将setTransform()替换为ctx.translate(this.x, this.y),然后通过调用ctx.translate(-this.x, -this.y);完成反转。如果它们以某种方式被转换(旋转,缩放等),我建议使用setTransforms悬停所有对象。

演示

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>