原来 Canvas 也能直接绘制圆角矩形了
很多时候,在使用 Canvas 绘制圆角矩形都是一件比较麻烦的事,因为之前并没有直接的方法,只能通过直线和圆弧间接组合而成,下面是一个常规绘制方式
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x + w, y, x + w, y + h, r);
ctx.arcTo(x + w, y + h, x, y + h, r);
ctx.arcTo(x, y + h, x, y, r);
ctx.arcTo(x, y, x + w, y, r);
ctx.closePath();
这里
x
、y
、w
、h
、r
分别代表x 坐标、y 坐标、宽度、高度、圆角。
这段代码应该是最精简的了,虽然不是特别复杂,但是应该很少有人能直接手写,主要是不够语义化,比较繁琐。
而圆角矩形又是一个非常常见的功能需求,为此,Canvas 在Chrome 99
悄悄推出了一个新的方法:roundRect()[1],花一分钟了解一下
一、roundRect 语法
roundRect
,顾名思义,就是圆角矩形,和 rect[2]用法一致,只是参数上多了一个圆角radii
image-20221218183223938
这里x
、y
、w
、h
就不介绍了,重点介绍一下这个圆角radii
。
圆角radii
有以下几种取值
all-corners
,只有 1 一个值的时候,表示所有 4 个圆角[all-corners]
,也可以是数组,当只有 1 一个值的时候,也表示 4 个圆角[top-left-and-bottom-right, top-right-and-bottom-left]
,数组为 2 个值的时候,表示 左上、右下 圆角 和 右上、左下 圆角[top-left, top-right-and-bottom-left, bottom-right]
,数组为 3 个值的时候,表示 左上 圆角、右上、左下 圆角 和 右下 圆角[top-left, top-right, bottom-right, bottom-left]
,数组为 4 个值的时候,表示 左上 圆角、右上 圆角 、 右下 圆角和 左下 圆角
看似麻烦,其实就是和 CSS 中的圆角规则是一致的,稍微看一眼就能明白
下面来看具体的效果
二、roundRect 案例及细节
首先来看一个值的,可以满足绝大部分情况
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
ctx.strokeStyle = "red";
ctx.beginPath();
ctx.roundRect(20, 20, 150, 100, 10);
ctx.stroke();
效果如下
当然这个值也是可以省略的,这样就没有圆角了,等同于rect
ctx.roundRect(20, 20, 150, 100);
效果如下
再来看数组的情况,比如两个值的,就像这样
ctx.roundRect(20, 150, 150, 100, [10, 40]);
效果如下
再来看 4 个值的情况
ctx.roundRect(200, 20, 150, 100, [0, 30, 50, 60]);
效果如下
如果这个圆角非常大呢,超出了矩形的尺寸会怎么样呢?
ctx.roundRect(200, 20, 150, 100, 300);
可以看到,这种情况也是完美适配,和 CSS 表现完全一致,变成了跑道形状,效果如下
还有需要注意的是,这个 圆角不能为负数 ,否则直接报错
整代码可以查看以下任意链接
- canvas roundRect (juejin.cn)[3]
- canvas roundRect (codepen.io)[4]
- canvas roundRect (runjs.work)[5]
三、兼容性和 polyfill
这个方法还比较新,也就是今年初才推出的,兼容性还不是特别好,如下
除了firefox
,其他主流浏览器都已经兼容。
当然也不用担心,这个也是有polyfill
的,如下
其实实现上还是比较复杂的,考虑的情况非常多,各种临界场景,参数的数量。这也是为什么推荐用原生 API 的原因的,语法容错性太强了!
参考资料
[1] roundRect(): https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/roundRect
[2] rect: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/rect
[3] canvas roundRect (juejin.cn): https://code.juejin.cn/pen/7178419723002970145
[4] canvas roundRect (codepen.io): https://codepen.io/xboxyan/pen/wvxwbWv
[5] canvas roundRect (runjs.work): https://runjs.work/projects/1ceee49205914def