我发现了这段代码,它生成了一个带圆角的矩形,但我希望能够根据需要增加矩形的大小(高度和宽度)。
var canvas = document.getElementById('newCanvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(20, 10);
ctx.lineTo(80, 10);
ctx.quadraticCurveTo(90, 10, 90, 20);
ctx.lineTo(90, 80);
ctx.quadraticCurveTo(90, 90, 80, 90);
ctx.lineTo(20, 90);
ctx.quadraticCurveTo(10, 90, 10, 80);
ctx.lineTo(10, 20);
ctx.quadraticCurveTo(10, 10, 20, 10);
ctx.stroke();
答案 0 :(得分:1)
我注意到你忘记关闭路径了。根据 ctx.lineJoin 设置,这可能会导致路径开始/结束处出现轻微的接缝或凹凸。
对 ctx.closePath 的调用用一行将结尾连接到开头
要使用的曲线类型的视觉设计规则。
贝塞尔曲线永远无法完全拟合圆。二次贝塞尔曲线非常不适合。如果您必须使用贝塞尔曲线,请使用三次贝塞尔曲线以获得更好的拟合。
使用三次贝塞尔曲线的最佳 approximation of a circle 是通过 c = 0.55191502449
作为半径的一部分插入控制点。这将导致 0.019608% 的最小可能径向误差
示例显示了三次(黑色)和二次(红色)曲线之间的区别。
const ctx = canvas.getContext('2d');
ctx.strokeStyle = 'red';
drawRoundedRectQuad(ctx, 10, 10, 180, 180, 70);
ctx.strokeStyle = 'black';
drawRoundedRect(ctx, 10, 10, 180, 180, 70);
function drawRoundedRect(ctx, x, y, w, h, r) {
const c = 0.55191502449;
const cP = r * (1 - c);
const right = x + w;
const bottom = y + h;
ctx.beginPath();
ctx.lineTo(right - r, y);
ctx.bezierCurveTo(right - cP, y, right, y + cP, right, y + r);
ctx.lineTo(right, bottom - r);
ctx.bezierCurveTo(right, bottom - cP, right - cP, bottom, right - r, bottom);
ctx.lineTo(x + r, bottom);
ctx.bezierCurveTo(x + cP, bottom, x, bottom - cP, x, bottom - r);
ctx.lineTo(x, y + r);
ctx.bezierCurveTo(x, y + cP , x + cP, y, x + r, y);
ctx.closePath();
ctx.stroke();
}
function drawRoundedRectQuad(ctx, x, y, w, h, r){
ctx.beginPath();
ctx.lineTo(x + w- r, y);
ctx.quadraticCurveTo(x + w, y, x + w, y + r);
ctx.lineTo(x + w, y + h- r);
ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
ctx.lineTo(x + r, y + h);
ctx.quadraticCurveTo(x, y + h, x, y + h- r);
ctx.lineTo(x, y + r);
ctx.quadraticCurveTo(x, y, x + r, y);
ctx.closePath();
ctx.stroke();
};
<canvas id="canvas" width ="200" height="200"></canvas>
border-radius
要获得真正的圆角矩形(圆形而不是近似曲线),请使用 ctx.arc 创建圆角。
roundedRect
扩展 2D API下面的代码通过将函数 strokeRoundedRect(x, y, w, [h, [r]])
、fillRoundedRect(x, y, w, [h, [r]])
和 roundedRect(x, y, w, [h, [r]])
添加到 2D 上下文原型来绘制一个圆角矩形。
x, y, w, [h, [r]]
Math.min(w * 0.5, h * 0.5)
包括圆角矩形扩展的实现。
function Extend2DRoundedRect() {
const p90 = Math.PI * 0.5;
const p180 = Math.PI;
const p270 = Math.PI * 1.5;
const p360 = Math.PI * 2;
function roundedRect(x, y, w, h = w, r = 0) {
const ctx = this;
if (r < 0) { r = 0 }
if (r === 0) {
ctx.rect(x, y, w, h);
return;
}
r = Math.min(r, w * 0.5, h * 0.5)
ctx.moveTo(x, y + r);
ctx.arc(x + r , y + r , r, p180, p270);
ctx.arc(x + w - r, y + r , r, p270, p360);
ctx.arc(x + w - r, y + h - r, r, 0 , p90);
ctx.arc(x + r , y + h - r, r, p90 , p180);
ctx.closePath();
}
function strokeRoundedRect(...args) {
const ctx = this;
ctx.beginPath();
ctx.roundedRect(...args);
ctx.stroke();
}
function fillRoundedRect(...args) {
const ctx = this;
ctx.beginPath();
ctx.roundedRect(...args);
ctx.fill();
}
CanvasRenderingContext2D.prototype.roundedRect = roundedRect;
CanvasRenderingContext2D.prototype.strokeRoundedRect = strokeRoundedRect;
CanvasRenderingContext2D.prototype.fillRoundedRect = fillRoundedRect;
}
Extend2DRoundedRect();
// Using rounded rectangle extended 2D context
const ctx = canvas.getContext('2d');
ctx.strokeStyle = "#000";
ctx.strokeRoundedRect(10.5, 10.5, 180, 180); // no radius render rectangle
ctx.strokeRoundedRect(210.5, 10.5, 180, 180, 20); // Draw 1px line along center of pixels
ctx.strokeRoundedRect(20, 20, 160, 160, 30);
ctx.fillRoundedRect(30, 30, 140, 140, 20);
ctx.fillRoundedRect(230, 30, 140, 40, 20); // Circle ends
ctx.fillRoundedRect(230, 80, 140, 20, 20); // Auto circle ends
ctx.fillRoundedRect(280, 120, 40, 40, 120); // circle all sides
var inset = 0;
ctx.beginPath();
while (inset < 80) {
ctx.roundedRect(
10 + inset, 210 + inset,
380 - inset * 2, 180 - inset * 2,
50 - inset
);
inset += 8;
}
ctx.fill("evenodd");
<canvas id="canvas" width="400" height="400"></canvas>
答案 1 :(得分:0)
您需要将静态值转换为 (x, y)
坐标和 [width × height]
维度变量。
我采用了您所拥有的,并对公式进行了逆向工程以计算您的静态绘图。将您现有的变量更改为 x
或 y
,并在其中添加 width
或 height
,并在必要时添加或减去 radius
。< /p>
const drawRoundedRect = (ctx, x, y, width, height, radius) => {
ctx.beginPath();
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);
ctx.stroke();
};
const canvas = document.getElementById('new-canvas');
const ctx = canvas.getContext('2d');
ctx.strokeStyle = 'black';
ctx.strokeRect(10, 10, 80, 80);
ctx.strokeStyle = 'red';
drawRoundedRect(ctx, 10, 10, 80, 80, 10);
ctx.strokeStyle = 'green';
drawRoundedRect(ctx, 20, 20, 60, 60, 14);
<canvas id="new-canvas"></canvas>