有没有HarmonyOS鸿蒙Next实现自定义镂空形状的方法,中间的镂空形状可以动态变化

有没有HarmonyOS鸿蒙Next实现自定义镂空形状的方法,中间的镂空形状可以动态变化 需要自定义实现不规则形状的镂空效果并可以动态变化,当前社区的几个帖子都是固定的矩形和圆形的例子。镂空的效果都是通过固定的圆形和方形的API实现的。没有不规则图形镂空的实现。

有没有类似Android PorterDuffXfermode 允许我们在绘制时改变目标与源图形的像素混合方式。通过设置 Mode.CLEAR,可以将绘制区域清除为透明,从而实现镂空效果。

  • 图层混合

    为了让 Xfermode 生效,通常需要在 onDraw() 中调用 canvas.saveLayer() 将目标绘制到一个图层中,再利用 Xfermode 清除特定区域,最后恢复图层合成效果。这种效果的API或实现


更多关于有没有HarmonyOS鸿蒙Next实现自定义镂空形状的方法,中间的镂空形状可以动态变化的实战教程也可以访问 https://www.itying.com/category-93-b0.html

9 回复

你好,请问你这边具体想达到怎么样的效果?能描述一下吗?最好能提供一个动画或者截图。

更多关于有没有HarmonyOS鸿蒙Next实现自定义镂空形状的方法,中间的镂空形状可以动态变化的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


觉得使用Canvas混合模式应该可行,可以利用globalCompositeOperation属性中的destination-out模式,该模式会将新绘制的图形区域与已有内容做减法运算,形成镂空效果。结合Path自定义路径可实现任意形状。

示例

@Entry
@Component
struct DynamicHollow {
  private settings = new RenderingContextSettings(true);
  private ctx = new CanvasRenderingContext2D(this.settings);
  @State pathPoints: number[][] = [[100,100], [150,50], [200,100]]; // 动态路径点

  build() {
    Column() {
      Canvas(this.ctx)
        .onReady(() => this.drawHollow())
        .onClick(() => { 
          // 点击更新路径实现动态变化
          this.pathPoints = this.generateNewPath();
          this.drawHollow();
        })
    }
  }

  private drawHollow() {
    this.ctx.clearRect(0, 0, 300, 300);
    
    // 绘制背景
    this.ctx.fillStyle = 'rgba(0,0,0,0.5)';
    this.ctx.fillRect(0, 0, 300, 300);
    
    // 设置混合模式
    this.ctx.globalCompositeOperation = 'destination-out';
    
    // 绘制自定义路径
    const path = new Path2D();
    path.moveTo(this.pathPoints, this.pathPoints);
    this.pathPoints.forEach(point => {
      path.lineTo(point, point);
    });
    path.closePath();
    this.ctx.fill(path);
    
    // 恢复混合模式
    this.ctx.globalCompositeOperation = 'source-over';
  }
}

不知道楼主是不是想要这种效果,姑且试着写了一下。

```typescript
      Column() {
        Row() {
          Column()
            .width(30)
            .height('100%')
            .borderRadius({
              topLeft: 0,
              topRight: 15,
              bottomLeft: 0,
              bottomRight: 0
            })
            .backgroundColor(Color.Transparent)
            .blendMode(BlendMode.DST_IN, BlendApplyType.OFFSCREEN)

          Column()
            .width(30)
            .height(30)
            .borderRadius({
              topLeft: 10,
              topRight: 15,
              bottomLeft: 15,
              bottomRight: 5
            })
            .backgroundColor(Color.Transparent)
            .blendMode(BlendMode.DST_IN, BlendApplyType.OFFSCREEN)
        }
        .width(63)
        .height(60)
        .zIndex(1)
        .justifyContent(FlexAlign.SpaceBetween)
        .linearGradient({
          direction: GradientDirection.Bottom,
          colors: [[0xff0000, 0.0], [0xffff00, 1.0]]
        })
        .blendMode(BlendMode.SRC_OVER, BlendApplyType.OFFSCREEN)

        Column() {
          ForEach(Array.from({ length: 13 }), (item: undefined, index: number) => {
            Text('Hello World')
          })
        }
        .position({ top: 0 })
      }
```

cke_1033.png

解决了,使用rendernode + Region 实现的

或者通过裁剪、遮罩组合自定义形状试一下?没有现成的API,需要自己搭建下,感觉有难度。如果实现了,期待大佬分享,学习学习!

https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-sharp-clipping

可以试一下canvas的path api,Path-图形绘制-ArkTS组件-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者 路径绘制组件,根据绘制路径生成封闭的自定义形状。并通过fill和fileOpacity设置填充区透明度。

path只能当前层级的形状,如果中间有一层遮罩的话,path并不能透过遮罩直接显示下面的内容,

HarmonyOS Next实现自定义镂空形状可通过Shape组件配合Path完成。使用PathaddRectaddCircle等方法绘制外框,通过appendPath添加镂空区域路径。动态变化镂空需在@State装饰的路径数据变更时触发UI刷新。示例代码片段:

@State path: Path = new Path()
build() {
  Shape()
    .path(this.path)
    .fill(Color.Blue)
}

修改镂空形状时更新path对象并重新赋值给@State变量即可实现动态效果。注意路径方向需遵循非零绕数规则。

在HarmonyOS Next中实现自定义镂空形状并支持动态变化,可以使用Canvas的Path和Clip能力。以下是关键实现方案:

  1. 使用Path定义任意形状:
// 创建Path对象
let path = new Path()
// 添加自定义路径(示例为五角星)
path.moveTo(200, 50)
path.lineTo(250, 150)
path.lineTo(350, 150)
// ...继续添加其他顶点

// 设置裁剪区域
canvas.clipPath(path, CanvasClipRule.NON_ZERO)
  1. 动态更新镂空区域:
// 更新Path路径
path.reset()
path.moveTo(newX, newY)
// 添加新的顶点坐标
...

// 重绘触发更新
this.controller.setNeedsRedraw()
  1. 复合镂空效果可通过叠加多个Path实现:
// 创建组合Path
let compoundPath = new Path()
compoundPath.addPath(path1)
compoundPath.addPath(path2, {x: offsetX, y: offsetY})

// 设置反向裁剪(镂空)
canvas.clipPath(compoundPath, CanvasClipRule.INVERSE)
  1. 性能优化建议:
  • 对于复杂路径,考虑使用Path.op()进行布尔运算
  • 动态变化时使用requestAnimationFrame控制刷新频率
  • 对静态部分使用离屏Canvas缓存

相比Android的PorterDuffXfermode,HarmonyOS的Path+Clip方案更轻量且支持硬件加速,适合实现动态不规则镂空效果。

回到顶部