HarmonyOS 鸿蒙Next中使用图片当水印

HarmonyOS 鸿蒙Next中使用图片当水印 如何把文本水印换成图片效果跟下面图片一样,求大佬指点


更多关于HarmonyOS 鸿蒙Next中使用图片当水印的实战教程也可以访问 https://www.itying.com/category-93-b0.html

14 回复

【背景知识】

应用背景水印是综合办公类应用中的高频使用场景之一,当用户查看的内容涉及内部敏感信息时,应用在背景自动生成水印,保证信息安全性。 应用背景水印示例基于Canvas绘制水印图案,并通过设置浮层叠加在背景上,实现背景水印功能。

【解决方案】

  1. 在Canvas组件上绘制水印图案。

    @Builder
    waterMark() {
      Canvas(this.context)
        .onReady(() => {
          ... // 设置水印绘制参数
          while (posY < this.context.height) {
            ... // 设置每行位置参数
            posY = WATERMARK_HEIGHT * row;
            for (let i = 0; i <= Math.ceil(this.context.width / WATERMARK_WIDTH); i++) {
            ... // 绘制该行水印
            }
            row++;
          }
        });
    }
    
  2. 设置浮层属性,将绘制好的水印图案叠加到背景组件上。

    Column()
    .width('100%')
    .layoutWeight(1)
    .overlay(this.waterMark());
    

更多关于HarmonyOS 鸿蒙Next中使用图片当水印的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


1.关于鸿蒙水印的添加楼主可以参考下面的实现: Canvas提供画布组件,用于自定义绘制图形。使用CanvasRenderingContext2D对象在Canvas组件上进行绘制,其中fillText()方法用于绘制文本,drawImage()方法用于图像绘制。

开发流程

  1. 创建Canvas画布,在画布上绘制水印。
  2. 使用Stack组件或浮层overlay属性,将画布与UI页面组件融合显示。

2.具体实现参考代码:楼主可以参考这个仓库 https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-add-watermark#section20851175145112

3.部分实现代码:

@Prop watermarkWidth: number = 120;
@Prop watermarkHeight: number = 120;
@Prop watermarkText: string = this.getWatermarkText();
@Prop rotationAngle: number = -30;
@Prop fillColor: string | number | CanvasGradient | CanvasPattern = '#10000000';
@Prop font: string = '16vp';

draw() {
  this.context.fillStyle = this.fillColor;
  this.context.font = this.font;
  const colCount = Math.ceil(this.context.width / this.watermarkWidth);
  const rowCount = Math.ceil(this.context.height / this.watermarkHeight);
  for (let col = 0; col <= colCount; col++) {
    let row = 0;
    for (; row <= rowCount; row++) {
      const angle = this.rotationAngle * Math.PI / 180;
      this.context.rotate(angle);
      const positionX = this.rotationAngle > 0 ? this.watermarkHeight * Math.tan(angle) : 0;
      const positionY = this.rotationAngle > 0 ? 0 : this.watermarkWidth * Math.tan(-angle);
      this.context.fillText(this.watermarkText, positionX, positionY);
      this.context.rotate(-angle);
      this.context.translate(0, this.watermarkHeight);
    }
    this.context.translate(0, -this.watermarkHeight * row);
    this.context.translate(this.watermarkWidth, 0);
  }
}

使用水印方式Canvas绘画试试

看看这个是否是您需要的

https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-add-watermark#section12388834480

@Component
export struct Watermark {
  private settings: RenderingContextSettings = new RenderingContextSettings(true);
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
  // ...
  build() {
    Canvas(this.context)
      .width('100%')
      .height('100%')
      .hitTestBehavior(HitTestMode.Transparent)
      .onReady(() => this.draw())
  }
}
@Builder
watermarkBuilder() {
  Column() {
    Watermark()
  }
  .hitTestBehavior(HitTestMode.Transparent)
}

build() {
  // ...
    Column() {
      Image($r('app.media.empty'))
        .width(110)
        .height(88)
        // ...
    }
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
    .layoutWeight(1)
    .overlay(this.watermarkBuilder())
    // ...
}

试试通过离屏画布绘制技术实现。通过OffscreenCanvas创建离屏画布,利用drawImage()方法将水印图片叠加到原始图片上。加载原始图片与水印图片→创建画布→绘制叠加→保存新图片。

参考步骤

1/加载图片为PixelMap:将原始图片及水印图片转换为PixelMap对象

// 通过相册选择或资源加载获取图片

let imageSource = image.createImageSource(uri);

let originalPixelMap = await imageSource.createPixelMap();

let watermarkImageSource = image.createImageSource(watermarkUri);

let watermarkPixelMap = await watermarkImageSource.createPixelMap();

2/创建离屏画布并绘制

// 创建与原始图片同尺寸的离屏画布

let offCanvas = new OffscreenCanvasRenderingContext2D(

  originalPixelMap.width, 

  originalPixelMap.height

);

// 绘制原始图片

offCanvas.drawImage(originalPixelMap, 0, 0);

// 绘制水印图片

let watermarkX = originalPixelMap.width - watermarkPixelMap.width - 20; // 右边距20

let watermarkY = originalPixelMap.height - watermarkPixelMap.height - 20; // 下边距20

offCanvas.globalAlpha = 0.5; // 设置透明度

offCanvas.drawImage(watermarkPixelMap, watermarkX, watermarkY);

// 获取合成后的PixelMap

let resultPixelMap = offCanvas.getPixelMap();

3/保存处理后的图片

// 使用ImagePacker保存为文件

let imagePacker = image.createImagePacker();

let imageBuffer = await imagePacker.packToData(resultPixelMap, {

  format: 'image/jpeg',

  quality: 90

});

// 写入文件(需申请媒体库权限)

let filePath = ...; // 目标路径

await fileIo.write(filePath, imageBuffer);

要实现您描述的效果,通常需要利用底层图形绘制能力。鸿蒙文档中提到的 CanvasOffscreenCanvas 相关API是更合适的基础:

  1. 使用 Canvas / OffscreenCanvasRenderingContext2D:

    • 您可以先使用 Image 相关API(如 ImageDecoder)将图片解码为 PixelMap
    • 创建一个 CanvasOffscreenCanvas,其大小与图片一致。
    • PixelMap 绘制到 Canvas 上作为背景。
    • 使用 Canvasrotate() 方法旋转绘图上下文,然后使用 fillText()strokeText() 方法多次绘制文本,通过调整旋转角度和绘制位置来实现“很多条斜着”的水印效果。
    • 最后,使用 Canvas 的相关方法(如 toPixelMap)将合成后的图像获取出来。
  2. 关键API参考(来自鸿蒙文档):

    • CanvasRenderingContext2D.rotate(angle): 用于旋转当前的绘图上下文。
    • CanvasRenderingContext2D.fillText(text, x, y): 用于在画布上绘制填充文本。
    • CanvasRenderingContext2D.strokeText(text, x, y): 用于在画布上绘制文本边框(描边)。
    • OffscreenCanvasRenderingContext2D: 离屏画布的上下文,提供与 CanvasRenderingContext2D 相同的API,可在Worker线程中处理图像,避免阻塞UI。

我的想法是使用本地图片来当作水印,来实现这样一个效果,

你这个安装不了,没在https://ohpm.openharmony.cn注册,

?什么意思,

有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html

这个没用我要的效果是应用到全局要配合Navigation使用,

在HarmonyOS Next中,可通过Image组件结合绝对定位实现图片水印。使用WaterSpan或自定义布局,设置透明度与重复平铺。推荐使用PixelMap处理图像数据,避免直接操作位图。水印叠加需注意图层顺序与混合模式,确保不影响主内容显示。

在HarmonyOS Next中,可以通过Canvas绘制实现图片水印效果。以下是核心步骤:

  1. 使用Image组件加载水印图片,并通过CanvasRenderingContext2DdrawImage方法绘制到画布上
  2. 调整水印的透明度、旋转角度和位置,参考代码:
// 创建Canvas上下文
const ctx = canvas.getContext('2d')
// 加载水印图片
const img = new Image()
img.src = 'watermark.png'
img.onload = () => {
  // 设置透明度
  ctx.globalAlpha = 0.3
  // 旋转角度(可选)
  ctx.rotate(-20 * Math.PI/180)
  // 绘制水印
  ctx.drawImage(img, x, y, width, height)
}
  1. 如需全屏水印效果,可通过循环计算位置实现平铺

注意控制水印图片的尺寸和透明度,避免遮挡主体内容。

回到顶部