Elisabeth
Elisabeth

Reputation: 21226

Draw a rectangle with fill color and individual borders

How can I draw a canvas rectangle with fill color AND 4 different border colors on each side?

Upvotes: 0

Views: 4794

Answers (2)

markE
markE

Reputation: 105035

You can add a new method to canvas.context that draws your multi-colored rectangle.

enter image description here

You define a new method on the canvas.context through its prototype:

CanvasRenderingContext2D.prototype.myNewMethod = function(){ ... };

Inside the new method, you can use any context drawing commands to draw your desired shape.

Note that inside myNewMethod, “this” refers to the canvas.context, so you draw like this:

this.lineTo(x,y)    // not context.lineTo

Your fancy rectangle is a fairly straightforward drawing, except for mitered side strokes.

Each side stroke is drawn as a filled trapezoid:

function trapezoid(context,color,x1,y1,x2,y2,x3,y3,x4,y4){
    context.beginPath();
    context.moveTo(x1,y1);
    context.lineTo(x2,y2);
    context.lineTo(x3,y3);
    context.lineTo(x4,y4);
    context.closePath();
    context.fillStyle=color;
    context.fill();
}

Your fancy new rectangle method (rainbowRect) is called just like context.fillRect.

context.rainbowRect(100,50,100,50,"gold","red","blue","green","purple");

Here is a complete example:

$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");


    // Add a rainbowRect function to the context prototype
    // This method is used alone like context.fillRect
    // This method is not used within a context.beginPath
    // NOTE: this addition must always be run before it is used in code
    CanvasRenderingContext2D.prototype.rainbowRect = function (x,y,w,h,fillColor,tColor,rColor,bColor,lColor){

        // use existing fillStyle if fillStyle is not supplied
        fillColor=fillColor||this.fillStyle;

        // use existing strokeStyle if any strokeStyle is not supplied
        var ss=this.strokeStyle;
        tColor=tColor||ss;
        rColor=rColor||ss;
        bColor=bColor||ss;
        lColor=lColor||ss;


        // context will be modified, so save it
        this.save();

        // miter the lines
        this.lineJoin="miter";

        // helper function: draws one side's trapezoidal "stroke"
        function trapezoid(context,color,x1,y1,x2,y2,x3,y3,x4,y4){
            context.beginPath();
            context.moveTo(x1,y1);
            context.lineTo(x2,y2);
            context.lineTo(x3,y3);
            context.lineTo(x4,y4);
            context.closePath();
            context.fillStyle=color;
            context.fill();
        }

        // context lines are always drawn half-in/half-out
        // so context.lineWidth/2 is used a lot
        var lw=this.lineWidth/2;

        // shortcut vars for boundaries
        var L=x-lw;
        var R=x+lw;
        var T=y-lw;
        var B=y+lw;

        // top
        trapezoid(this,tColor,  L,T,  R+w,T,  L+w,B,  R,B );

        // right
        trapezoid(this,rColor,  R+w,T,  R+w,B+h,  L+w,T+h,  L+w,B );

        // bottom
        trapezoid(this,bColor,  R+w,B+h,  L,B+h,  R,T+h,  L+w,T+h );

        // left
        trapezoid(this,lColor,  L,B+h,  L,T,  R,B,  R,T+h );

        // fill
        this.fillStyle=fillColor;
        this.fillRect(x,y,w,h);

        // be kind -- always rewind (old vhs reference!)
        this.restore();
        // don't let this path leak
        this.beginPath();
        // chain
        return(this);
    };


    // testing
    ctx.lineWidth=20;
    ctx.rainbowRect(100,50,100,50,"gold","red","blue","green","purple");



}); // end $(function(){});
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas" width=300 height=150></canvas>

Upvotes: 3

Rowman Pirce
Rowman Pirce

Reputation: 423

Unfortunately, you can't draw borders of a rectangle just like you do with css. You can use stroke() method, but it draws "borders" just with one color for every side. So, I guess, you can draw borders manually by drawing lines near a rectangle.

Upvotes: 0

Related Questions