我发现只有填充矩形,但没有圆角,我怎么能这样做?
我需要做同样的事情并创建一个方法来做到这一点.
// Now you can just call
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 = "#0f0";
ctx.fillStyle = "#ddd";
// Different radii for each corner, others default to 0
roundRect(ctx, 300, 5, 200, 100, {
tl: 50,
br: 25
}, true);
/**
* 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 = 5] The corner radius; It can also be an object
* to specify different radii for corners
* @param {Number} [radius.tl = 0] Top left
* @param {Number} [radius.tr = 0] Top right
* @param {Number} [radius.br = 0] Bottom right
* @param {Number} [radius.bl = 0] Bottom left
* @param {Boolean} [fill = false] Whether to fill the rectangle.
* @param {Boolean} [stroke = true] Whether to stroke the rectangle.
*/
function roundRect(ctx, x, y, width, height, radius, fill, stroke) {
if (typeof stroke === 'undefined') {
stroke = true;
}
if (typeof radius === 'undefined') {
radius = 5;
}
if (typeof radius === 'number') {
radius = {tl: radius, tr: radius, br: radius, bl: radius};
} else {
var defaultRadius = {tl: 0, tr: 0, br: 0, bl: 0};
for (var side in defaultRadius) {
radius[side] = radius[side] || defaultRadius[side];
}
}
ctx.beginPath();
ctx.moveTo(x + radius.tl, y);
ctx.lineTo(x + width - radius.tr, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius.tr);
ctx.lineTo(x + width, y + height - radius.br);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius.br, y + height);
ctx.lineTo(x + radius.bl, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius.bl);
ctx.lineTo(x, y + radius.tl);
ctx.quadraticCurveTo(x, y, x + radius.tl, y);
ctx.closePath();
if (fill) {
ctx.fill();
}
if (stroke) {
ctx.stroke();
}
}
我从@jhoff的解决方案开始,但重新编写它以使用宽度/高度参数,并使用arcTo
使它更简洁:
CanvasRenderingContext2D.prototype.roundRect = function (x, y, w, h, r) { if (w < 2 * r) r = w / 2; if (h < 2 * r) r = h / 2; this.beginPath(); this.moveTo(x+r, y); this.arcTo(x+w, y, x+w, y+h, r); this.arcTo(x+w, y+h, x, y+h, r); this.arcTo(x, y+h, x, y, r); this.arcTo(x, y, x+w, y, r); this.closePath(); return this; }
还返回上下文,以便您可以链接一点.例如:
ctx.roundRect(35, 10, 225, 110, 20).stroke(); //or .fill() for a filled rect
HTML5画布不提供绘制带圆角的矩形的方法.
使用lineTo()
和arc()
方法怎么样?
您也可以使用该quadraticCurveTo()
方法而不是arc()
方法.
Juan,我对你的方法做了一些改进,允许分别改变每个矩形角半径:
/** * 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 {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 {Object} radius All corner radii. Defaults to 0,0,0,0; * @param {Boolean} fill Whether to fill the rectangle. Defaults to false. * @param {Boolean} stroke Whether to stroke the rectangle. Defaults to true. */ CanvasRenderingContext2D.prototype.roundRect = function (x, y, width, height, radius, fill, stroke) { var cornerRadius = { upperLeft: 0, upperRight: 0, lowerLeft: 0, lowerRight: 0 }; if (typeof stroke == "undefined") { stroke = true; } if (typeof radius === "object") { for (var side in radius) { cornerRadius[side] = radius[side]; } } this.beginPath(); this.moveTo(x + cornerRadius.upperLeft, y); this.lineTo(x + width - cornerRadius.upperRight, y); this.quadraticCurveTo(x + width, y, x + width, y + cornerRadius.upperRight); this.lineTo(x + width, y + height - cornerRadius.lowerRight); this.quadraticCurveTo(x + width, y + height, x + width - cornerRadius.lowerRight, y + height); this.lineTo(x + cornerRadius.lowerLeft, y + height); this.quadraticCurveTo(x, y + height, x, y + height - cornerRadius.lowerLeft); this.lineTo(x, y + cornerRadius.upperLeft); this.quadraticCurveTo(x, y, x + cornerRadius.upperLeft, y); this.closePath(); if (stroke) { this.stroke(); } if (fill) { this.fill(); } }
像这样使用它:
var canvas = document.getElementById("canvas"); var c = canvas.getContext("2d"); c.fillStyle = "blue"; c.roundRect(50, 100, 50, 100, {upperLeft:10,upperRight:10}, true, true);
drawPolygon
下面的函数可用于绘制任何带圆角的多边形.
看到它在这里运行.
function drawPolygon(ctx, pts, radius) { if (radius > 0) { pts = getRoundedPoints(pts, radius); } var i, pt, len = pts.length; ctx.beginPath(); for (i = 0; i < len; i++) { pt = pts[i]; if (i == 0) { ctx.moveTo(pt[0], pt[1]); } else { ctx.lineTo(pt[0], pt[1]); } if (radius > 0) { ctx.quadraticCurveTo(pt[2], pt[3], pt[4], pt[5]); } } ctx.closePath(); } function getRoundedPoints(pts, radius) { var i1, i2, i3, p1, p2, p3, prevPt, nextPt, len = pts.length, res = new Array(len); for (i2 = 0; i2 < len; i2++) { i1 = i2-1; i3 = i2+1; if (i1 < 0) { i1 = len - 1; } if (i3 == len) { i3 = 0; } p1 = pts[i1]; p2 = pts[i2]; p3 = pts[i3]; prevPt = getRoundedPoint(p1[0], p1[1], p2[0], p2[1], radius, false); nextPt = getRoundedPoint(p2[0], p2[1], p3[0], p3[1], radius, true); res[i2] = [prevPt[0], prevPt[1], p2[0], p2[1], nextPt[0], nextPt[1]]; } return res; }; function getRoundedPoint(x1, y1, x2, y2, radius, first) { var total = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)), idx = first ? radius / total : (total - radius) / total; return [x1 + (idx * (x2 - x1)), y1 + (idx * (y2 - y1))]; };
该函数接收带有多边形点的数组,如下所示:
var canvas = document.getElementById("cv"); var ctx = canvas.getContext("2d"); ctx.strokeStyle = "#000000"; ctx.lineWidth = 5; drawPolygon(ctx, [[20, 20], [120, 20], [120, 120], [ 20, 120]], 10); ctx.stroke();
这是一个端口和此处发布的解决方案的更通用版本.
这是我写的一个...使用弧而不是二次曲线来更好地控制半径.此外,它留下了抚摸和填补你
/* Canvas 2d context - roundRect * * Accepts 5 parameters, the start_x and start_y points, the end_x and end_y points, and the radius of the corners * * No return value */ CanvasRenderingContext2D.prototype.roundRect = function(sx,sy,ex,ey,r) { var r2d = Math.PI/180; if( ( ex - sx ) - ( 2 * r ) < 0 ) { r = ( ( ex - sx ) / 2 ); } //ensure that the radius isn't too large for x if( ( ey - sy ) - ( 2 * r ) < 0 ) { r = ( ( ey - sy ) / 2 ); } //ensure that the radius isn't too large for y this.beginPath(); this.moveTo(sx+r,sy); this.lineTo(ex-r,sy); this.arc(ex-r,sy+r,r,r2d*270,r2d*360,false); this.lineTo(ex,ey-r); this.arc(ex-r,ey-r,r,r2d*0,r2d*90,false); this.lineTo(sx+r,ey); this.arc(sx+r,ey-r,r,r2d*90,r2d*180,false); this.lineTo(sx,sy+r); this.arc(sx+r,sy+r,r,r2d*180,r2d*270,false); this.closePath(); }
这是一个例子:
var _e = document.getElementById('#my_canvas'); var _cxt = _e.getContext("2d"); _cxt.roundRect(35,10,260,120,20); _cxt.strokeStyle = "#000"; _cxt.stroke();
var canvas = document.createElement("canvas"); document.body.appendChild(canvas); var ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.moveTo(100,100); ctx.arcTo(0,100,0,0,30); ctx.arcTo(0,0,100,0,30); ctx.arcTo(100,0,100,100,30); ctx.arcTo(100,100,0,100,30); ctx.fill();