201 lines
5.9 KiB
Plaintext
201 lines
5.9 KiB
Plaintext
import { ActionType, Position, RectPosition } from './RectCropView';
|
|
|
|
@ComponentV2
|
|
export struct SelectBoundsView {
|
|
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
|
|
|
|
@Local clipRect: RectPosition = {
|
|
x: 0,
|
|
y: 0,
|
|
width: 80,
|
|
height: 40
|
|
};
|
|
@Local initPosition: Position = {
|
|
x: 0,
|
|
y: 0
|
|
}
|
|
@Local fontSize: number = 15
|
|
|
|
build() {
|
|
Stack() {
|
|
Stack()
|
|
.position({
|
|
x: this.clipRect.x,
|
|
y: this.clipRect.y
|
|
})
|
|
.width(this.clipRect.width)
|
|
.height(this.clipRect.height)
|
|
.blur(20)
|
|
.id('mosaic')
|
|
|
|
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 (this.onRectChange) {
|
|
this.onRectChange(this.clipRect)
|
|
}
|
|
})
|
|
}
|
|
|
|
// 绘制裁剪框
|
|
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), 80),
|
|
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
|
|
}
|
|
}
|
|
} |