鴻蒙HarmonyOS實戰-ArkUI元件(Shape)

蜀道山QAQ發表於2024-04-17

🚀一、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)
      }
    }
  }
}

image

🦋1.2 單獨使用

image

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

image

其他的就不做多介紹

🔎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')
        }
      }
    }
  }
}

image

將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")
        }
      }
    }
  }
}

image

🔎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)
      }
    }
  }
}

image

🔎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])
      }
    }
  }
}

image

🚀寫在最後

  • 如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
  • 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
  • 關注小編,同時可以期待後續文章ing🚀,不定期分享原創知識。
  • 更多鴻蒙最新技術知識點,請關注作者部落格:https://t.doruo.cn/14DjR1rEY

image

相關文章