64.Harmonyos NEXT 图片预览组件之手势处理实现(二)
2025-03-14 22:18:02
256次阅读
0个评论
最后修改时间:2025-03-14 22:18:31
温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦!

Harmonyos NEXT 图片预览组件之手势处理实现(二)
效果预览

一、双指旋转手势实现(续)
在上一篇文章中,我们介绍了图片预览组件的单指拖动和双指缩放手势实现。本文将继续介绍双指旋转手势和双击缩放手势的实现细节。
1. 旋转手势处理逻辑
双指旋转手势的核心逻辑包括:
RotationGesture({ angle: this.imageRotateInfo.startAngle })
    .onActionUpdate((event: GestureEvent) => {
        let angle = this.imageRotateInfo.lastRotate + event.angle
        if (event.angle > 0) {
            angle -= this.imageRotateInfo.startAngle;
        } else {
            angle += this.imageRotateInfo.startAngle;
        }
        this.matrix = matrix4.identity()
            .scale({
                x: this.imageScaleInfo.scaleValue,
                y: this.imageScaleInfo.scaleValue
            })
            .rotate({
                x: 0,
                y: 0,
                z: 1,
                angle: angle,
            }).copy();
        this.imageRotateInfo.currentRotate = angle;
    })
    .onActionEnd((event: GestureEvent) => {
        let rotate = simplestRotationQuarter(this.imageRotateInfo.currentRotate);
        runWithAnimation(() => {
            this.imageRotateInfo.currentRotate = rotate;
            this.matrix = matrix4.identity()
                .scale({
                    x: this.imageScaleInfo.scaleValue,
                    y: this.imageScaleInfo.scaleValue
                })
                .rotate({
                    x: 0,
                    y: 0,
                    z: 1,
                    angle: rotate,
                }).copy();
            this.imageRotateInfo.stash();
        })
    })
旋转手势的处理逻辑包括:
- 设置触发旋转的最小角度阈值(startAngle),防止误触
- 根据event.angle计算新的旋转角度,基于上次旋转的结果(lastRotate)
- 应用矩阵变换,实现图片的旋转效果
- 手势结束时,将旋转角度对齐到最接近的90度倍数(0°、90°、180°、270°)
- 保存当前旋转角度为最后旋转角度,用于下次旋转的基准计算
2. 角度对齐处理
为了提供更好的用户体验,组件在旋转手势结束时会将图片角度对齐到最接近的90度倍数:
export function simplestRotationQuarter(angle: number): number {
    // 将角度转换为0-360范围内
    let normalizedAngle = angle % 360;
    if (normalizedAngle < 0) {
        normalizedAngle += 360;
    }
    
    // 计算最接近的90度倍数
    let quarter = Math.round(normalizedAngle / 90) * 90;
    return quarter;
}
这个函数将任意角度转换为最接近的90度倍数,实现了图片旋转的"磁吸"效果。
二、双击缩放手势实现
1. 双击手势处理逻辑
双击缩放功能是图片预览的常见交互方式,其核心实现如下:
TapGesture({ count: 2 })
    .onAction(() => {
        const currentScale = this.imageScaleInfo.scaleValue;
        const targetScale = currentScale > 1 ? 1 : 2;
        
        runWithAnimation(() => {
            this.imageScaleInfo.scaleValue = targetScale;
            this.matrix = matrix4.identity()
                .scale({
                    x: targetScale,
                    y: targetScale
                })
                .rotate({
                    x: 0,
                    y: 0,
                    z: 1,
                    angle: this.imageRotateInfo.currentRotate,
                }).copy();
        })
    })
双击缩放的处理逻辑包括:
- 检测当前缩放值,决定是放大还是还原
- 使用动画过渡到目标缩放值
- 保持当前的旋转角度不变
2. 手势冲突处理
在实现多手势组件时,需要注意手势之间的冲突处理:
GestureGroup(GestureMode.Parallel,
    TapGesture({ count: 2 })...,
    PinchGesture()...,
    RotationGesture()...,
    PanGesture()...
)
三、完整示例
1. 组件定义
@Component
export struct ImagePreview {
    @State private matrix: Matrix4 = matrix4.identity().copy()
    private imageRotateInfo: ImageRotateInfo = new ImageRotateInfo()
    private imageScaleInfo: ImageScaleInfo = new ImageScaleInfo()
    
    build() {
        Image($r('app.media.example'))
            .objectFit(ImageFit.Contain)
            .gesture(
                GestureGroup(GestureMode.Parallel,
                    // 这里放入之前介绍的所有手势
                )
            )
            .transform(this.matrix)
    }
}
2. 效果展示
实现效果如下:
- 支持双指旋转,自动对齐到90度倍数
- 支持双击在1倍和2倍缩放之间切换
- 支持双指缩放和单指拖动
- 所有变换都有平滑动画过渡
四、性能优化建议
- 
  矩阵计算优化 - 避免在手势回调中频繁创建新的矩阵对象
- 考虑使用对象池复用矩阵对象
 
- 
  动画性能优化 - 使用requestAnimationFrame代替setTimeout
- 合理设置动画时长,建议在100-300ms之间
 
- 
  内存管理 - 及时清理不再使用的事件监听器
- 合理使用对象池管理频繁创建的对象
 
五、注意事项
- 
  手势阈值设置 - 旋转手势的起始角度阈值建议设置在5-10度之间
- 缩放手势的最小和最大值需要根据实际场景调整
 
- 
  边界处理 - 需要处理图片旋转后的边界情况
- 缩放时需要考虑内存占用,建议限制最大缩放倍数
 
- 
  兼容性处理 - 需要考虑不同设备的屏幕尺寸
- 注意触控板和触摸屏的交互差异
 
总结
本文详细介绍了HarmonyOS图片预览组件的手势处理实现,包括双指旋转、双击缩放等功能。通过合理的手势配置和动画处理,可以实现流畅的图片预览体验。在实际应用中,还需要根据具体场景进行性能优化和交互细节调整。
00
- 0回答
- 5粉丝
- 0关注
相关话题
- 63.Harmonyos NEXT 图片预览组件之手势处理实现
- 65.Harmonyos NEXT 图片预览组件之手势处理实现(三)
- 75.HarmonyOS NEXT ImageItemView组件深度剖析:手势交互与动画实现(二)
- 【HarmonyOS】头像圆形裁剪功能之手势放大缩小,平移,双击缩放控制(三)
- 72.HarmonyOS NEXT PicturePreviewImage组件深度剖析:手势交互与动画系统深度解析 (二)
- 57.Harmonyos NEXT 图片预览组件实现概览
- 160.HarmonyOS NEXT系列教程之列表交换组件手势系统实现
- 60.Harmonyos NEXT 图片预览组件之边界处理与图片切换
- HarmonyOS NEXT 小说阅读器应用系列教程之手势交互与动画效果开发技巧
- (二二)HarmonyOS Design 的手势设计
- 鸿蒙开发:单一手势实现长按事件
- 59.Harmonyos NEXT 图片预览组件之PicturePreviewImage实现原理
- 62.Harmonyos NEXT 图片预览组件之工具类实现
- 鸿蒙开发:单一手势实现多次点击事件
- 79.HarmonyOS NEXT 手势操作模型详解:移动、缩放与旋转的实现原理

