
回复
基于上篇一镜到底实现,做出一些优化,增加长按事件弹出操作框。
演示:
上篇不足:
1.图片初始位置相对屏幕Y轴的偏移没有赋值,影响图片放大后拖动的上下边界,导致上边会有黑边,下边有一部分显示不全
2.图片缩放没有限制,图片可以放大很大
3.手势识别区域为图片初始大小,放大之后其他区域没有响应
优化:
1.图片绘制完成之后,获取图片左上角相对页面左上角的位置
.onAreaChange((oldValue: Area, newValue: Area) => {
this.imagePositionY = vp2px(Number(newValue.globalPosition.y))
})
2.通过图片原始像素和屏幕像素的对比,设置图片的最大放大比例,再捏合手势里限制图片放大倍数
// 计算图片最大缩放比例(基于窗口和图片尺寸)
calcFitScaleRatio(imageWidth: number,imageHeight:number): number {
let ratio: number = 1.0;
if (this.componentWidth > imageWidth) {
ratio = this.componentWidth / imageWidth;
} else {
ratio = this.componentHeight / imageHeight;
}
return ratio + 2; // 如果嫌小可以自定义增大倍数
}
3.Image的背景Stack改为充满屏幕,这样手势可以全屏识别,更具图片的高度和屏幕高度计算图片Y轴偏移
屏幕高度-图片高度-导航栏-状态栏
this.geometryPositionY = (this.componentHeight-this.imageHeight-this.systemBarHeight)/2
4.图片放大之后禁用Swiper滑动
5.增加图片长按弹框,可以添加图片相关操作事件,给Stack绑定全屏模态页面
@Builder
sheetBuilder(){
Stack({alignContent:Alignment.Bottom}){
Column(){
Row({space:10}){
Column({space:5}){
Image($r('app.media.icon_pic_save')).objectFit(ImageFit.Contain).padding(5).width(40).height(40).backgroundColor(Color.White).borderRadius(5)
Text('保存图片').fontSize(12)
}.onClick(()=>{
promptAction.showToast({
message: '保存图片成功',
duration: 1000,
alignment:Alignment.Center
});
})
}
.width('100%')
.justifyContent(FlexAlign.Start)
.alignItems(VerticalAlign.Center)
.padding({top:30,bottom:20,left:10,right:10})
Divider().color(Color.Gray)
Text('取消').textAlign(TextAlign.Center).fontColor(Color.Blue).margin({top:20}).width('100%').height(60)
.onClick(()=>{
this.isShowSheet=false
})
}
.borderRadius({
topLeft:10,
topRight:10
})
.width('100%')
.backgroundColor('#F1F1F1')
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
}
.width('100%')
.height('100%')
.backgroundColor('#66000000')
}
源码:
import { display, matrix4, promptAction } from "@kit.ArkUI";
enum Status {
IDLE, // 初始状态(无手势)
PINCHING, // 双指捏合缩放中
PAN_ONLY, // 单指拖动中
READY_TO_BACK // 准备返回上一页
}
@ComponentV2
export struct PhotoPreviewItem {
@Consumer() isDisableSwipe:boolean=true
// 屏幕尺寸(vp)
public componentHeight: number = display.getDefaultDisplaySync().height;
public componentWidth: number = display.getDefaultDisplaySync().width;
@Local status: Status = Status.IDLE; // 当前手势状态
@Local gestureCount: number = 0; // 手势并发计数(用于判断所有手势是否结束)
@BuilderParam imageUrl: string; // 图片资源路径
@BuilderParam systemBarHeight: number; // 导航栏和状态栏高度
@Local imageScale: number = 1; // 图片缩放比例(双指捏合控制)
public maxScale: number = 1;
@Local imagePullingDownScale: number = 1; // 下拉拖动时的缩放比例(影响整体大小)
@Local backOpacity: number = 1; // 黑色背景和下拉比例有关
@Local imageTranslateX: number = 0; // X轴偏移量(px,拖动控制)
@Local imageTranslateY: number = 0; // Y轴偏移量(px,拖动控制)
@Local geometryPositionX: number = 0; // 几何过渡X坐标
@Local geometryPositionY: number = 0; // 几何过渡Y坐标
@Local centerX: number = 0; // 缩放中心X(相对图片的比例)
@Local centerY: number = 0; // 缩放中心Y(相对图片的比例)
@Local imageWidth: number = display.getDefaultDisplaySync().width; // 图片原始宽度(px)
@Local imageHeight: number = display.getDefaultDisplaySync().height; // 图片原始高度(px)
@Local panDirection: PanDirection = PanDirection.Vertical; // 拖动手势允许的方向
@Local gestureDisabled: boolean = false; // 是否禁用所有手势
// 图片拖动边界限制(vp)
@Local maxOffsetX: number = 0; // X轴最大偏移(右边界)
@Local minOffsetX: number = 0; // X轴最小偏移(左边界)
@Local maxOffsetY: number = 0; // Y轴最大偏移(下边界)
@Local minOffsetY: number = 0; // Y轴最小偏移(上边界)
// 实际显示区域边界(px,由图片和屏幕共同决定)
private realDisplayBoundsLeft: number = 0;
private realDisplayBoundsTop: number = 0;
private realDisplayBoundsRight: number = 0;
private realDisplayBoundsBottom: number = 0;
// 手势起始状态记录(用于计算增量)
private startGestureOffsetX: number = 0; // 起始X偏移(vp)
private startGestureOffsetY: number = 0; // 起始Y偏移(vp)
private startGestureScale: number = 1; // 起始缩放比例
// 图片原始位置(未变换时的坐标,px)
private imagePositionX: number = 0;
private imagePositionY: number = 0;
// 屏幕边界(px)
private displayLeft: number = 0;
private displayTop: number = 0;
private displayRight: number = display.getDefaultDisplaySync().width;
private displayBottom: number = display.getDefaultDisplaySync().height;
// 上一次缩放中心(用于计算偏移补偿)
private lastCenterX: number = 0;
private lastCenterY: number = 0;
private geometryScale: number = 1; // 几何过渡缩放比例
private firstStarted = true; // 是否首次加载
@BuilderParam backToFirstPage: () => void; // 返回上一页的回调
@Local isShowSheet: boolean = false
// 监听手势计数变化,所有手势结束后触发
@Monitor('gestureCount')
onAllGestureFinish(): void {
if (this.firstStarted) {
this.firstStarted = false;
return;
}
if (this.gestureCount !== 0) return;
// 空闲状态:修正图片位置(避免超出边界)
if (this.status === Status.IDLE) {
this.disableGesture();
this.getUIContext().animateTo({
duration: 300,
onFinish: () => {
this.updatePanDirection();
this.resumeGesture();
}
}, () => {
this.imagePullingDownScale = 1;
this.backOpacity = this.imagePullingDownScale
let leftTop = this.calculateLeftTopPoint();
let leftTopX = leftTop[0];
let leftTopY = leftTop[1];
let rightBottom = this.calculateRightBottomPoint();
let rightBottomX = rightBottom[0];
let rightBottomY = rightBottom[1];
const imageWidth = this.imageWidth * this.imageScale;
const imageHeight = this.imageHeight * this.imageScale;
// X轴居中或边界修正
if (imageWidth < this.displayRight - this.displayLeft) {
this.centerX = 0;
this.imageTranslateX = 0;
} else if (leftTopX > this.displayLeft) {
this.imageTranslateX += (this.displayLeft - leftTopX);
} else if (rightBottomX < this.displayRight) {
this.imageTranslateX += (this.displayRight - rightBottomX);
}
// Y轴居中或边界修正
if (imageHeight < this.displayBottom - this.displayTop) {
this.centerY = 0;
this.imageTranslateY = 0;
} else if (leftTopY > this.displayTop) {
this.imageTranslateY += (this.displayTop - leftTopY);
} else if (rightBottomY < this.displayBottom) {
this.imageTranslateY += (this.displayBottom - rightBottomY);
}
});
}
// 准备返回状态:执行过渡动画后返回上一页
if (this.status === Status.READY_TO_BACK) {
this.status = Status.IDLE;
this.disableGesture();
this.getUIContext().animateTo({
duration: 100,
onFinish: () => {
this.resumeGesture();
this.updatePanDirection();
this.backToFirstPage();
}
}, () => {
let leftTop = this.calculateLeftTopPoint();
let leftTopX = leftTop[0];
let leftTopY = leftTop[1];
this.geometryPositionX = leftTopX - this.imagePositionX;
this.geometryPositionY = leftTopY - this.imagePositionY+(this.componentHeight-this.imageHeight-this.systemBarHeight)/2;
this.geometryScale = this.imageScale * this.imagePullingDownScale;
this.resetTransform();
});
}
}
/**
* 根据缩放中心变化调整偏移量,确保缩放后图片位置不变
* (解决缩放中心改变时图片"跳变"的问题)
*/
updateTranslateAccordingToCenter() {
if (this.lastCenterX === this.centerX && this.lastCenterY === this.centerY) {
return; // 中心未变化,无需调整
}
// 计算中心变化前后的矩阵变换差异
const matrixOld = matrix4.identity()
.scale({
x: this.imageScale * this.imagePullingDownScale,
y: this.imageScale * this.imagePullingDownScale,
centerX: this.lastCenterX,
centerY: this.lastCenterY
})
.translate({ x: this.imageTranslateX, y: this.imageTranslateY });
const matrixNew = matrix4.identity()
.scale({
x: this.imageScale * this.imagePullingDownScale,
y: this.imageScale * this.imagePullingDownScale,
centerX: this.centerX,
centerY: this.centerY
})
.translate({ x: this.imageTranslateX, y: this.imageTranslateY });
// 计算图片左上角点在新旧矩阵下的位置差异,补偿偏移量
let leftTopOld = matrixOld.transformPoint([-this.imageWidth / 2, -this.imageHeight / 2]);
let leftTopNew = matrixNew.transformPoint([-this.imageWidth / 2, -this.imageHeight / 2]);
this.imageTranslateX += (leftTopOld[0] - leftTopNew[0]);
this.imageTranslateY += (leftTopOld[1] - leftTopNew[1]);
console.log('缩放过程中x,y偏移: X轴偏移量'+this.imageTranslateX+' Y轴偏移量'+this.imageTranslateY)
}
/**
* 更新图片可拖动的边界范围
* (根据当前缩放比例和屏幕大小计算,避免拖动时出现过大空白)
*/
updateExtremeOffset() {
const totalScale = this.imageScale * this.imagePullingDownScale;
const matrix = matrix4.identity()
.scale({
x: totalScale,
y: totalScale,
centerX: this.centerX,
centerY: this.centerY
});
// 计算图片左上角和右下角在变换后的坐标(px)
let leftTop = matrix.transformPoint([-this.imageWidth / 2, -this.imageHeight / 2]);
let leftTopX = leftTop[0];
let leftTopY = leftTop[1];
const leftTopPointX = leftTopX + this.imageWidth / 2 + this.imagePositionX;
const leftTopPointY = leftTopY + this.imageHeight / 2 + this.imagePositionY;
const rightBottomPointX = leftTopPointX + this.imageWidth * totalScale;
const rightBottomPointY = leftTopPointY + this.imageHeight * totalScale;
// 计算实际显示边界(取图片和屏幕的交集)
this.realDisplayBoundsLeft = Math.max(this.displayLeft, leftTopPointX);
this.realDisplayBoundsRight = Math.min(this.displayRight, rightBottomPointX);
this.realDisplayBoundsTop= Math.max(this.displayTop, leftTopPointY);
this.realDisplayBoundsBottom = Math.min(this.displayBottom, rightBottomPointY);
// 转换为可拖动的偏移边界(vp)
this.minOffsetX = px2vp(this.realDisplayBoundsRight - rightBottomPointX);
this.maxOffsetX = px2vp(this.realDisplayBoundsLeft - leftTopPointX);
this.minOffsetY = px2vp(this.realDisplayBoundsBottom - rightBottomPointY);
this.maxOffsetY = px2vp(this.realDisplayBoundsTop - leftTopPointY);
console.log('边界:maxOffsetY: '+this.maxOffsetY+' minOffsetY: '+this.minOffsetY)
}
// 重置拖动方向(根据图片是否超出屏幕边界动态调整)
updatePanDirection(): void {
this.panDirection = PanDirection.Vertical;
let leftTop = this.calculateLeftTopPoint();
let leftTopX = leftTop[0];
let rightBottom = this.calculateRightBottomPoint();
let rightBottomX = rightBottom[0];
// 图片左边界超出屏幕左边缘:允许向右拖动
if (leftTopX < this.displayLeft - 1) {
this.panDirection |= PanDirection.Right;
}
// 图片右边界超出屏幕右边缘:允许向左拖动
if (rightBottomX > this.displayRight + 1) {
this.panDirection |= PanDirection.Left;
}
}
// 重置图片变换状态(位置、缩放均恢复初始值)
resetTransform(): void {
this.imageTranslateX = 0;
this.imageTranslateY = 0;
this.imageScale = 1;
this.imagePullingDownScale = 1;
this.centerX = 0;
this.centerY = 0;
this.updateExtremeOffset();
}
/**
* 更新缩放中心(基于手势中心点)
* @param gestureCenterPoint 手势中心点坐标(px)
*/
updateCenter(gestureCenterPoint: [number, number]) {
this.lastCenterX = this.centerX;
this.lastCenterY = this.centerY;
// 计算当前矩阵变换下的图片左上角坐标
const matrix = matrix4.identity()
.scale({
x: this.imageScale * this.imagePullingDownScale,
y: this.imageScale * this.imagePullingDownScale,
centerX: this.lastCenterX,
centerY: this.lastCenterY
})
.translate({ x: this.imageTranslateX, y: this.imageTranslateY });
let leftTop = matrix.transformPoint([-this.imageWidth / 2, -this.imageHeight / 2]);
let leftTopX = leftTop[0];
let leftTopY = leftTop[1];
const leftTopPointX = leftTopX + this.imageWidth / 2; // 图片左上角X(px)
const leftTopPointY = leftTopY + this.imageHeight / 2; // 图片左上角Y(px)
// 计算手势中心相对图片的比例(作为新的缩放中心)
this.centerX = (gestureCenterPoint[0] - leftTopPointX) / this.imageScale - this.imageWidth / 2;
this.centerY = (gestureCenterPoint[1] - leftTopPointY - this.imagePositionY) / this.imageScale - this.imageHeight / 2 ;
console.log('缩放中心: centerX:'+this.centerX+' centerY:'+this.centerY)
}
// 计算变换后图片左上角坐标(px)
calculateLeftTopPoint(): [number, number] {
const matrix = matrix4.identity()
.scale({
x: this.imageScale * this.imagePullingDownScale,
y: this.imageScale * this.imagePullingDownScale,
centerX: this.centerX,
centerY: this.centerY
})
.translate({ x: this.imageTranslateX, y: this.imageTranslateY });
let leftTop = matrix.transformPoint([-this.imageWidth / 2, -this.imageHeight / 2]);
return [
leftTop[0] + this.imageWidth / 2 + this.imagePositionX,
leftTop[1] + this.imageHeight / 2 + this.imagePositionY
];
}
// 计算变换后图片右下角坐标(px)
calculateRightBottomPoint(): [number, number] {
const matrix = matrix4.identity()
.scale({
x: this.imageScale * this.imagePullingDownScale,
y: this.imageScale * this.imagePullingDownScale,
centerX: this.centerX,
centerY: this.centerY
})
.translate({ x: this.imageTranslateX, y: this.imageTranslateY });
let rightBottom = matrix.transformPoint([this.imageWidth / 2, this.imageHeight / 2]);
return [
rightBottom[0] + this.imageWidth / 2 + this.imagePositionX,
rightBottom[1] + this.imageHeight / 2 + this.imagePositionY
];
}
// 禁用所有手势
disableGesture(): void {
this.gestureDisabled = true;
}
// 恢复所有手势
resumeGesture(): void {
this.gestureDisabled = false;
}
// 判断是否禁用拖动手势
cannotPan(): boolean {
return this.gestureDisabled;
}
// 判断是否禁用捏合手势
cannotPinch(): boolean {
return this.status === Status.PAN_ONLY || this.gestureDisabled;
}
// 组件初始化时执行
aboutToAppear(): void {
this.updateExtremeOffset(); // 初始化边界
this.updatePanDirection(); // 初始化拖动方向
}
@Builder
sheetBuilder(){
Stack({alignContent:Alignment.Bottom}){
Column(){
Row({space:10}){
Column({space:5}){
Image($r('app.media.icon_pic_save')).objectFit(ImageFit.Contain).padding(5).width(40).height(40).backgroundColor(Color.White).borderRadius(5)
Text('保存图片').fontSize(12)
}.onClick(()=>{
promptAction.showToast({
message: '保存图片成功',
duration: 1000,
alignment:Alignment.Center
});
})
}
.width('100%')
.justifyContent(FlexAlign.Start)
.alignItems(VerticalAlign.Center)
.padding({top:30,bottom:20,left:10,right:10})
Divider().color(Color.Gray)
Text('取消').textAlign(TextAlign.Center).fontColor(Color.Blue).margin({top:20}).width('100%').height(60)
.onClick(()=>{
this.isShowSheet=false
})
}
.borderRadius({
topLeft:10,
topRight:10
})
.width('100%')
.backgroundColor('#F1F1F1')
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
}
.width('100%')
.height('100%')
.backgroundColor('#66000000')
}
build() {
Stack() {
// 背景层(随下拉透明度变化)
Column()
.width('100%')
.height('100%')
.backgroundColor(Color.Black)
.transition(TransitionEffect.OPACITY)
.opacity(this.backOpacity)
// 图片层(核心内容)
Stack() {
Image($r(this.imageUrl))
.width(px2vp(this.imageWidth) * this.geometryScale)
.height(px2vp(this.imageHeight) * this.geometryScale)
.onComplete((event) => {
// 图片加载完成后修正宽高比例
const imageWidth = event?.width ?? 0;
const imageHeight = event?.height ?? 0;
this.maxScale = this.calcFitScaleRatio(imageWidth,imageHeight)
this.imageHeight = imageHeight * this.imageWidth / imageWidth;
this.geometryPositionY = (this.componentHeight-this.imageHeight-this.systemBarHeight)/2
})
.transform(matrix4.identity()
.scale({
x: this.imageScale * this.imagePullingDownScale,
y: this.imageScale * this.imagePullingDownScale,
centerX: this.centerX,
centerY: this.centerY
})
.translate({ x: this.imageTranslateX, y: this.imageTranslateY })
)
.id(this.imageUrl)
.geometryTransition(this.imageUrl)
.transition(TransitionEffect.OPACITY)
.position({
x: px2vp(this.geometryPositionX),
y: px2vp(this.geometryPositionY)
})
.onAreaChange((oldValue: Area, newValue: Area) => {
this.imagePositionY = vp2px(Number(newValue.globalPosition.y))
})
.draggable(false)
}
.width('100%')
.height('100%')
.parallelGesture(
GestureGroup(GestureMode.Exclusive,
// 双指捏合缩放手势(核心优化部分)
PinchGesture({ fingers: 2, distance: 1 })
.onActionStart((event: GestureEvent) => {
// 1. 标记状态为"捏合中",禁用拖动冲突
this.status = Status.PINCHING;
// 2. 计算手势中心点(转换为px单位,与图片坐标统一)
let gestureCenter: [number, number] = [vp2px(event.pinchCenterX), vp2px(event.pinchCenterY)];
this.updateCenter(gestureCenter);
// 3. 补偿偏移量,避免中心变化导致图片跳变
this.updateTranslateAccordingToCenter();
// 4. 记录起始缩放比例(用于计算增量)
this.startGestureScale = this.imageScale;
// 5. 增加手势计数(标记手势开始)
this.gestureCount++;
})
.onActionUpdate((event: GestureEvent) => {
// 1. 计算当前缩放比例(基于起始比例和手势缩放增量)
let newScale = this.startGestureScale * event.scale;
// 2. 限制缩放范围(避免过度缩放)
newScale = Math.max(0.5, Math.min(newScale, this.maxScale));
this.imageScale = newScale;
// 3. 实时更新边界,确保拖动限制有效
this.updateExtremeOffset();
})
.onActionEnd(() => {
// 1. 恢复状态为"空闲"
this.status = Status.IDLE;
// 2. 缩放小于1时,动画恢复到1倍(优化体验)
if (this.imageScale < 1) {
this.getUIContext().animateTo({ duration: 250, curve: Curve.EaseOut }, () => {
this.imageScale = 1;
});
}
if (this.imageScale>1) {
this.isDisableSwipe = true
}else {
this.isDisableSwipe = false
}
// 3. 减少手势计数(标记手势结束)
this.gestureCount--;
}),
// 单指拖动手势
PanGesture({ direction: this.panDirection })
.onActionStart((event: GestureEvent) => {
// 初始方向为垂直,识别后改为全方向
this.panDirection = PanDirection.All;
let leftTop = this.calculateLeftTopPoint();
let leftTopY = leftTop[1];
// 图片未超出屏幕且非捏合状态:标记为"拖动中"
if (leftTopY >= this.displayTop - 1 && this.status !== Status.PINCHING) {
this.status = Status.PAN_ONLY;
}
// 非捏合状态下,更新拖动中心
if (this.status !== Status.PINCHING) {
const finger = event.fingerList[0];
const currentX = finger?.globalX ?? event.offsetX;
const currentY = finger?.globalY ?? event.offsetY;
let centerPoint : [number, number]= [vp2px(currentX), vp2px(currentY )];
this.updateCenter(centerPoint);
this.updateTranslateAccordingToCenter();
this.updateExtremeOffset();
}
// 记录起始偏移量
this.startGestureOffsetX = px2vp(this.imageTranslateX);
this.startGestureOffsetY = px2vp(this.imageTranslateY);
this.gestureCount++;
})
.onActionUpdate((event: GestureEvent) => {
const offsetX = event.offsetX;
const offsetY = event.offsetY;
// 拖动状态:直接更新偏移(带动画效果)
if (this.status === Status.PAN_ONLY) {
this.imageTranslateX = vp2px(this.startGestureOffsetX + offsetX);
this.imageTranslateY = vp2px(this.startGestureOffsetY + offsetY);
// 下拉时降低背景透明度
this.imagePullingDownScale = 1 - Math.abs(event.offsetY) / px2vp(this.displayBottom);
this.backOpacity = this.imagePullingDownScale
console.log('拖动时偏移: imageTranslateX:'+this.imageTranslateX+' imageTranslateY:'+this.imageTranslateY)
}
// 非拖动状态(缩放后拖动):带边界限制
if (this.status !== Status.PAN_ONLY) {
// 边界弹性限制(超出边界时阻力增大)
let limitedOffsetX = offsetX;
let limitedOffsetY = offsetY;
// X轴边界限制
if (offsetX + this.startGestureOffsetX > this.maxOffsetX) {
const distance = offsetX + this.startGestureOffsetX - this.maxOffsetX;
limitedOffsetX = this.maxOffsetX + distance * (1 - Math.exp(-distance / 300)) - this.startGestureOffsetX;
} else if (offsetX + this.startGestureOffsetX < this.minOffsetX) {
const distance = this.minOffsetX - (offsetX + this.startGestureOffsetX);
limitedOffsetX = this.minOffsetX - distance * (1 - Math.exp(-distance / 300)) - this.startGestureOffsetX;
}
// Y轴边界限制
if (offsetY + this.startGestureOffsetY > this.maxOffsetY) {
const distance = offsetY + this.startGestureOffsetY - this.maxOffsetY;
limitedOffsetY = this.maxOffsetY + distance * (1 - Math.exp(-distance / 300)) - this.startGestureOffsetY;
} else if (offsetY + this.startGestureOffsetY < this.minOffsetY) {
const distance = this.minOffsetY - (offsetY + this.startGestureOffsetY);
limitedOffsetY = this.minOffsetY - distance * (1 - Math.exp(-distance / 300)) - this.startGestureOffsetY;
}
// console.log('边界: limitedOffsetX: '+limitedOffsetX+'limitedOffsetY: '+limitedOffsetY)
// 应用限制后的偏移
this.imageTranslateX = vp2px(this.startGestureOffsetX + limitedOffsetX);
this.imageTranslateY = vp2px(this.startGestureOffsetY + limitedOffsetY);
console.log('拖动时偏移: imageTranslateX:'+this.imageTranslateX+' imageTranslateY:'+this.imageTranslateY)
}
})
.onActionEnd((event: GestureEvent) => {
// 拖动结束:判断是否返回上一页
if (this.status === Status.PAN_ONLY) {
this.status = event.offsetY > 100 ? Status.READY_TO_BACK : Status.IDLE;
}
this.gestureCount--;
}),
// 双击手势(放大/还原)
TapGesture({ count: 2 })
.onAction(() => {
this.imageScale = this.imageScale > 1 ? 1 : 2; // 双击切换1倍/2倍
if (this.imageScale==1) {
this.isDisableSwipe = false
}else {
this.isDisableSwipe = true
this.panDirection = PanDirection.All;
}
this.onAllGestureFinish();
}),
// 单击手势(未缩放时返回)
TapGesture({ count: 1 })
.onAction(() => {
if (this.imageScale === 1) {
this.backToFirstPage();
}
}),
//长按手势
LongPressGesture()
.onAction(()=>{
if (this.status === Status.IDLE) {
this.isShowSheet = true
}
})
)
)
.onGestureJudgeBegin((gestureInfo: GestureInfo, event: BaseGestureEvent) => {
// 手势冲突判断:优先处理当前状态允许的手势
if (gestureInfo.type === GestureControl.GestureType.PAN_GESTURE) {
return this.cannotPan() ? GestureJudgeResult.REJECT : GestureJudgeResult.CONTINUE;
}
if (gestureInfo.type === GestureControl.GestureType.PINCH_GESTURE) {
return this.cannotPinch() ? GestureJudgeResult.REJECT : GestureJudgeResult.CONTINUE;
}
return GestureJudgeResult.CONTINUE;
})
.bindContentCover(this.isShowSheet,this.sheetBuilder())
}
.width('100%')
.height('100%')
}
// 计算图片最大缩放比例(基于窗口和图片尺寸)
calcFitScaleRatio(imageWidth: number,imageHeight:number): number {
let ratio: number = 1.0;
if (this.componentWidth > imageWidth) {
ratio = this.componentWidth / imageWidth;
} else {
ratio = this.componentHeight / imageHeight;
}
return ratio + 2;
}
}