鸿蒙HarmonyOS实战-ArkUI组件(Shape)

🚀一、Shape

Shape组件是用于创建2D形状和粒子效果的组件。它可以创建包括圆形、正方形、三角形和多边形等基本形状,同时还可以自定义形状。Shape组件创建各种不同的效果,例如火花、烟雾、雨滴等。在使用Shape组件时,可以通过编辑顶点、路径和大小等属性来控制形状的外观和行为。

🔎1.创建绘制组件

🦋1.1 Shape嵌套使用

使用Shape作为父组件,实现类似SVG的效果

Shape(value?: PixelMap)

其中value用于设置绘制目标,可将图形绘制在指定的PixelMap对象中,若未设置,则在当前绘制目标中进行绘制。

@Entry
@Component
struct MyComponent {
  build() {
    Column() {
      Shape() {
        Rect().width(300).height(50)
      }
    }
  }
}

🦋1.2 单独使用

@Entry
@Component
struct MyComponent {
  build() {
    Column() {
      Circle({ width: 150, height: 150 })
    }
  }
}

其他的就不做多介绍

🔎2.形状视口viewport

形状视口(Shape Viewport)是SVG(Scalable Vector Graphics)中的一个重要概念,它指定了用户空间中的一个矩形,并将该矩形映射到与该SVG元素相关联的视区边界上,用于在屏幕上渲染出SVG图像。在SVG中,每个元素都有一个默认的视口,可以通过设置viewport属性来自定义视口。viewport属性的值包括四个可选参数,分别为x、y、width和height,用于定义视口的位置和大小。其中,x和y表示视口左上角的坐标,width和height表示视口的尺寸。

由于SVG是一种矢量图形格式,可以在不失真的情况下自由缩放,因此视口设置在设计中具有非常重要的作用。通过指定不同的视口大小和缩放级别,可以使SVG图像在不同的设备和屏幕尺寸下以最佳方式呈现。

viewport属性指定的是视口在用户空间中的位置和大小,而不是在屏幕上的位置和大小。在实际应用中,需要根据屏幕分辨率、窗口大小等因素计算出实际的屏幕位置和大小,并将视口映射到屏幕上。因此,在设计SVG图像时需要考虑不同设备和屏幕尺寸的差异,以保证图像能够在各种情况下显示得清晰、流畅和美观。

viewPort{ x?: number | string, y?: number | string, width?: number | string, height?: number | string }

案例:

@Entry
@Component
struct MyComponent {
  build() {
    Column() {
      // 画一个宽高都为150的圆
      Text('原始尺寸Circle组件')
      Circle({width: 75, height: 75}).fill('#E87361')

      Row({space:10}) {
        Column() {
          // 创建一个宽高都为150的shape组件,背景色为黄色,一个宽高都为75的viewport。用一个蓝色的矩形来填充viewport,在viewport中绘制一个直径为75的圆。
          // 绘制结束,viewport会根据组件宽高放大两倍
          Text('shape内放大的Circle组件')
          Shape() {
            Rect().width('100%').height('100%').fill('#0097D4')
            Circle({width: 75, height: 75}).fill('#E87361')
          }
          .viewPort({x: 0, y: 0, width: 75, height: 75})
          .width(150)
          .height(150)
          .backgroundColor('#F5DC62')
        }
        Column() {
          // 创建一个宽高都为150的shape组件,背景色为黄色,一个宽高都为300的viewport。用一个绿色的矩形来填充viewport,在viewport中绘制一个直径为75的圆。
          // 绘制结束,viewport会根据组件宽高缩小两倍。
          Text('Shape内缩小的Circle组件')
          Shape() {
            Rect().width('100%').height('100%').fill('#BDDB69')
            Circle({width: 75, height: 75}).fill('#E87361')
          }
          .viewPort({x: 0, y: 0, width: 300, height: 300})
          .width(150)
          .height(150)
          .backgroundColor('#F5DC62')
        }
      }
    }
  }
}

将viewport向右方和下方各平移150

@Entry
@Component
struct MyComponent {
  build() {
    Column() {
      Row({space:10}) {
        Column() {
          Shape() {
            Rect().width("100%").height("100%").fill("#0097D4")
            Circle({ width: 150, height: 150 }).fill("#E87361")
          }
          .viewPort({ x: 0, y: 0, width: 300, height: 300 })
          .width(300)
          .height(300)
          .backgroundColor("#F5DC62")
        }
        Column() {
          Shape() {
            Rect().width("100%").height("100%").fill("#0097D4")
            Circle({ width: 150, height: 150 }).fill("#E87361")
          }
          .viewPort({ x: -150, y: -150, width: 300, height: 300 })
          .width(300)
          .height(300)
          .backgroundColor("#F5DC62")
        }
      }
    }
  }
}

🔎3.自定义样式

抗锯齿和斜接长度与边框宽度比值是设计和开发中的一个重要概念,用于控制图形边缘的清晰度和平滑度,以提高视觉效果。

抗锯齿是一种技术,用于减少在图像中出现的锯齿状边缘,从而实现更加平滑的边缘效果。斜接长度是指在设计中将边缘的两个颜色混合,从而实现平缓的过渡效果。

边框宽度比值是指图形的边框宽度和图形本身大小的比值。通常,在设计中,边框宽度比值为 1:10 是一种常见的比例。

在实际开发中,为了获得最佳的视觉效果,抗锯齿和斜接长度的比值通常应与边框宽度比值相匹配。这样可以确保图像边缘的清晰度和平滑度与整个设计的比例保持一致。

@Entry
@Component
struct MyComponent {
  build() {
    Column() {
      Row(){
        //通过fill可以设置组件填充区域颜色
        Path()
          .width(100)
          .height(100)
          .commands('M150 0 L300 300 L0 300 Z')
          .fill("#E87361")
        //通过stroke可以设置组件边框颜色
        Path()
          .width(100)
          .height(100)
          .fillOpacity(0)
          .commands('M150 0 L300 300 L0 300 Z')
          .stroke(Color.Red)
        //通过strokeOpacity可以设置边框透明度
        Path()
          .width(100)
          .height(100)
          .fillOpacity(0)
          .commands('M150 0 L300 300 L0 300 Z')
          .stroke(Color.Red)
          .strokeWidth(10)
          .strokeOpacity(0.2)

      }
      Row(){
        //通过strokeLineJoin可以设置线条拐角绘制样式。拐角绘制样式分为Bevel(使用斜角连接路径段)、Miter(使用尖角连接路径段)、Round(使用圆角连接路径段)
        Polyline()
          .width(100)
          .height(100)
          .fillOpacity(0)
          .stroke(Color.Red)
          .strokeWidth(8)
          .points([[20, 0], [0, 100], [100, 90]])
            // 设置折线拐角处为圆弧
          .strokeLineJoin(LineJoinStyle.Round)
        //通过strokeMiterLimit设置斜接长度与边框宽度比值的极限值。
        // 斜接长度表示外边框外边交点到内边交点的距离,边框宽度即strokeWidth属性的值。strokeMiterLimit取值需大于等于1,且在strokeLineJoin属性取值LineJoinStyle.Miter时生效
        Polyline()
          .width(100)
          .height(100)
          .fillOpacity(0)
          .stroke(Color.Red)
          .strokeWidth(10)
          .points([[20, 0], [20, 100], [100, 100]])
            // 设置折线拐角处为尖角
          .strokeLineJoin(LineJoinStyle.Miter)
            // 设置斜接长度与线宽的比值
          .strokeMiterLimit(1/Math.sin(45))
        Polyline()
          .width(100)
          .height(100)
          .fillOpacity(0)
          .stroke(Color.Red)
          .strokeWidth(10)
          .points([[20, 0], [20, 100], [100, 100]])
          .strokeLineJoin(LineJoinStyle.Miter)
          .strokeMiterLimit(1.42)
      }
      Row(){
        //通过antiAlias设置是否开启抗锯齿,默认值为true(开启抗锯齿)
        Circle()
          .width(150)
          .height(200)
          .fillOpacity(0)
          .strokeWidth(5)
          .stroke(Color.Black)
        //关闭抗锯齿
        Circle()
          .width(150)
          .height(200)
          .fillOpacity(0)
          .strokeWidth(5)
          .stroke(Color.Black)
          .antiAlias(false)
      }
    }
  }
}

🔎4.场景示例

@Entry
@Component
struct MyComponent {
  build() {
    Column() {
      Row(){
        Shape() {
          Path().width(200).height(60).commands('M0 0 L400 0 L400 150 Z')
        }
        .viewPort({ x: -80, y: -5, width: 500, height: 300 })
        .fill(0x317AF7)
        .stroke(Color.Red)
        .strokeWidth(3)
        .strokeLineJoin(LineJoinStyle.Miter)
        .strokeMiterLimit(5)
      }
      Row(){
        //绘制一个直径为150的圆
        Circle({ width: 150, height: 150 })
        //绘制一个直径为150、线条为红色虚线的圆环
        Circle()
          .width(150)
          .height(200)
          .fillOpacity(0)
          .strokeWidth(3)
          .stroke(Color.Red)
          .strokeDashArray([1, 2])
      }
    }
  }
}

🚀写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 更多鸿蒙最新技术知识点,请关注作者博客:https://t.doruo.cn/14DjR1rEY