HarmonyOS 鸿蒙Next 使用clipShape进行裁剪后,borderRadius无法生效怎么处理
【问题现象】
对容器组件使用clipShape进行裁剪后,再使用borderRadius对被裁剪容器设置圆角时无法生效,如下图所示效果:
【背景知识】
1. 设置组件圆角的方法
1.1 borderRadius
borderRadius属性用于设置组件边框的圆角,可以同时设置四个角,也可以分别对四个角的圆角大小进行设置。为了避免因子组件尺寸大于组件,导致子组件覆盖圆角,可以搭配属性clip使用。
1.2 clipShape
clipShape属性用于对组件进行形状裁剪,通过传入不同的组件类型,将组件裁剪为对应的形状。
2. 绘制圆角的方法
2.1 Path
- Path是路径绘制组件,可以通过commands属性绘制出需求的形状,包括圆角(圆角多边形)。
- 关于贝塞尔曲线和控制点的关系:由一组控制点的向量决定,给定的控制点按顺序连接构成控制多边形。
2.2 Path和clipShape的区别
- Path是绘制组件,通过设置路径绘制出需求的形状,其填充区域一般是颜色而非图片。
- clipShape是通用属性,通过设置不同组件类型对组件进行裁剪,裁剪后的形状背景是组件的一部分。比如对Image组件进行裁剪,裁剪后的形状背景是该Image组件图片的一部分。
【定位思路】
borderRadius属性从规格上是相对于组件的大小而言的,当组件同时设置borderRadius和clipShape时,borderRadius会首先生效,对整个组件设置圆角效果,然后clipShape裁剪效果会覆盖borderRadius的圆角效果,导致borderRadius不生效。
【解决方案】
1. 对裁剪的组件设置圆角
使用clipShape对组件进行裁剪时,根据需求,对需设置为圆角的角进行圆角裁剪处理。被裁剪的组件可以是容器组件(如Column、Row等)或Image组件。
注意:不能设置两次clipShape属性进行多次裁剪,否则最后一个clipShape的裁剪将会覆盖前面的clipShape裁剪。
以下示例对Image组件设置clipShape属性,使用PathShape形状描述组件被裁剪后的形状。
代码示例如下:
@Entry
@Component
struct ClipFilletCorner {
// 定义PathShape绘制的路线
/*
绘制原始图形,即不裁剪,绘制路线的单位为px,宽高默认单位为vp,可以按需要使用像素单位转换方法进行转换
*/
commands1:string=`M0 0 L${vp2px(300)} 0 L${vp2px(300)}${vp2px(200)} L0 ${vp2px(200)} Z`
/*
将图片裁剪为三角形
* commands的命令M是定义绘制的起点,如M0 0是定义点(0, 0)为绘制起点
* commands的命令L是绘制当前点到指定点的直线,如L600 0是绘制当前点到(600, 0)的直线
* commands的命令Z是指绘制当前点到起点的直线并结束绘制
*/
commands2:string='M0 0 L600 0 L600 300 Z'
/*
将图片裁剪为带圆角的不规则图形
* commands的命令H是绘制当前点到对应x坐标的点的水平线,如M0 100 H300是绘制从(0, 100)到(300, 100)的水平线
* commands的命令V是绘制当前点到对应y坐标的点的垂直线,如M100 0 V300是绘制从(100, 0)到(100, 300)的垂直线
* commands的命令S是绘制当前点到终点的二次贝塞尔曲线,前两个值是设置控制点,后两个值是曲线终点
*/
commands3:string='M0 100 S0 0 100 0 H300 S400 0 400 100 V300 S400 400 300 400 H200Z'
@State shapeNum:number=1
build() {
Column() {
// 待裁剪图片
Image($r('app.media.startIcon'))
.height(200)
.width(300)
.margin({top:10, bottom:10})
.objectFit(ImageFit.Cover)
.borderRadius({topRight:5})
.clipShape(newPathShape().commands(this.shapeNum===1?this.commands1:this.shapeNum===2?this.commands2:this.commands3))
// 定义命令控制器
Row() {
Button('Original')
.type(ButtonType.Capsule)
.width(80)
.onClick(() => {
this.shapeNum=1
})
Button('Triangle')
.type(ButtonType.Capsule)
.width(80)
.onClick(() => {
this.shapeNum=2
})
Button('Irregular')
.type(ButtonType.Capsule)
.width(80)
.onClick(() => {
this.shapeNum=3
})
}.width(300)
.height(100)
.justifyContent(FlexAlign.SpaceEvenly)
}.width('100%')
.height('40%')
.backgroundColor(Color.Orange)
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
}
效果图:
2. 绘制带圆角的组件
某些场景下可能需要绘制出带有圆角或其他形状的图形,此时可以使用Path组件进行绘制。
代码示例如下:
@Entry
@Component
struct PathFilletCorner {
build() {
Row() {
// 绘制上一示例的带圆角的不规则图形
Path()
.fill(Color.Pink)
.stroke(Color.Blue)
// 命令与上一示例的commands3相同
.commands('M0 100 S0 0 100 0 H300 S400 0 400 100 V300 S400 400 300 400 H200Z')
// 绘制带圆角的三角形
Path()
.fill(Color.Brown)
.commands('M120 150 L480 150 S600 150 480 90 L360 30 S300 0 240 30 L120 90 S0 150 120 150Z')
}.width('100%')
.height('40%')
.backgroundColor(Color.Orange)
.justifyContent(FlexAlign.SpaceEvenly)
.alignItems(VerticalAlign.Center)
}
}
效果图:
【总结】
- 当对组件进行圆角设置时,可以使用borderRadius属性。
- 当需要对裁剪后的组件进行圆角设置时,borderRadius属性的效果会被覆盖,可以在使用clipShape对组件进行裁剪时,使用PathShape形状按需要进行形状和圆角的裁剪。
- 当需要绘制带圆角的图形时,可以使用Path组件进行绘制。
更多关于HarmonyOS 鸿蒙Next 使用clipShape进行裁剪后,borderRadius无法生效怎么处理的实战教程也可以访问 https://www.itying.com/category-93-b0.html