import { StrUtil } from '@pura/harmony-utils'; import { ActionType, Position, RectPosition } from './RectCropView'; @ComponentV2 export struct WatermarkView { private settings: RenderingContextSettings = new RenderingContextSettings(true); private canvasContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private actionType: ActionType = ActionType.move; private touchPosition: Position = { x: 0, y: 0 }; private sw: number = 0; //图片展示框固定宽度 private sh: number = 0; //图片展示框固定高度 @Param onRectChange?: (rect: RectPosition) => void = undefined @Param onClose?: () => void = undefined @Param content: string = '' @Param textColor: string = '' @Param imagePath: string = '' @Param imageRadius: number = 0 @Local clipRect: RectPosition = { x: 0, y: 0, width: 80, height: 40 }; @Local initPosition: Position = { x: 0, y: 0 } @Local fontSize: number = 15 build() { Stack() { if (StrUtil.isNotEmpty(this.content)) { Text(this.content) .position({ x: this.clipRect.x, y: this.clipRect.y }) .width(this.clipRect.width) .height(this.clipRect.height) .fontColor(this.textColor ? this.textColor : Color.White) .fontSize(this.fontSize) .textAlign(TextAlign.Center) .onSizeChange(() => { this.caleTextSize() }) .id('textWatermark') } else if (StrUtil.isNotEmpty(this.imagePath)) { Image(this.imagePath) .position({ x: this.clipRect.x, y: this.clipRect.y }) .width(this.clipRect.width) .height(this.clipRect.height) .borderRadius(this.imageRadius) .id('imageWatermark') } Image($r('app.media.ic_right_bottom_rect')) .position({ x: this.clipRect.x + this.clipRect.width - 9, y: this.clipRect.y + this.clipRect.height - 9 }) .width(15) .height(15) // 裁剪框 Canvas(this.canvasContext) .position({ x: this.clipRect.x, y: this.clipRect.y }) .width(this.clipRect.width) .height(this.clipRect.height) .onReady(() => { this.drawClipImage() }) .onTouch(event => { if (event.type === TouchType.Down) { this.isMove(event.target.area, event.touches[0]); this.touchPosition = { x: event.touches[0].screenX, y: event.touches[0].screenY } } else if (event.type === TouchType.Move) { let moveX = event.changedTouches[0].screenX - this.touchPosition.x; let moveY = event.changedTouches[0].screenY - this.touchPosition.y; this.touchPosition = { x: event.changedTouches[0].screenX, y: event.changedTouches[0].screenY } this.moveClipCanvas(moveX, moveY); } }) Image($r('app.media.ic_left_top_rect')) .position({ x: this.clipRect.x - 7, y: this.clipRect.y - 7 }) .width(16) .height(16) .onClick(() => { if (this.onClose) { this.onClose() } }) } .width('100%') .height('100%') .onAreaChange((_oldArea, newArea) => { this.sw = newArea.width as number this.sh = newArea.height as number if (StrUtil.isNotEmpty(this.imagePath)) { this.clipRect.width = 80 this.clipRect.height = 80 } this.moveClipCanvas(0, 0) }) } // 绘制裁剪框 drawClipImage() { this.canvasContext.clearRect(0, 0, this.clipRect.width, this.clipRect.height); this.canvasContext.lineWidth = 2 this.canvasContext.strokeStyle = Color.White this.canvasContext.beginPath() this.canvasContext.rect(0, 0, this.clipRect.width, this.clipRect.height) this.canvasContext.stroke() } // 裁剪框位置和大小变化 初始位置为图片的初始坐标 移动的坐标 moveClipCanvas(moveX: number, moveY: number) { let clipRect: RectPosition = { x: this.clipRect.x, y: this.clipRect.y, width: this.clipRect.width, height: this.clipRect.height } switch (this.actionType) { case ActionType.move: clipRect.x += moveX; clipRect.y += moveY; break; case ActionType.topLeft: clipRect.x += moveX; clipRect.y += moveY; clipRect.width += -moveX; clipRect.height += -moveY; break; case ActionType.topRight: clipRect.y += moveY; clipRect.width += moveX; clipRect.height += -moveY; break; case ActionType.bottomLeft: clipRect.x += moveX; clipRect.width += -moveX; clipRect.height += moveY; break; case ActionType.bottomRight: clipRect.width += moveX; clipRect.height += moveY; break; default: break; } // 偏移坐标小于初始位置 if (clipRect.x < this.initPosition.x) { clipRect.x = this.initPosition.x; } if (clipRect.y < this.initPosition.y) { clipRect.y = this.initPosition.y; } // 横坐标限制位置 if (clipRect.width + clipRect.x > this.sw + this.initPosition.x) { if (this.actionType === ActionType.move) { clipRect.x = this.sw + this.initPosition.x - clipRect.width; } else { clipRect.width = this.sw + this.initPosition.x - clipRect.x; } } // 纵坐标限制 if (clipRect.height + clipRect.y > this.sh + this.initPosition.y) { if (this.actionType === ActionType.move) { clipRect.y = this.sh + this.initPosition.y - clipRect.height; } else { clipRect.height = this.sh + this.initPosition.y - clipRect.y; } } //裁剪框位置大小 this.clipRect = { x: Math.round(clipRect.x), y: Math.round(clipRect.y), width: Math.max(Math.round(clipRect.width), StrUtil.isNotEmpty(this.content) ? 80 : 40), height: Math.max(Math.round(clipRect.height), 40) }; if (this.onRectChange) { this.onRectChange(this.clipRect) } } // 判断操作类型 isMove(area: Area, touch: TouchObject) { if (touch.x < 30 && touch.y < 30) { // 左上角 this.actionType = ActionType.topLeft } else if (touch.x < 30 && touch.y > (Number(area.height) - 30)) { // 左下 this.actionType = ActionType.bottomLeft } else if (touch.x > Number(area.width) - 30 && touch.y < 30) { // 右上 this.actionType = ActionType.topRight } else if (touch.x > Number(area.width) - 30 && touch.y > (Number(area.height) - 30)) { // 右下 this.actionType = ActionType.bottomRight } else { this.actionType = ActionType.move } } // 缩放文字大小 caleTextSize() { let textSize = this.getUIContext().getMeasureUtils().measureTextSize({ textContent: this.content, fontSize: this.fontSize }) let textWidth = textSize.width let textHeight = textSize.height let ratioW = vp2px(this.clipRect.width - 10) / (textWidth as number) let ratioH = vp2px(this.clipRect.height - 10) / (textHeight as number) let fontSize = Math.floor(this.fontSize * Math.min(ratioW, ratioH)) if (fontSize > 8) { this.fontSize = fontSize } } }