動態

詳情 返回 返回

鴻蒙元服務實戰-笑笑五子棋(3) - 動態 詳情

鴻蒙元服務實戰-笑笑五子棋(3)

接上篇。上一篇主要講解了元服務的創建和 canvas 的一些基本使用,直線、矩形、弧形、文本、圖像等。canvas 本身還有很多其他

的功能。這裏繼續圍繞 canvas 進行講解。

createPattern

createPattern(image: ImageBitmap, repetition: string | null): CanvasPattern | null

通過指定圖像和重複方式創建圖片填充的模板。

參數名 類型 必填 説明
image ImageBitmap 圖源對象,具體參考 ImageBitmap 對象。
repetition string \ null 設置圖像重複的方式:'repeat':沿 x 軸和 y 軸重複繪製圖像;'repeat-x':沿 x 軸重複繪製圖像;'repeat-y':沿 y 軸重複繪製圖像;'no-repeat':不重複繪製圖像;'clamp':在原始邊界外繪製時,超出部分使用邊緣的顏色繪製;'mirror':沿 x 軸和 y 軸重複翻轉繪製圖像。

提前準備好圖片

image-20250105085559069

基本使用

  1. 基於圖片創建填充模版
  2. 設置到 canvas 的 fillStyle 中
  3. 進行描繪
@Entry
@Component
struct Index {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  private img: ImageBitmap = new ImageBitmap("/images/2.png")

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#ffff00')
        .onReady(() => {
          // 1  基於圖片創建填充模版
2.
          let pattern = this.context.createPattern(this.img, 'no-repeat') // 不平鋪
          if (pattern) {
            // 2 設置到canvas的fillStyle中
            this.context.fillStyle = pattern
          }
          // 3 進行描繪
          this.context.fillRect(0, 0, 400, 400)
        })
    }
    .width('100%')
    .height('100%')
  }
}

效果

image-20250105085914214

repetition:repeat

設置平鋪

let pattern = this.context.createPattern(this.img, "repeat");

效果

image-20250105090015220

clamp

在原始邊界外繪製時,超出部分使用邊緣的顏色繪製;
let pattern = this.context.createPattern(this.img, "clamp");

image-20250105090145764

mirror

沿 x 軸和 y 軸重複翻轉繪製圖像。
let pattern = this.context.createPattern(this.img, "mirror");

image-20250105090203370

quadraticCurveTo

quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void

創建二次貝賽爾曲線的路徑。

參數名 類型 必填 説明
cpx number 貝塞爾參數的 x 座標值。默認單位:vp。
cpy number 貝塞爾參數的 y 座標值。默認單位:vp。
x number 路徑結束時的 x 座標值。默認單位:vp。
y number 路徑結束時的 y 座標值。默認單位:vp。

示例代碼

this.context.beginPath();
this.context.moveTo(20, 20);
this.context.quadraticCurveTo(100, 100, 200, 20);
this.context.stroke();

效果

image-20250105091240519

輔助理解

img


image-20250105091007706

bezierCurveTo

bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void

創建三次貝賽爾曲線的路徑。

參數名 類型 必填 説明
cp1x number 第一個貝塞爾參數的 x 座標值。默認單位:vp。
cp1y number 第一個貝塞爾參數的 y 座標值。默認單位:vp。
cp2x number 第二個貝塞爾參數的 x 座標值。默認單位:vp。
cp2y number 第二個貝塞爾參數的 y 座標值。默認單位:vp。
x number 路徑結束時的 x 座標值。默認單位:vp。
y number 路徑結束時的 y 座標值。默認單位:vp。

示例代碼

  this.context.beginPath()
  this.context.moveTo(10, 10)
  this.context.bezierCurveTo(20, 100, 200, 100, 200, 20)
  this.context.stroke()

效果

image-20250105091324817

輔助理解

img

image-20250105091128806

ImageData

ImageData對象可以存儲 canvas 渲染的像素數據。也就是説 ImageData 可以讓我們使用 canvas 對畫布中的每一個像素進行操作。提

供了強大的控制能力。

實例屬性

  • ImageData.data 只讀

    Uint8ClampedArray 描述了一個一維數組,包含以 RGBA 順序的數據,數據使用 0255(包含)的整數表示。

  • ImageData.height 只讀

    無符號長整型(unsigned long),使用像素描述 ImageData 的實際高度。

  • ImageData.width 只讀

    無符號長整型(unsigned long),使用像素描述 ImageData 的實際寬度。

這裏通過 canvas 的[getImageData]()方法快速獲取 ImageData 數據。然後通過putImageData把處理好的內容重新描繪到畫圖上。

@Entry
@Component
struct Index {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  private img: ImageBitmap = new ImageBitmap("/images/2.png")

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#ffff00')
        .onReady(() => {
          this.context.drawImage(this.img, 0, 0, 130, 130)
          // 獲取了 ImageData 示例
          let imagedata = this.context.getImageData(50, 50, 130, 130)
          // 又重新描繪到canvas上
          this.context.putImageData(imagedata, 150, 150)
        })
    }
    .width('100%')
    .height('100%')
  }
}

效果

image-20250105092307492

ImageData 反色

this.context.drawImage(this.img, 0, 0, 130, 130);
// 獲取了 ImageData 示例
let imagedata = this.context.getImageData(50, 50, 130, 130);
// console.log("xxx,", JSON.stringify(imagedata.data))
Object.keys(imagedata.data).forEach((k) => {
  // 反色
  imagedata.data[k] = 255 - imagedata.data[k];
});
// 又重新描繪到canvas上
this.context.putImageData(imagedata, 150, 150);

image-20250105092847039

ImageData 其他效果

反轉效果:

  • 原理:通過將每個像素的 RGB 值取反來實現反轉效果。
  • 實現方式:使用getImageData獲取圖像數據,然後遍歷每個像素,將每個像素的 RGB 值取反,再使用putImageData將修改後的數據繪製回 Canvas。

黑白效果:

  • 原理:將每個像素的 RGB 值轉換為灰度值,使圖像變為黑白。
  • 實現方式:使用getImageData獲取圖像數據,然後遍歷每個像素,將每個像素的 RGB 值轉換為灰度值(R、G、B 三個分量取平均值),再使用putImageData將修改後的數據繪製回 Canvas。

亮度效果:

  • 原理:調整每個像素的亮度值,使圖像變亮或變暗。
  • 實現方式:使用getImageData獲取圖像數據,然後遍歷每個像素,調整每個像素的亮度值,再使用putImageData將修改後的數據繪製回 Canvas。

復古效果:

  • 原理:通過調整每個像素的色調、飽和度和亮度,使圖像呈現復古效果。
  • 實現方式:使用getImageData獲取圖像數據,然後遍歷每個像素,調整每個像素的色調、飽和度和亮度,再使用putImageData將修改後的數據繪製回 Canvas。

紅色、綠色、藍色效果:

  • 原理:增加或減少每個像素的紅色、綠色、藍色分量的值,使圖像呈現相應顏色的效果。
  • 實現方式:使用getImageData獲取圖像數據,然後遍歷每個像素,增加或減少每個像素的紅色、綠色、藍色分量的值,再使用putImageData將修改後的數據繪製回 Canvas。

透明效果:

  • 原理:調整每個像素的透明度值,使圖像呈現透明效果。
  • 實現方式:使用getImageData獲取圖像數據,然後遍歷每個像素,調整每個像素的透明度值,再使用putImageData將修改後的數據繪製回 Canvas。

馬賽克效果:

  • 原理:將圖像分割為小塊,每個小塊的像素值設置為該小塊內像素的平均值,從而實現馬賽克效果。
  • 實現方式:使用getImageData獲取圖像數據,然後將圖像分割為小塊,計算每個小塊內像素的平均值,再將該小塊內所有像素的值設置為該平均值,最後使用putImageData將修改後的數據繪製回 Canvas。

馬賽克效果

  • 由於實際操作過程中,上述馬賽克效果處理性能比較底下,這裏用來一個取巧的效果來實現。就是先用 canvas 將畫面畫小,然後再將畫面縮放來實現一個模糊效果,間接實現馬賽克效果

漸變濾鏡效果:

  • 原理:通過在圖像上應用漸變效果,使圖像呈現漸變色的效果。
  • 實現方式:使用createLinearGradientcreateRadialGradient創建漸變對象,然後使用漸變對象作為填充樣式,繪製圖像到 Canvas 上。

參考鏈接

  1. 數學曲線之一:貝塞爾曲線
  2. 神奇 canvas 帶你實現魔法攝像頭
  3. ImageData
user avatar zourongle 頭像 k21vin 頭像 gxx01 頭像 xiaoyuindebuilder 頭像 waylau521 頭像 aixiaodekaomianbao_ddkwvd 頭像 jiuliangxiaodeshuanggang 頭像
點贊 7 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.