前言:ArkTS语言中照片添加水印常见用法总结和整理,目前常见的旋转铺满全屏水印,区域水印,底部带背景色的水印,以及图文混排的水印。 这篇文章对各种用法都进行了归纳整理。
HomePage示例图片显示
Button('Single: Diagonal Watermark')
.onClick(() => this.handleWaterMarkAddition(LXWaterMarkStyle.Default))
.height(30)
Button('Single: Top-Left Watermark')
.onClick(() => this.handleWaterMarkAddition(LXWaterMarkStyle.LeftTop))
.height(30)
Button('Single: Bottom-Right Watermark')
.onClick(() => this.handleWaterMarkAddition(LXWaterMarkStyle.RightBottom))
.height(30)
Button('Multiple: Diagonal Watermark')
.onClick(() => this.handleWaterMarkAddition(LXWaterMarkStyle.MoreDefault, true))
.height(30)
各种样式水印添加方法如上所示。
核心的代码封装类:
LXWaterMarkMgr.ets
水印信息封装类:
LXWaterMarkInfo
水印信息配置类:
LXWaterMarkFillOption
水印样式配置枚举:
LXWaterMarkStyle
照片信息类:
LXImagePixelMap
水印绘制器抽象:
LXWaterMarkDrawer
好处是,所有的水印都继承于LXWaterMarkDrawer的方法实现,简单明了。
// 水印绘制器抽象
abstract class LXWaterMarkDrawer {
abstract draw(
offScreenCanvas: OffscreenCanvasRenderingContext2D,
imagePixelMap: LXImagePixelMap,
waterMarkInfoList: LXWaterMarkInfo[],
option: LXWaterMarkFillOption,
scale: number,
canvasSize?:SizeOptions
): Promise<void>;
}
// 默认水印绘制器
class DefaultWaterMarkDrawer extends LXWaterMarkDrawer {
async draw(
iOffScreenContext: OffscreenCanvasRenderingContext2D,
imagePixelMap: LXImagePixelMap,
waterMarkInfoList: LXWaterMarkInfo[],
option: LXWaterMarkFillOption,
scale: number,
canvasSize?:SizeOptions
): Promise<void> {
const waterInfo = waterMarkInfoList.length>0?waterMarkInfoList[0]:'';
const waterMarkInfo = (waterInfo&&waterInfo.content.length>0)?waterInfo.content:'水印信息';
const waterMarkW = 120;
const waterMarkH = 120;
const rotationAngle = -30;
iOffScreenContext.font = `${16 * scale}vp`;
const iWidth = canvasSize?canvasSize.width: DisplayUtil.getWidth();
const iHeight = canvasSize?canvasSize.height: DisplayUtil.getHeight();
const colCount = Math.ceil(iWidth as number / waterMarkW);
const rowCount = Math.ceil(iHeight as number / waterMarkH);
for (let col = 0; col < colCount; col++) {
for (let row = 0; row <= rowCount; row++) {
iOffScreenContext.save();
iOffScreenContext.translate(col * waterMarkW, row * waterMarkH);
iOffScreenContext.rotate((rotationAngle * Math.PI) / 180);
iOffScreenContext.fillText(waterMarkInfo, 0, 0);
iOffScreenContext.restore();
}
}
}
}
核心的水印信息绘制代码如下:
1.创建画布
2.绘制原始图片
3.设置画布的属性
4.绘制水印(通过水印绘制器工厂get到每个样式的绘制器进行单独绘制)
export async function addWaterMarkWithContext(
context: UIContext,
imagePixelMap: LXImagePixelMap,
waterMarkInfoList?: LXWaterMarkInfo[],
waterMarkFillOption?: LXWaterMarkFillOption,
customDrawer?: (ctx: OffscreenCanvasRenderingContext2D) => void
): Promise<image.PixelMap> {
if (!context) {
LogUtil.error('Context is undefined, returning original image');
ToastUtil.showToast('Context为空,返回原图');
return imagePixelMap.pixelMap;
}
// 创建离屏画布
const iHeight = context.px2vp(imagePixelMap.height);
const iWidth = context.px2vp(imagePixelMap.width);
const offScreenCanvas = new OffscreenCanvas(iWidth, iHeight);
const offScreenContext = offScreenCanvas.getContext('2d');
if (!offScreenContext) {
throw new Error('Failed to create offscreen context');
}
// 绘制原始图片
offScreenContext.drawImage(imagePixelMap.pixelMap, 0, 0, iWidth, iHeight);
// 自定义或自动水印
if (customDrawer) {
customDrawer(offScreenContext);
} else if (waterMarkFillOption && waterMarkInfoList?.length) {
const scale = await calculateImageScale(context, iWidth);
const drawer = WaterMarkDrawerFactory.getDrawer(waterMarkFillOption.waterMartStyle);
// 设置全局画布属性
offScreenContext.textAlign = waterMarkFillOption.textAlign || 'left';
offScreenContext.fillStyle = waterMarkFillOption.textFillStyle || '#A2FFFFFF';
offScreenContext.globalAlpha = waterMarkFillOption.textGlobalAlpha || 1.0;
//绘制水印
await drawer.draw(offScreenContext, imagePixelMap, waterMarkInfoList, waterMarkFillOption, scale,{width:iWidth,height:iHeight});
}
return offScreenContext.getPixelMap(0, 0, iWidth, iHeight);
}
详细demo工程:
gitcode.com/luxingxing1… 如有使用请注明来源,不要直接上传的官方Demo工程。
效果图: