鴻蒙元服務實戰-笑笑五子棋(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 軸重複翻轉繪製圖像。 |
提前準備好圖片
基本使用
- 基於圖片創建填充模版
- 設置到 canvas 的 fillStyle 中
- 進行描繪
@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%')
}
}
效果:
repetition:repeat
設置平鋪
let pattern = this.context.createPattern(this.img, "repeat");
效果
clamp
在原始邊界外繪製時,超出部分使用邊緣的顏色繪製;
let pattern = this.context.createPattern(this.img, "clamp");
mirror
沿 x 軸和 y 軸重複翻轉繪製圖像。
let pattern = this.context.createPattern(this.img, "mirror");
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();
效果
輔助理解
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()
效果
輔助理解
ImageData
ImageData對象可以存儲 canvas 渲染的像素數據。也就是説 ImageData 可以讓我們使用 canvas 對畫布中的每一個像素進行操作。提
供了強大的控制能力。
實例屬性
-
ImageData.data只讀Uint8ClampedArray描述了一個一維數組,包含以 RGBA 順序的數據,數據使用0至255(包含)的整數表示。 -
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%')
}
}
效果
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);
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 將畫面畫小,然後再將畫面縮放來實現一個模糊效果,間接實現馬賽克效果
漸變濾鏡效果:
- 原理:通過在圖像上應用漸變效果,使圖像呈現漸變色的效果。
- 實現方式:使用
createLinearGradient或createRadialGradient創建漸變對象,然後使用漸變對象作為填充樣式,繪製圖像到 Canvas 上。
參考鏈接
- 數學曲線之一:貝塞爾曲線
- 神奇 canvas 帶你實現魔法攝像頭
- ImageData