HarmonyOS 鸿蒙Next中可可图片编辑图片裁剪-canvas

HarmonyOS 鸿蒙Next中可可图片编辑图片裁剪-canvas

可可图片编辑 HarmonyOS(4)图片裁剪-canvas

前言

可可图片编辑 实现了图片的裁剪功能,效果如图所示。这里的核心技术是使用了canvas。

Canvas 入门

Canvas提供画布组件,用于自定义绘制图形,开发者使用CanvasRenderingContext2D对象和OffscreenCanvasRenderingContext2D对象在Canvas组件上进行绘制,绘制对象可以是基础形状、文本、图片等,canvas也可以实现对图片到裁剪,并且还可以把canvas上描绘的图形下载保存成图片。本章节主要讲解下canvas的基本使用。

基本使用

canvas 的基本使用分为 4 步:

  1. 设置是否抗锯齿抗锯齿(Anti - aliasing)是一种在数字图形处理中使用的技术,主要用于减少图像中因为像素有限而产生的锯齿状边缘的现象
  2. 创建画布上下文
  3. 渲染画布组件
  4. 在画布上描绘图案
@Entry
@Component
struct Index {
  // 1 用来配置CanvasRenderingContext2D对象的参数,包括是否开启抗锯齿,true表明开启抗锯齿。
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  // 2 用来创建CanvasRenderingContext2D对象,通过在canvas中调用CanvasRenderingContext2D对象来绘制。
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
      // 3 在canvas中调用CanvasRenderingContext2D对象。
    Column(){
      Canvas(this.context)
        .width('100%')
        .height('100%')
        .backgroundColor('#F5DC62')
        .onReady(() => {
          // 4 可以在这里绘制内容。
          this.context.strokeRect(50, 50, 200, 150);
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}
  1. 效果

canvas 常见用法

canvas 的核心思想是将想要的图形如,直线、圆圈、矩形等图形描绘到画布上。如果想要呈现出比较酷炫的效果,做法是:

  1. 描绘图形
  2. 擦除画布
  3. 计算数值-重新描绘图形
  4. 擦除画布
  5. 。。。

通过以上过程实现动画效果

canvas 的坐标系

在 canvas 中画图形都是基于坐标系来进行的。 左上角为起点。

描绘图形

canvas 中内置的常见的描绘图形的方法有以下:

  1. 直线
  2. 矩形
  3. 弧形
  4. 文本
  5. 图像

直线

描绘直线可以使用:

  1. 定起点 moveTo
  2. 定终点 lineTo
  3. 开始描绘 stroke
this.context.moveTo(10, 10);
this.context.lineTo(100, 100);
this.context.stroke();

矩形

可以使用直线lineTo自己画成一个矩形。也可以直接使用 strokeRect直接生成矩形

lineTo 画矩形

this.context.moveTo(10, 10);
this.context.lineTo(300, 10);
this.context.lineTo(300, 300);
this.context.lineTo(10, 300);
//   自动闭环
this.context.closePath();
//   开始描述 将路径的当前点移回到路径的起点,当前点到起点间画一条直线
this.context.stroke();

strokeRect 画矩形

// this.context.strokeRect(x, y, 宽度, 高度);
this.context.strokeRect(50, 50, 200, 150);

弧形

弧形可以使用 arcarcTo 来描绘

arc

arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean)

参数名 类型 必填 说明
x number 弧线圆心的 x 坐标值。默认单位:vp。
y number 弧线圆心的 y 坐标值。默认单位:vp。
radius number 弧线的圆半径。默认单位:vp。
startAngle number 弧线的起始弧度。单位:弧度
endAngle number 弧线的终止弧度。单位:弧度
counterclockwise boolean 是否逆时针绘制圆弧。true:逆时针方向绘制椭圆。false:顺时针方向绘制椭圆。默认值:false。

这里需要注意的是 arc 使用的单位是弧度不是角度

一圈 = 360角度 =  2 * Math.PI
半圈 = 180角度 =  Math.PI ≈ 3.14

观察以下效果

100,75 是圆心坐标

50 是半径

0 是开始的弧度

6.28 ≈ 2 * Math.PI = 一圈


arc 是从正右方向开始旋转的。

this.context.beginPath();
this.context.arc(100, 75, 50, 0, 3.14 / 2);
this.context.stroke();

arcTo

arcTo(x1: number, y1: number, x2: number, y2: number, radius: number)

参数名 类型 必填 说明
x1 number 第一个控制点的 x 坐标值。默认单位:vp。
y1 number 第一个控制点的 y 坐标值。默认单位:vp。
x2 number 第二个控制点的 x 坐标值。默认单位:vp。
y2 number 第二个控制点的 y 坐标值。默认单位:vp。
radius number 圆弧的圆半径值。默认单位:vp。

this.context.beginPath();
this.context.strokeStyle = "#000000";
this.context.lineWidth = 3;
this.context.moveTo(360, 20);
this.context.arcTo(360, 170, 110, 170, 150);
this.context.stroke();

辅助理解

想象一下,我们有一个起点(即当前路径的最后一个点),然后有三个更多的点:两个控制点 (x1, y1) 和 (x2, y2),以及由 radius

定义的一个圆心。arcTo 会创建一条从起点到第二个控制点 (x2, y2) 的圆弧,这条圆弧是位于以 radius 为半径的圆周上的一部

分。该圆弧会在起点和第一个控制点 (x1, y1) 之间形成一个切线,并且也会在第二个控制点 (x2, y2) 和圆弧的终点之间形成一个切线。

文本

  1. strokeText表示描边的图形
  2. fillText 表示填充的图形,还有其他fillfillRect等也表示填充。

strokeText

  this.context.font = '55px sans-serif'
  this.context.strokeText("Hello World!", 20, 60)

fillText

this.context.font = '55px sans-serif'
this.context.fillText("Hello World!", 20, 60)

图像

drawImage可以把图像描绘到画布上,很多的在线图形合成效果都可以利用该功能实现

drawImage(image: ImageBitmap | PixelMap, dx: number, dy: number): void

drawImage(image: ImageBitmap | PixelMap, dx: number, dy: number, dw: number, dh: number): void

drawImage(image: ImageBitmap | PixelMap, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void

参数名 类型 必填 说明
image ImageBitmapPixelMap 图片资源,请参考 ImageBitmap 或 PixelMap。
sx number 裁切源图像时距离源图像左上角的 x 坐标值。image 类型为 ImageBitmap 时,默认单位:vp。image 类型为 PixelMap 时,单位:px。
sy number 裁切源图像时距离源图像左上角的 y 坐标值。image 类型为 ImageBitmap 时,默认单位:vp。image 类型为 PixelMap 时,单位:px。
sw number 裁切源图像时需要裁切的宽度。image 类型为 ImageBitmap 时,默认单位:vp。image 类型为 PixelMap 时,单位:px。
sh number 裁切源图像时需要裁切的高度。image 类型为 ImageBitmap 时,默认单位:vp。image 类型为 PixelMap 时,单位:px。
dx number 绘制区域左上角在 x 轴的位置。默认单位:vp。
dy number 绘制区域左上角在 y 轴的位置。默认单位:vp。
dw number 绘制区域的宽度。当绘制区域的宽度和裁剪图像的宽度不一致时,将图像宽度拉伸或压缩为绘制区域的宽度。默认单位:vp。
dh number 绘制区域的高度。当绘制区域的高度和裁剪图像的高度不一致时,将图像高度拉伸或压缩为绘制区域的高度。默认单位:vp。
@Entry
@Component
struct Index {
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  private img: ImageBitmap = new ImageBitmap("/images/example.jpg")

  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)
          this.context.drawImage(this.img, 0, 150, 300, 100)
          this.context.drawImage(this.img, 0, 0, 500, 500, 0, 300, 400, 200)
        })
    }
    .width('100%')
    .height('100%')
  }
}

canvas 浅尝动态效果 1

const width = px2vp(display.getDefaultDisplaySync().availableWidth) * 0.9;
const height = width;
let x = 0;
let y = 0;
setInterval(() => {
  this.context.strokeRect(x, y, 100, 100);
  x++;
  y++;
}, 20);

canvas 浅尝动态效果 2

const width = px2vp(display.getDefaultDisplaySync().availableWidth) * 0.9;
const height = width;
let x = 0;
let y = 0;
setInterval(() => {
  // 清理画布
  this.context.strokeRect(x, y, 100, 100);
  x++;
  y++;
}, 

更多关于HarmonyOS 鸿蒙Next中可可图片编辑图片裁剪-canvas的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

666 学习了

更多关于HarmonyOS 鸿蒙Next中可可图片编辑图片裁剪-canvas的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


感谢支持,

在HarmonyOS鸿蒙Next中,图片裁剪可通过Canvas组件实现。Canvas提供drawImage方法用于绘制图像,结合Rect区域设置可完成裁剪。开发者需使用Image组件加载图片后,通过CanvasContext调整源图像与目标区域的尺寸和位置参数,实现指定区域的裁剪功能。该过程基于ArkTS声明式开发,无需依赖Java或C语言。

在HarmonyOS Next中使用Canvas实现图片裁剪功能是一个高效且灵活的选择。Canvas组件提供了强大的绘图能力,通过CanvasRenderingContext2D可以精确控制图片的绘制区域,实现裁剪效果。

关键步骤包括:

  1. 创建Canvas上下文并设置抗锯齿
  2. 使用drawImage方法绘制图片,通过参数控制裁剪区域(sx, sy, sw, sh)和绘制位置(dx, dy, dw, dh)
  3. 结合用户交互(如触摸事件)动态调整裁剪区域
  4. 通过toDataURL或getPixelMap导出裁剪后的图片

需要注意的是,Canvas在HarmonyOS Next中的坐标系以左上角为原点,单位默认使用vp,但在处理PixelMap时需注意px单位的转换。对于性能优化,建议在动画场景中使用requestAnimationFrame替代setInterval。

这种方案适合需要自定义裁剪逻辑的场景,相比系统自带的图片裁剪接口提供了更大的灵活性。

回到顶部