多种图片操作实现方法鸿蒙示例代码

鸿蒙场景化示例代码技术工程师
发布于 2025-3-20 17:01
浏览
0收藏

本文原创发布在华为开发者社区

介绍

本实例主要展示了图片应用场景相关demo。主要包括了图片预览、图片编辑美化、场景变化前后对比、图片切割九宫格、两张图片拼接、AI抠图、图片加水印等场景示例。

多种图片操作实现方法源码链接

图片预览

使用说明

点击图片,进入图片预览界面。可对图片进行缩放、拖拽等操作。

效果预览

多种图片操作实现方法鸿蒙示例代码-鸿蒙开发者社区

实现思路

1、给图片组件的scale、width、height、offset等属性绑定相关响应式变量

Image(item)
  .width(`calc(100% * ${this.activeImage.scale})`)
  .height(`calc(100% * ${this.activeImage.scale})`)
  .objectFit(ImageFit.Contain)
  .draggable(false)
  .scale(this.active === i ? { x: this.activeImage.scale, y: this.activeImage.scale } : null)
  .offset(this.active === i ? { x: this.activeImage.offsetX, y: this.activeImage.offsetY } : null)
  .onComplete(e => {
    if (e?.loadingStatus) {
      // 记录每张图片的大小
      this.imageListSize[i] = {
        width: px2vp(Number(e.contentWidth)),
        height: px2vp(Number(e.contentHeight))
      }
      // 记录当前选中图片的大小,方便后面手势操作计算
      if (this.active === i) {
        this.activeImage.width = this.imageListSize[i].width
        this.activeImage.height = this.imageListSize[i].height
      }
    }
  })
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

2、监听相关手势操作并执行相关操作逻辑,如:二指缩放、单指滑动、双击等

// 双指操作
PinchGesture({ fingers: 2 })
  .onActionStart((e) => {
    this.defaultScale = this.activeImage.scale
  })
  .onActionUpdate((e) => {
    let scale = e.scale * this.defaultScale
    // 计算缩放比例及相应偏移距离
    if (scale <= 4 && scale >= 1) {
      this.activeImage.offsetX = this.activeImage.offsetX / (this.activeImage.scale - 1) * (scale - 1) || 0
      this.activeImage.offsetY = this.activeImage.offsetY / (this.activeImage.scale - 1) * (scale - 1) || 0
      this.activeImage.offsetStartX = this.activeImage.offsetX
      this.activeImage.offsetStartY = this.activeImage.offsetY
      this.activeImage.scale = scale
    }
  })
// 单指滑动
PanGesture()
  .onActionStart(e => {
    // 记录起始位置
    this.activeImage.dragOffsetX = e.fingerList[0].globalX
    this.activeImage.dragOffsetY = e.fingerList[0].globalY
  })
  .onActionUpdate((e) => {
    if (this.activeImage.scale === 1) {
      return
    }
    if(!e.fingerList[0]){
      return
    }
    // 计算移动距离
    let offsetX = e.fingerList[0].globalX - this.activeImage.dragOffsetX +
    this.activeImage.offsetStartX
    let offsetY = e.fingerList[0].globalY - this.activeImage.dragOffsetY +
    this.activeImage.offsetStartY
    if (this.activeImage.width * this.activeImage.scale > this.containerWidth &&
      (this.activeImage.width * this.activeImage.scale - this.containerWidth) / 2 >=
      Math.abs(offsetX)) {
      this.activeImage.offsetX = offsetX
    }
    if (this.activeImage.height * this.activeImage.scale >
    this.containerHeight &&
      (this.activeImage.height * this.activeImage.scale - this.containerHeight) / 2 >=
      Math.abs(offsetY)) {
      this.activeImage.offsetY = offsetY
    }
    if ((this.activeImage.width * this.activeImage.scale - this.containerWidth) / 2 < Math.abs(offsetX)) {
      this.disabledSwipe = false
    }
  })
  .onActionEnd((e) => {
    // 记录当前偏移位置,作为下次操作的其实位置
    this.activeImage.offsetStartX = this.activeImage.offsetX
    this.activeImage.offsetStartY = this.activeImage.offsetY
  })
  .onActionCancel(() => {
    // 记录当前偏移位置,作为下次操作的其实位置
    this.activeImage.offsetStartX = this.activeImage.offsetX
    this.activeImage.offsetStartY = this.activeImage.offsetY
  }),
//双击手势
TapGesture({ count: 2 })
  .onAction(() => {
    // 缩小
    if (this.activeImage.scale > 1) {
      this.activeImage.scale = 1
      this.activeImage.offsetX = 0
      this.activeImage.offsetY = 0
      this.activeImage.offsetStartX = 0
      this.activeImage.offsetStartY = 0
      this.disabledSwipe = false
    } else {
      // 放大
      this.activeImage.scale = 2
      this.disabledSwipe = true
    }
  }),
//单击手势
TapGesture({ count: 1 })
  .onAction(() => {
    this.closePreviewFn()
  }),
)
)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.

图片编辑美化

使用说明

可对图片编辑,包含裁剪、旋转、色域调节(本章只介绍亮度、透明度、饱和度)、滤镜等功能。

效果预览

多种图片操作实现方法鸿蒙示例代码-鸿蒙开发者社区

实现思路

1、通过pixelMap的crop方法来裁剪图片

export async function cropImage(pixelMap: image.PixelMap, x = 0, y = 0, width = 300, height = 300) {
  // x:裁剪起始点横坐标
  // y:裁剪起始点纵坐标
  // height:裁剪高度,方向为从上往下
  // width:裁剪宽度,方向为从左到右
  await pixelMap.crop({ x, y, size: { height, width } })
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

2、通过pixelMap的rotate方法来旋转图片

export async function rotateImage(pixelMap: PixelMap, rotateAngle = 90) {
  await pixelMap.rotate(rotateAngle);
}
  • 1.
  • 2.
  • 3.

3、通过对每个像素点的rgb值转换来改变亮度、透明度

export function execColorInfo(bufferArray: ArrayBuffer, last: number, cur: number, hsvIndex: number) {
  if (!bufferArray) {
    return;
  }
  const newBufferArr = bufferArray;
  let colorInfo = new Uint8Array(newBufferArr);
  for (let i = 0; i < colorInfo?.length; i += CommonConstants.PIXEL_STEP) {
    // rgb转换成hsv
    const hsv = rgb2hsv(colorInfo[i + RGBIndex.RED], colorInfo[i + RGBIndex.GREEN], colorInfo[i + RGBIndex.BLUE]);
    let rate = cur / last;
    hsv[hsvIndex] *= rate;
    // hsv转换成rgb
    const rgb = hsv2rgb(hsv[HSVIndex.HUE], hsv[HSVIndex.SATURATION], hsv[HSVIndex.VALUE]);
    colorInfo[i + RGBIndex.RED] = rgb[RGBIndex.RED];
    colorInfo[i + RGBIndex.GREEN] = rgb[RGBIndex.GREEN];
    colorInfo[i + RGBIndex.BLUE] = rgb[RGBIndex.BLUE];
  }
  return newBufferArr;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

4、通过effectKit来添加滤镜

export async function pinkColorFilter(pixelMap: PixelMap) {
  const pinkColorMatrix: Array<number> = [
    1, 1, 0, 0, 0,
    0, 1, 0, 0, 0,
    0, 0, 1, 0, 0,
    0, 0, 0, 1, 0
  ]
  const pixelMapFiltered = await effectKit.createEffect(pixelMap).setColorMatrix(pinkColorMatrix).getEffectPixelMap();
  return pixelMapFiltered;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

场景变化前后对比

使用说明

通过拖拽移动按钮,来展示两张图片的不同

效果预览

多种图片操作实现方法鸿蒙示例代码-鸿蒙开发者社区

实现思路

1.创建三个Stack组件,用来展示装修前后对比图,第一个和第三个Stack分别存放装修前的图片和装修后的图片,zIndex设置为1。第二个Stack存放按钮的图片,zIndex设置为2,这样按钮的图片就会覆盖在两张装修图片之上。

Row() {
    /**
     * 创建两个Stack组件,用来展示装修前后对比图,分别存放装修前的图片和装修后的图片,zIndex设置为1。
     * 中间Column存放按钮的图片,zIndex设置为2,这样按钮的图片就会覆盖在两张装修图片之上。
     */
    Stack() {
     ...
    }
    .zIndex(CONFIGURATION.Z_INDEX1) 
    .width(this.leftImageWidth)
    .clip(true)
    .alignContent(Alignment.TopStart)
    
    Column() {
      Image($r("app.media.drag_to_switch_pictures_drag_button"))
        .width(30)
        .height(160)
        .draggable(false)
        ...
    }
    .width(2)
    .zIndex(CONFIGURATION.Z_INDEX2) 
    
    Stack() {
      ...
    }
    .zIndex(CONFIGURATION.Z_INDEX1) 
    .clip(true)
    .width(this.rightImageWidth)
    .alignContent(Alignment.TopEnd)
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.

2.将Image组件放在Row容器里,将Row容器的宽度设置为状态变量,再利用clip属性对于Row容器进行裁剪。

Row() {
    Image($r("app.media.drag_to_switch_pictures_before_decoration"))
      .width(320)
      .height(160)
      .draggable(false)
  }
  .width(this.leftImageWidth) 
  .zIndex(CONFIGURATION.Z_INDEX1) 
  .clip(true)
  .borderRadius({
    topLeft: 10,
    bottomLeft: 10
  })
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

3.右边的Image组件与左边同样的操作,但是新增了一个direction属性,使元素从右至左进行布局,为的是让Row从左侧开始裁剪。

Row() {
    Image($r("app.media.drag_to_switch_pictures_after_decoration"))
      .width(320)
      .height(160)
      .draggable(false)
    }
    .width(this.rightImageWidth)
    .clip(true)
    .zIndex(CONFIGURATION.Z_INDEX1)
    .direction(Direction.Rtl)
    .borderRadius({
    topRight: 10,
    bottomRight: 10
    })
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

4.中间的Image组件通过手势事件中的滑动手势对Image组件滑动进行监听,对左右Image组件的宽度进行计算从而重新布局渲染。

Image($r("app.media.drag_to_switch_pictures_drag_button"))
    .width(30)
    .height(160)
    .draggable(false)
    .gesture(
      PanGesture({ fingers: CONFIGURATION.PAN_GESTURE_FINGERS, distance: CONFIGURATION.PAN_GESTURE_DISTANCE })
        .onActionStart(() => {
          this.dragRefOffset = CONFIGURATION.INIT_VALUE; 
        })
        .onActionUpdate((event: GestureEvent) => {
          // 通过监听GestureEvent事件,实时监听图标拖动距离
          this.dragRefOffset = event.offsetX;
          this.leftImageWidth = this.imageWidth + this.dragRefOffset;
          this.rightImageWidth = CONFIGURATION.IMAGE_FULL_SIZE - this.leftImageWidth;
          if (this.leftImageWidth >=
          CONFIGURATION.LEFT_IMAGE_RIGHT_LIMIT_SIZE) { // 当leftImageWidth大于等于310vp时,设置左右Image为固定值,实现停止滑动效果。
            this.leftImageWidth = CONFIGURATION.LEFT_IMAGE_RIGHT_LIMIT_SIZE;
            this.rightImageWidth = CONFIGURATION.RIGHT_IMAGE_RIGHT_LIMIT_SIZE;
          } else if (this.leftImageWidth <=
          CONFIGURATION.LEFT_IMAGE_LEFT_LIMIT_SIZE) { // 当leftImageWidth小于等于30vp时,设置左右Image为固定值,实现停止滑动效果。
            this.leftImageWidth = CONFIGURATION.LEFT_IMAGE_LEFT_LIMIT_SIZE;
            this.rightImageWidth = CONFIGURATION.RIGHT_IMAGE_LEFT_LIMIT_SIZE;
          }
        })
        .onActionEnd(() => {
          if (this.leftImageWidth <= CONFIGURATION.LEFT_IMAGE_LEFT_LIMIT_SIZE) {
            this.leftImageWidth = CONFIGURATION.LEFT_IMAGE_LEFT_LIMIT_SIZE;
            this.rightImageWidth = CONFIGURATION.RIGHT_IMAGE_LEFT_LIMIT_SIZE;
            this.imageWidth = CONFIGURATION.LEFT_IMAGE_LEFT_LIMIT_SIZE;
          } else if (this.leftImageWidth >= CONFIGURATION.LEFT_IMAGE_RIGHT_LIMIT_SIZE) {
            this.leftImageWidth = CONFIGURATION.LEFT_IMAGE_RIGHT_LIMIT_SIZE;
            this.rightImageWidth = CONFIGURATION.RIGHT_IMAGE_RIGHT_LIMIT_SIZE;
            this.imageWidth = CONFIGURATION.LEFT_IMAGE_RIGHT_LIMIT_SIZE;
          } else {
            this.leftImageWidth = this.imageWidth + this.dragRefOffset; // 滑动结束时leftImageWidth等于左边原有Width+拖动距离。
            this.rightImageWidth =
              CONFIGURATION.IMAGE_FULL_SIZE - this.leftImageWidth; // 滑动结束时rightImageWidth等于340-leftImageWidth。
            this.imageWidth = this.leftImageWidth; // 滑动结束时ImageWidth等于leftImageWidth。
          }
        })
    )
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.

图片切割九宫格

使用说明

通过图库选择一张图片,将其切割成九宫格展示,然后可保存到图库中

效果预览

多种图片操作实现方法鸿蒙示例代码-鸿蒙开发者社区

实现思路

根据图片宽高信息以及要分割的行数列数,计算出每张图片的左上角起始位置的坐标及宽高,根据这些信息获取对应的pixelMap

export async function splitImage(l = 3, c = 3): Promise<SplitImageModel> {
  // 选择图片
  let uris = await selectImages(1)
  let originUri = ''
  // 存储切割图片
  let imagePixels: image.PixelMap[] = []
  if (uris && uris.length) {
    originUri = uris[0]
    // 创建图像编码ImagePacker对象
    let imagePickerApi = image.createImagePacker();
    // 以只读方式打开指定下标图片
    let file: fileIo.File = await fileIo.open(uris[0], fileIo.OpenMode.READ_ONLY)
    let fd: number = file.fd;
    // 获取图片源
    let imageSource = image.createImageSource(fd);
    // 图片信息
    let imageInfo = await imageSource.getImageInfo();
    // 图片高度除以3,就是把图片切为3份
    let height = imageInfo.size.height / l;
    let width = imageInfo.size.width / c;
    // 切换为 3x3 张图片
    for (let i = 0; i < l; i++) {
      for (let j = 0; j < c; j++) {
        // 设置解码参数DecodingOptions,解码获取pixelMap图片对象
        let decodingOptions: image.DecodingOptions = {
          desiredRegion: {
            size: {
              height: height, // 切开图片高度
              width: width  // 切开图片宽度
            },
            x: j * width, // 切开x起始位置
            y: i * height     // 切开y起始位置
          }
        }
        // 根据参数重新九宫格图片
        let img: image.PixelMap = await imageSource.createPixelMap(decodingOptions);
        // 把生成新图片放到内存里
        imagePixels.push(img);
      }
    }
    imagePickerApi.release();
    fileIo.closeSync(fd);
  }
  return { originUri, splitImages: imagePixels }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.

两张图片拼接

使用说明

通过图库选择一张图片,可横向拼接成一张图,也可竖向拼接成一张图。然后保存到图库

实现效果

多种图片操作实现方法鸿蒙示例代码-鸿蒙开发者社区

实现思路

获取要拼接图片的信息,计算出拼接后图片的大小等信息,根据这些信息创建出一个pixelMap。然后将要拼接的图片的pixelMap写入创建的空的pixelMap即可

export async function joinImages(images: Array<string>, isH = true) {
  try {
    if (images.length < 2) {
      return;
    }
    获取图片信息
    ...
    
    根据要拼接图片创建拼接后的pixelMap
    const combineColor = new ArrayBuffer(combineOpts.size.width * combineOpts.size.height * 4);
    const newPixelMap = await image.createPixelMap(combineColor, combineOpts);
    for (let x = 0; x < images.length; x++) {
      const singleOpts = x === 0 ? singleOpts1 : singleOpts2
      let singleColor = new ArrayBuffer(singleOpts.desiredSize!.width * singleOpts.desiredSize!.height * 4);
      let imageSource = x === 0 ? imageSource1 : imageSource2
      let singleWidth = x === 0 ? singleWidth1 : singleWidth2
      let singleHeight = x === 0 ? singleHeight1 : singleHeight2
      //读取小图
      const singlePixelMap = await imageSource.createPixelMap(singleOpts);
      await singlePixelMap.readPixelsToBuffer(singleColor);
      //写入大图
      let area: image.PositionArea = {
        pixels: singleColor,
        offset: 0,
        stride: singleWidth * 4,
        region: {
          size: { height: singleHeight, width: singleWidth },
          x: isH ? x === 0 ? 0 : singleWidth1 : 0,
          y: isH ? 0 : x === 0 ? 0 : singleHeight1
        }
      }
      await newPixelMap.writePixels(area);
    }
    return newPixelMap;
  } catch (err) {
    hilog.error(0x0000, 'JOIN_IMAGES', 'PictureJoinTogether join error: ' + JSON.stringify(err))
  }
  return
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.

AI抠图

使用说明

长按需要被抠图的元素并拖拽

效果预览

多种图片操作实现方法鸿蒙示例代码-鸿蒙开发者社区

实现思路

将Image接口的enableAnalyzer属性设为true

Image(this.imagePixelMap)
  .enableAnalyzer(true)
  .width('100%')
  • 1.
  • 2.
  • 3.

图片加水印

使用说明

从图库中选取图片,点击添加水印按钮。即可添加上水印

效果预览

多种图片操作实现方法鸿蒙示例代码-鸿蒙开发者社区

实现思路

1.根据canvas容器实际大小以及图片的实际大小,将选择的图片绘制到canvas中

// 记录图片实际大小
let imageSource: image.ImageSource = image.createImageSource(imageInfo);
imageSource.getImageInfo((err, value) => {
  if (err) {
    return;
  }
  this.hValue = Math.round(value.size.height * 1);
  this.wValue = Math.round(value.size.width * 1);
  let defaultSize: image.Size = {
    height: this.hValue,
    width: this.wValue
  };

  let opts: image.DecodingOptions = {
    editable: true,
    desiredSize: defaultSize
  };
  imageSource.createPixelMap(opts, (err, pixelMap) => {
    if (err) {
      return
    }
    // 将图片绘制canvas上
    let rect = this.getComponentRect("imageContainer") as Record<string, number>
    this.imageScale = (rect.right - rect.left) / this.wValue
    this.imageHeight = this.hValue * this.imageScale
    this.context.transform(this.imageScale, 0, 0, this.imageScale, 0, 0)
    this.pixelMap = pixelMap
    this.context.drawImage(this.pixelMap, 0, 0)

  })
})
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.

2.在画布上绘制水印内容

this.context.beginPath()
this.context.font = `宋体 ${100 / this.imageScale}px}`
this.context.textBaseline = "top"
this.context.fillStyle = "#80b2bec3"
this.context.rotate(Math.PI / 180 * 30)
this.context.fillText("水印水印水印水印", 100 / this.imageScale, 100 / this.imageScale)
this.context.rotate(-Math.PI / 180 * 30)
this.context.closePath()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

3.根据图片实际大小将加水印的canvas重新绘制一遍,然后将绘制后的pixelMap保存到土库中

let imageInfo = await this.pixelMap.getImageInfo()
let offCanvas = new OffscreenCanvas(px2vp(imageInfo.size.width), px2vp(imageInfo.size.height))
let offContext = offCanvas.getContext("2d")
let contextPixelMap = this.context.getPixelMap(0, 0, this.context.width, this.context.height)
offContext.drawImage(contextPixelMap, 0, 0, offCanvas.width, offCanvas.height)
savePixelMapToGalleryBySaveButton(this,
  offContext.getPixelMap(0, 0, offCanvas.width, offCanvas.height));
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

分类
收藏
回复
举报
回复
    相关推荐