鴻蒙繪制凹形布局,滑動(dòng)進(jìn)行大小重繪

當(dāng)系統(tǒng)布局無(wú)法滿足需求的時(shí)候,就需要自己繪制了,我的需求是繪制如下圖,且跟跟隨上下滑動(dòng)調(diào)整凹形大小。


snapshot_2024-11-11_10-33-59 拷貝.png

布局分析

對(duì)關(guān)鍵點(diǎn)拆分如下圖:


image.png
  1. 三個(gè)一樣大小的圓
  • 進(jìn)行外切
  1. 中間的凹形
  • DG弧度繪制
  • AD/GE弧度繪制
  1. 上下滑動(dòng)凹形大小尺寸變化
  • 通過(guò)官網(wǎng)查詢,最合適是使用Canvas,但Canvas.onReady只繪制一次,可以通過(guò)@Watch監(jiān)聽(tīng)變量(圓的直徑)大小變化解決

用到的知識(shí)

1. 勾股定理

在平面上的一個(gè)直角三角形中,兩個(gè)直角邊邊長(zhǎng)的平方加起來(lái)等于斜邊長(zhǎng)的平方。如果設(shè)直角三角形的兩條直角邊長(zhǎng)度分別是和,斜邊長(zhǎng)度是,那么可以用數(shù)學(xué)語(yǔ)言表達(dá):


image.png

2. 弧度與角度轉(zhuǎn)化

弧度與角度轉(zhuǎn)換公式
1)將弧度轉(zhuǎn)換為角度:乘以 180,除以 π
2)將角度轉(zhuǎn)換為弧度:乘以 π,除以 180

這是弧度與角度的對(duì)照列表:

角度 弧度(精確) 弧度(近似)
30° π/6 0.524
45° π/4 0.785
60° π/3 1.047
90° π/2 1.571
180° π 3.142
270° 3π/2 4.712
360° 6.283

布局開(kāi)始繪制

對(duì)于以上的布局分析,可以知道,布局繪制,其實(shí)畫(huà)三個(gè)弧線就可以完成了,代碼如下:

// AD左上弧-起始角度270,終點(diǎn)角度330
this.context.arc(centerX - mar, radius, radius, 270 * Math.PI / 180, 330 * Math.PI / 180)
// DG底部弧-起始角度150,終點(diǎn)角度30
this.context.arc(centerX, 0, radius, 150 * Math.PI / 180, 30 * Math.PI / 180, true)
// GE右上弧-起始角度210,終點(diǎn)角度270
this.context.arc(centerX + mar, radius, radius, 210 * Math.PI / 180, 270 * Math.PI / 180)

完整代碼如下

// 上下滑動(dòng)修改fabSize的大小,使Canvas重新繪制
@State @Watch('drawBottomBar') fabSize: number = 80

drawBottomBar() {
    let width = this.context.width
    let height = this.context.height
    // 刪除之前繪制的,重新繪制
    this.context.clearRect(0, 0, width, height)
    this.context.beginPath()

    let centerX = width / 2
    let radius = this.fabSize / 2
    // AB/BE的距離
    let mar = Math.sqrt(Math.pow(this.fabSize, 2) - Math.pow(radius, 2))
    // 左上直線
    this.context.lineTo(centerX - mar, 0)
    // AD左上弧-起始角度270,終點(diǎn)角度330
    this.context.arc(centerX - mar, radius, radius, 270 * Math.PI / 180, 330 * Math.PI / 180)
    // DG底部弧-起始角度150,終點(diǎn)角度30
    this.context.arc(centerX, 0, radius, 150 * Math.PI / 180, 30 * Math.PI / 180, true)
    // GE右上弧-起始角度210,終點(diǎn)角度270
    this.context.arc(centerX + mar, radius, radius, 210 * Math.PI / 180, 270 * Math.PI / 180)
    // 右上直線
    this.context.lineTo(width, 0)
    // 右下直線
    this.context.lineTo(width, height)
    // 底部直線
    this.context.lineTo(0, height)
    // 閉合
    this.context.closePath()
    // 顏色
    this.context.fillStyle = '#344955'
    // 填充
    this.context.fill()
}

build() {
    Stack() {
      Canvas(this.context)
        .height(80)
        .width('100%')
        .onReady(() => {
          this.drawBottomBar()
        })
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容