Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS3 border radius to HTML5 Canvas

I trying to reproduce the CSS3 border radius in canvas.

It's easy to draw a rounded rectangle but in CSS, the value of each border can be high.

For example :
HTML

<div class="normal_radius"></div>
<div class="high_radius"></div>
<div class="high2_radius"></div>

CSS

div { height:50px;width:50px;position:absolute;top:10px; }
.normal_radius {
    border: 1px solid black;
    border-radius: 5px 5px 10px 15px;
    left: 10px;
}
.high_radius {
    border: 1px solid red;
    border-radius: 5000px 500px 100px 150px;
    left: 80px;
}
.high2_radius {
    border: 1px solid blue;
    border-radius: 2500px 250px 50px 75px;
    left: 160px;
}

Here a jsfiddle

The black, normal border radius value, i can reproduce that. The red, high value for border radius, i don't know how reproduce that. And the blue, high value divided by 2, same result of red.

My question is simple, how to reproduce the red and the blue in canvas?

Best regards.

like image 484
kran Avatar asked Nov 20 '12 21:11

kran


2 Answers

The function below is pretty close. Although if you use values greater than the width and height you're going to have issues.

Live Demo

function canvasRadius(x, y, w, h, tl, tr, br, bl){
  var r = x + w,
      b = y + h;

  ctx.beginPath();
  ctx.moveTo(x+tl, y);
  ctx.lineTo(r-(tr), y);
  ctx.quadraticCurveTo(r, y, r, y+tr);
  ctx.lineTo(r, b-br);
  ctx.quadraticCurveTo(r, b, r-br, b);
  ctx.lineTo(x+bl, b);
  ctx.quadraticCurveTo(x, b, x, b-bl);
  ctx.lineTo(x, y+tl);
  ctx.quadraticCurveTo(x, y, x+tl, y);
  ctx.stroke();

}

canvasRadius(10,10,50,50,5,5,10,15);
ctx.strokeStyle = "red";
canvasRadius(80,10,50,50,47,3,0,0);
ctx.strokeStyle = "blue";
canvasRadius(160,10,50,50,47,3,0,0);
like image 95
Loktar Avatar answered Sep 19 '22 13:09

Loktar


here the solution :

CanvasRenderingContext2D.prototype.roundRect=function(x,y,width,height,tl,tr,br,bl) {
  var x1,x2,x3,x4,y1,y2,y3,y4,radii,ratio=0,CURVE2KAPPA=0.5522847498307934;
  ratio=Math.min(Math.min(width/(tl+tr),width/(br+bl)),Math.min(height/(tl+bl),height/(tr+br)));
  if ((ratio>0)&&(ratio<1)) {
    tl*=ratio;
    tr*=ratio;
    bl*=ratio;
    br*=ratio;
  }
  xw=x+width;
  yh=y+height;
  x1=x+tl;
  x2=xw-tr;
  x3=xw-br;
  x4=x+bl;
  y1=y+tr;
  y2=yh-br;
  y3=yh-bl;
  y4=y+tl;
  this.beginPath();
  this.moveTo(x1,y);
  this.lineTo(x2,y);
  radii=CURVE2KAPPA*tr;
  this.bezierCurveTo(x2+radii,y,xw,y1-radii,xw,y1);
  this.lineTo(xw,y2);
  radii=CURVE2KAPPA*br;
  this.bezierCurveTo(xw,y2+radii,x3+radii,yh,x3,yh);
  this.lineTo(x4,yh);
  radii=CURVE2KAPPA*bl;
  this.bezierCurveTo(x4-radii,yh,x,y3+radii,x,y3);
  this.lineTo(x,y4);
  radii=CURVE2KAPPA*tl;
  this.bezierCurveTo(x,y4-radii,x1-radii,y,x1,y);
  this.stroke();
}

ctx.roundRect(0,0,50,50,5,5,10,15);
ctx.strokeStyle="red";
ctx.roundRect(0,0,50,50,5000,500,100,150);
ctx.strokeStyle="blue";
ctx.roundRect(0,0,50,50,2500,250,50,75);

Live demo

Have fun.

like image 32
kran Avatar answered Sep 18 '22 13:09

kran