玩转canvas之实现一个圆角矩形

在canvas中绘制一个矩形是非常简单的,使用canvas的rect()方法即可,但是没有办法绘制一个带圆角的矩形,如图:
在这里插入图片描述

代码

class DrawBoard extends BasicCanvas{
  constructor(c){
    super(c)
  }
  // 如何绘制带圆角的矩形
  createRect(x,y,w,h,r = 0,{width,stroke,fill}={}){
    r > 1/2*w ? r = 1/2*w : null
    let x1 = x + r, x2 = x + w - r, x3 = x + w
    let y1 = y + r, y2 = y + h -r, y3 = y + h
    this.begin()
    .start(x+1/2*w,y)
    .link(x2, y)
    .qbc(x3, y, x3, y1)
    .link(x3,y2)
    .qbc(x3, y3, x2, y3)
    .link(x1, y3)
    .qbc(x, y3, x, y2)
    .link(x, y1)
    .qbc(x, y, x1, y)
    .end()
    .lineStyle(width)
    .stroke(stroke)
    .fill(fill)
  }
}

上面的代码是基于前几期写的玩转canvas系列封装的BasicCanvas类,有兴趣的可以去看一下,现在这个类是DrawBoard类,主要是用于封装一些图形方法

原理

思路

绘制一个圆角的矩形,主要使用的是canvas中的path路径方法,以及二次贝塞尔曲线方法,主要思路是直线的部分使用lineTo方法,曲线部分使用二次贝塞尔曲线方法(下面简称称为 qbc)

分析

根据上面的思路,我们大致可以将矩形分割为这几个部分(见下图),横轴的部分主要有四个区域x,x1,x2,x3,纵轴的区域是y,y1,y2,y3。
x,y是需要我们传入的参数,主要用于定义矩形左上角在canvas画布中的位置
x1 = x + r
x2 = x + w - r
x3 = x + w
y1 = y + r
y2 = y + h - r
y3 = y + h
其中 r 是圆角的半径,w 是矩形的宽,h 是矩形的高

讲解

首先需要定义起点
起点不应定义为左上角,应定义在矩形上方的中心,也是下图标定的地方。

this.begin()
// 起点坐标(x+1/2w, y+1/2h)
.start(x+1/2*w,y)
// 然后连接到点(x2, y)
.link(x2, y)
// 使用qbc方法,控制点(x3, y)结束点(x3, y1)
.qbc(x3, y, x3, y1)
// 然后连接到点(x3,y2)
.link(x3,y2)
// 使用qbc方法,控制点(x3, y3)结束点(x2, y3)
.qbc(x3, y3, x2, y3)
// 然后连接到点(x1, y3)
.link(x1, y3)
// 使用qbc方法,控制点(x, y3)结束点(x, y2)
.qbc(x, y3, x, y2)
// 然后连接到点(x, y1)
.link(x, y1)
// 使用qbc方法,控制点(x, y)结束点(x1, y)
.qbc(x, y, x1, y)
// 最后结束 
.end()
.lineStyle(width)
.stroke(stroke)
.fill(fill)

看下图
在这里插入图片描述

缺陷

这个方法其实是有一定缺陷的,也就是使用qbc方法实现的圆角并非真正的圆角,我们将其圆角设为宽度的一半的时候,这个图像展现的应该是一个圆,但实际图像并非正规的圆
在这里插入图片描述

改进

改进圆角非正规圆角的问题

将使用qbc方法制作圆角的方法改成使用arc方法来制作圆角,这样即可实现真正的圆角

this.begin()
// 开始的点还是上方中心点
.start(x+1/2*w,y)
.link(x2, y)
// 使用四分之一的圆做圆角,起始角度是3/2*pi,结束角度是0
.circular(x2, y1, r, 3/2*pi, 0, false)
.link(x3,y2)
// 使用四分之一的圆做圆角,起始角度是0,结束角度是1/2*pi
.circular(x2, y2, r, 0, 1/2*pi, false)
.link(x1, y3)
// 使用四分之一的圆做圆角,起始角度是1/2*pi,结束角度是pi
.circular(x1, y2, r, 1/2*pi, pi, false)
.link(x, y1)
// 使用四分之一的圆做圆角,起始角度是pi,结束角度是3/2*pi
.circular(x1, y1, r, pi, 3/2*pi, false)
.end()

这里使用的circlar是自己封装的绘制圆形的方法,与arc()方法传递的参数几乎相同,只是我的方法可以链式调用使用起来更加便捷。

改进后的代码实现的圆角

在这里插入图片描述
在这里插入图片描述
这样就是很正规的圆角了
并且由于传入的圆角半径不能超过其最短边的一半,否则就会这样
在这里插入图片描述

改进圆角过大的问题

因此我们需要加上短边判断
首先判断出短边,然后判断短边的一半与圆角的大小关系

w >= h ? r > 1/2*h ? r = 1/2*h : null : r > 1/2*w ? r = 1/2*w : null

改进后
在这里插入图片描述
这样就是正常的圆角了

总结

实现圆角矩形的方法起始有多种,有兴趣的童鞋可以自己发挥一下脑洞,只要判断好直线与圆角的绘制就可以实现了。

完整代码

createRect(
x, // 矩形左上角x坐标
y, // 矩形左上角y坐标
w, // 矩形宽
h, // 矩形高
r = 0, // 圆角半径
{width,stroke,fill}={} // 样式 边框宽度,边框颜色,填充颜色
){
  w >= h ? r > 1/2*h ? r = 1/2*h : null : r > 1/2*w ? r = 1/2*w : null
  console.log(r)
  let x1 = x + r, x2 = x + w - r, x3 = x + w
  let y1 = y + r, y2 = y + h -r, y3 = y + h
  let pi = Math.PI
  this.begin()
  .start(x+1/2*w,y)
  .link(x2, y)
  // .qbc(x3, y, x3, y1)
  .circular(x2, y1, r, 3/2*pi, 0, false)
  .link(x3,y2)
  // .qbc(x3, y3, x2, y3)
  .circular(x2, y2, r, 0, 1/2*pi, false)
  .link(x1, y3)
  // .qbc(x, y3, x, y2)
  .circular(x1, y2, r, 1/2*pi, pi, false)
  .link(x, y1)
  // // .qbc(x, y, x1, y)
  .circular(x1, y1, r, pi, 3/2*pi, false)
  .end()
  .lineStyle(width)
  .stroke(stroke)
  .fill(fill)
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值