要实现顶部或底部有凹凸弧度的矩形或图片,实现的效果如下:
第一步:需要定义生成顶部或底部有弧度的矩形的函数
- 参数定义:topRadianHeight: 顶部弧度的高度,大于0为顶部凸,小于0为顶部凹;bottomRadianHeight:底部弧度高度,大于0为底部凸,小于0为底部凹
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47/**
* 画顶部或底部有弧度的矩形或图片需要用到的方法
* @param params
* @param topRadianHeight 顶部弧度,大于0为顶部凸,小于0为顶部凹
* @param bottomRadianHeight 底部弧度,大于0为底部凸,小于0为底部凹
* @param ctx
*/
const toDrawArcRect = (params, ctx) => { // 画上下左右方向有弧度的矩形
const {
left, top, width, height,
topRadianHeight, bottomRadianHeight
} = params
const halfWidth = width / 2
const radianHeight = topRadianHeight || bottomRadianHeight || 0
const r = (halfWidth * halfWidth + radianHeight * radianHeight) / (2 * Math.abs(radianHeight))
const radiusX = left + halfWidth // 圆心X的坐标
const radianValue = Math.acos(halfWidth / r) // 弧度
ctx.beginPath()
if (bottomRadianHeight) { // 底部凸
if (bottomRadianHeight > 0) {
ctx.arc(radiusX, top + height - r, r, radianValue, -radianValue + Math.PI)
ctx.lineTo(left, top)
ctx.lineTo(left + width, top)
ctx.lineTo(left + width, top - radianHeight + height)
} else { // 底部凹
ctx.arc(radiusX, top + height + r + radianHeight, r, radianValue - Math.PI, -radianValue)
ctx.lineTo(left + width, top)
ctx.lineTo(left, top)
ctx.lineTo(left, top + height)
}
return
}
if (topRadianHeight) {
if (topRadianHeight > 0) { // 顶部凸
ctx.arc(radiusX, top + r, r, radianValue - Math.PI, -radianValue)
ctx.lineTo(left + width, top + height)
ctx.lineTo(left, top + height)
ctx.lineTo(left, top + radianHeight)
} else { // 顶部凹
ctx.arc(radiusX, top - r - topRadianHeight, r, radianValue, -radianValue + Math.PI)
ctx.lineTo(left, top + height)
ctx.lineTo(left + width, top + height)
ctx.lineTo(left + width, top)
}
}
}
第二步:绘制顶部或底部有凹凸弧度的线框、矩形或图片
- 画线框
1
2toDrawArcRect(***)
this.ctx.stroke() - 画矩形
1
2toDrawArcRect(***)
this.ctx.fill() - 画图片_注:原理是,clip() 方法会在原始画布上剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。可以在使用 clip() 方法前通过使用 save() 方法对当前画布区域进行保存,并在以后的任意时间通过 restore() 方法对其进行恢复。
1
2
3
4
5
6
7this.ctx.save()
toDrawArcRect(***)
ctx.strokeStyle = 'rgba(255,255,255,0)'
ctx.stroke()
this.ctx.clip()
this.ctx.drawImage(***)
this.ctx.restore()