Thursday, July 29, 2010

Canvas Rounded Corner Rectangles

I've recently started using the canvas tag and  needed to draw rounded corner rectangles. I did find a good post explaing how to do it but I didn't find a nice method so I decided to create one.  I took Futomi Hatano's code  and abstracted it into a method.

 * Draws a rounded rectangle using the current state of the canvas. 
 * If you omit the last three params, it will draw a rectangle 
 * outline with a 5 pixel border radius 
 * @param {CanvasRenderingContext2D} ctx
 * @param {Number} x The top left x coordinate
 * @param {Number} y The top left y coordinate 
 * @param {Number} width The width of the rectangle 
 * @param {Number} height The height of the rectangle
 * @param {Number} radius The corner radius. Defaults to 5;
 * @param {Boolean} fill Whether to fill the rectangle. Defaults to false.
 * @param {Boolean} stroke Whether to stroke the rectangle. Defaults to true.
function roundRect(ctx, x, y, width, height, radius, fill, stroke) {
  if (typeof stroke == "undefined" ) {
    stroke = true;
  if (typeof radius === "undefined") {
    radius = 5;
  ctx.moveTo(x + radius, y);
  ctx.lineTo(x + width - radius, y);
  ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
  ctx.lineTo(x + width, y + height - radius);
  ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
  ctx.lineTo(x + radius, y + height);
  ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
  ctx.lineTo(x, y + radius);
  ctx.quadraticCurveTo(x, y, x + radius, y);
  if (stroke) {
  if (fill) {

And it can be used like the following:

// My html contains a canvas with id "rounded-rect" 500X350
var ctx = document.getElementById("rounded-rect").getContext("2d");
// Draw using default border radius, 
// stroke it but no fill (function's default values)
roundRect(ctx, 5, 5, 50, 50);
// To change the color on the rectangle, just manipulate the context
ctx.strokeStyle = "rgb(255, 0, 0)";
ctx.fillStyle = "rgba(255, 255, 0, .5)";
roundRect(ctx, 100, 5, 100, 100, 20, true);
// Manipulate it again
ctx.strokeStyle = "#2d6";
ctx.fillStyle = "#abc";
roundRect(ctx, 100, 200, 200, 100, 50, true);

Which will produce the following output:

For Firefox and Chrome (and maybe other browsers), you can do the following for syntactic sugar

CanvasRenderingContext2D.prototype.roundRect = 

function(x, y, width, height, radius, fill, stroke) {
  if (typeof stroke == "undefined" ) {
    stroke = true;
  if (typeof radius === "undefined") {
    radius = 5;
  this.moveTo(x + radius, y);
  this.lineTo(x + width - radius, y);
  this.quadraticCurveTo(x + width, y, x + width, y + radius);
  this.lineTo(x + width, y + height - radius);
  this.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
  this.lineTo(x + radius, y + height);
  this.quadraticCurveTo(x, y + height, x, y + height - radius);
  this.lineTo(x, y + radius);
  this.quadraticCurveTo(x, y, x + radius, y);
  if (stroke) {
  if (fill) {

// Now you can just call
var ctx = document.getElementById("rounded-rect").getContext("2d");
ctx.roundRect(5, 5, 50, 50);

Here's a JsFiddle that you can edit freely


  1. Yay Juan! Good job! Gotta say, big bro, I don't understand a thing, but I came to show my love. Hahaha!
    Kiss kiss from your sis,

    1. Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog. Really very informative post you shared here. Kindly keep blogging. If anyone wants to become a Front end developer learn from Javascript Training in Chennai . or Javascript Training in Chennai. Nowadays JavaScript has tons of job opportunities on various vertical industry. ES6 Training in Chennai

  2. Hi,

    nice Idea, but isnt it possible to inherit your own Context class from canvas Context? So that you dont need to pass the context? Would be more elegant or?
    BTW. can i use the code for an Palm Web OS project i am working on?

  3. @Matthias: Please do use it for anything you'd like. I don't think there's a way to inherit or augment the CanvasContext object returned by getContext() that works across browsers. Let me know if you know how to do it. I modified the post to show you how to do what you want in Firefox. By the way, thanks for the first comment on my blog that is not from a relative :)

    I knew I should have added a disclaimer. This is not the code I actually use in production. This is just the simplest way to do it so that others can benefit.

  4. There's a bug on line 15 of the first listing:

    stroke = stroke === undefined ? true : false;

    should be

    stroke = stroke === (undefined || true) ? true : false

  5. Thanks Brian. Fixed it with a clearer syntax.

  6. Thanks! I've used your routine on my page: I changed a couple of things, I added at the beginning and ctx.restore() at the end, and switched the order of the stroke and fill at the end, since if you did both, the fill messed up the stroke a bit. In a comment in the routine, I give you credit, and have a link back to this blog.

  7. Well the url for my page is different. It's:
    I also made it so you can have an additional boolean arguments for the top left, top right, bottom right and bottom left corners. For each of the arguments, if specified as true, that corner will be rectangular. If unspecified it works just like yours.

    I have:
    var tl=arguments[7];
    var tr=arguments[8];
    var br=arguments[9];
    var bl=arguments[10];
    and then for each corner a section like:


    That way, if you don't specify them the test as false and you get the original specification. As an example of how I used that, look at the colored header on the CoC widget. I wanted to draw it so that the corners would match the canvas, and now I can by adding the correct arguments.

  8. Hi Patrick, thanks for the link to to your usage, it's nice to see someone using it. I'll add your changes (support for multiple corner radii) to this post soon. Thanks for the link back. I should add a note explaining that all code I post here is free for the taking and any link backs are done out of generosity, they are not required.

    Nice job implementing dragging within the canvas tag. I've had to do it myself and it's a PITA.

  9. You must be talking about the sliders I made. I have some really cool buttons too. I made a generic handler for events so that javascript objects could register for events and provide a hit() routine. When an event comes in for the canvas, it looks through the queue for that event and calls the hit() routine for each thing passing the x,y in canvas coordinates for the event. If hit returns true, the callback for the object gets called with the event. I figured that way complex graphic shapes could all use this, and each would be the expert on whether the event hit them. Once the framework was set up adding sliders and buttons turned out to be really easy. If you haven't checked out my site in a while ( check it out, and look at the tutorials.

  10. good work !
    I made a live example using this code at

  11. Thanks for this...helped and works very well

  12. just for the js challenged folks (like myself) that might stumble on this - I struggled with the the contextual call version - your "syntactical sugar" version - not working for the longest time. Finally decided to move the function definition in the js file above the location in the file where I get the context object and magically it started working! Not sure if that is browser specific behavior but I was getting the same behavior on both chrome and safari on mac - btw that approach does work on safari (at least the version I have (5.1.2) )

  13. Great function. Can I use it in an open source data visualization library?

    1. Cool stuff, feel free to use it, attribution not required, but appreciated. Love the name of your lib

  14. Hi I am using this wpaint code in my application, but the save image options is not working after I merge the code in my application, can you please help me by giving the required changes for save image option to work. thanks in advance for your help :)

    1. Somu, I'm not sure why you think I can help with wPaint. You should ask at

  15. Inspiring writings and I greatly admired what you have to say , I hope you continue to provide new ideas for us all and greetings success always for you..Keep update more information..
    Website for school uk

  16. I have read such a mind-blowing blog after a long time. I really appreciate your article and you have described every thing in this blog with proper advice.Appreciated.

    Now website design buffalo ny service is available with complete professionalism in reasonable budget.


  17. Thanks, Learned a lot of new things from your post! Good creation and HATS OFF to the creativity of your mind.
    Very interesting and useful blog!
    javascript Training in Gurgaon

  18. Thanks for sharing this Informative content. Well explained.
    Javascript Training in Delhi

  19. Our Web Designing Course and other IT Training Programs give professionals the opportunity to attend our open- sourced academic courses on the go which

    ultimately helps them build the skills and knowledge they need to reach their professional goals.

    WordPress Training
    Web Designing Course in Delhi
    SEO Course
    Digital Marketing Training in Delhi
    SMO Training
    PPC Institute in Delhi
    Joomla Course in Delhi
    JQuery Institute in Delhi
    JavaScript Course

  20. Existing without the answers to the difficulties you’ve sorted out through this guide is a critical case, as well as the kind which could have badly affected my entire career if I had not discovered your website.
    nebosh course in chennai

  21. It is really a great work and the way in which you are sharing the knowledge is excellent. Thanks for your informative article
    offshore safety course in chennai

  22. This comment has been removed by the author.

  23. Really very happy to say,your post is very interesting to read.I never stop myself to say something about it.You’re doing a great job.Keep it up.php course in mumbai

  24. Great Article… I love to read your articles because your writing style is too good, its is very very helpful for all of us and I never get bored while reading your article because, they are becomes a more and more interesting from the starting lines until the end.

    Data Science course in rajaji nagar
    Data Science with Python course in chenni
    Data Science course in electronic city
    Data Science course in USA
    Data science course in pune | Data Science Training institute in Pune
    Data science course in bangalore

  25. Its a wonderful post and very helpful, thanks for all this information. You are including better information.
    Javascript Training in Delhi
    Javascript Course in Delhi
    Javascript Training institute in Delhi

  26. Its a wonderful post and very helpful, thanks for all this information. You are including better information regarding this topic in an effective way.Thank you so much.

    Java Online Training

    Java Training

    Java Interview Questions and Answers