Reputation: 21226
How can I draw a canvas rectangle with fill color AND 4 different border colors on each side?
Upvotes: 0
Views: 4794
Reputation: 105035
You can add a new method to canvas.context that draws your multi-colored rectangle.
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
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