【愚公系列】2023年12月 HarmonyOS教学课程 028-ArkUI组件(Shape)

举报
愚公搬代码 发表于 2023/12/31 19:30:41 2023/12/31
【摘要】 🏆 作者简介,愚公搬代码🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,51CTO博客专家等。🏆《近期荣誉》:2023年华为云十佳博主,2022年CSDN博客之星TOP2,2022年华为云十佳博主等。🏆《博客内容》:.NET、Java、...

🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2023年华为云十佳博主,2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏

🚀一、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 单独使用

绘制类型 简要说明
Circle 绘制一个圆,需要指定圆心的坐标和半径。
Ellipse 绘制一个椭圆,需要指定椭圆的中心点、长轴和短轴的长度。
Line 绘制一条直线,需要指定起点和终点的坐标。
Polyline 绘制一条由多个点连接而成的折线,需要指定每个点的坐标。
Polygon 绘制一个封闭的多边形,需要指定每个点的坐标。
Path 绘制一条复杂的路径,可以包含直线、曲线、圆弧等多个元素。
Rect 绘制一个矩形,需要指定左上角和右下角的坐标。
@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])
      }
    }
  }
}

在这里插入图片描述


🚀感谢:给读者的一封信

亲爱的读者,

我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。

如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。

我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。

如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。

在这里插入图片描述

再次感谢您的阅读和支持!

最诚挚的问候, “愚公搬代码”

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。