admin管理员组

文章数量:1037775

95.HarmonyOS NEXT 图片约束处理教程:深入理解Constrain

温馨提示:本篇博客的详细代码已发布到 git : 可以下载运行哦!

HarmonyOS NEXT 图片约束处理教程:深入理解Constrain

1. 图片约束基础

1.1 核心概念

概念

说明

应用场景

图片适配类型

定义图片如何适应容器

图片展示方式

偏移约束

限制图片移动范围

拖拽和缩放

边界检测

判断是否超出显示范围

图片浏览

1.2 图片适配类型定义

代码语言:typescript复制
export enum ImageFitType {
    TYPE_WIDTH = 'width',
    TYPE_HEIGHT = 'height',
    TYPE_DEFAULT = 'default'
}

2. 偏移计算实现

2.1 最大偏移量计算

代码语言:typescript复制
export function getMaxAllowedOffset(
  winSize: number,
  imageSize: number,
  scale: number
) {
    const maxNum = Math.max(imageSize * scale, winSize);
    const minNum = Math.min(imageSize * scale, winSize);
    return (maxNum - minNum) / 2;
}

2.2 偏移约束实现

代码语言:typescript复制
function constrainOffset(
  offset: number,
  winSize: number,
  imageSize: number,
  scale: number
): number {
    let maxAllowedOffset = getMaxAllowedOffset(winSize, imageSize, scale);
    return Math.min(Math.max(offset, -maxAllowedOffset), maxAllowedOffset);
}

3. 图片切换判断

3.1 切换条件判断

代码语言:typescript复制
function isToggle(
  offset: number,
  winSize: number,
  imageSize: number,
  scale: number,
  TogglePercent: number
): boolean {
    let maxAllowedOffset = getMaxAllowedOffset(winSize, imageSize, scale);
    const deviation = Math.abs(offset) - maxAllowedOffset;
    const switchThreshold = winSize * TogglePercent;

    return deviation > switchThreshold;
}

3.2 参数说明

参数

说明

用途

offset

当前偏移量

记录当前位置

winSize

窗口大小

确定显示范围

imageSize

图片大小

计算实际尺寸

scale

缩放比例

处理缩放效果

TogglePercent

切换阈值

控制切换灵敏度

4. 图片尺寸处理

4.1 尺寸获取函数

代码语言:typescript复制
export function getImgSize(
  imageSize: image.Size,
  rotate: number,
  dimensionWH: ImageFitType.TYPE_WIDTH | ImageFitType.TYPE_HEIGHT
): number {
    const isStandardRotation = [90, 270].includes(Math.abs(rotate % 360));
    const Key = isStandardRotation ? 
      (dimensionWH == ImageFitType.TYPE_WIDTH ? 
        ImageFitType.TYPE_HEIGHT : 
        ImageFitType.TYPE_WIDTH) :
      dimensionWH;
    return imageSize[Key];
}

4.2 旋转处理

  1. 标准旋转判断const isStandardRotation = [90, 270].includes(Math.abs(rotate % 360));
  2. 维度切换const Key = isStandardRotation ? (dimensionWH == ImageFitType.TYPE_WIDTH ? ImageFitType.TYPE_HEIGHT : ImageFitType.TYPE_WIDTH) : dimensionWH;

5. 约束动画实现

5.1 约束和动画函数

代码语言:typescript复制
export function constrainOffsetAndAnimation(
  info: ConstrainOffsetAndAnimationType
): [boolean, boolean] {
    if (info.dimensionWH === ImageFitType.TYPE_DEFAULT) {
        return [false, false];
    }
    
    const WIN_SIZE = windowSizeManager.get();
    const IMG_SIZE = getImgSize(
      info.imageDefaultSize,
      info.rotate,
      info.dimensionWH
    );
    
    // 获取当前偏移量
    let currentOffset = info.imageOffsetInfo[
      `last${info.dimensionWH === ImageFitType.TYPE_WIDTH ? 'X' : 'Y'}`
    ];
    
    // 处理列表偏移
    if (info.dimensionWH === (
      info.listDirection === Axis.Horizontal ? 
        ImageFitType.TYPE_WIDTH : 
        ImageFitType.TYPE_HEIGHT
    )) {
        currentOffset += info.imageListOffset;
    }
    
    // 计算约束后的偏移量
    const CLAMPED_OFFSET = constrainOffset(
      currentOffset,
      WIN_SIZE[info.dimensionWH],
      IMG_SIZE,
      info.scaleValue
    );
    
    // 处理偏移量变化
    if (CLAMPED_OFFSET !== currentOffset) {
        let updateFn = () => {
            info.imageOffsetInfo[
              `current${info.dimensionWH == ImageFitType.TYPE_WIDTH ? 'X' : 'Y'}`
            ] = CLAMPED_OFFSET;
            info.imageOffsetInfo.stash();
        };
        
        runWithAnimation(updateFn);
        
        // 检查是否需要切换图片
        if (isToggle(
          currentOffset,
          WIN_SIZE[info.dimensionWH],
          IMG_SIZE,
          info.scaleValue,
          info.TogglePercent
        )) {
            const BOL = currentOffset >= 0;
            return [BOL, !BOL];
        }
    }
    
    return [false, false];
}

5.2 使用示例

代码语言:typescript复制
// 处理图片约束和动画
const [leftExceeded, rightExceeded] = constrainOffsetAndAnimation({
    dimensionWH: ImageFitType.TYPE_WIDTH,
    imageDefaultSize: imageSize,
    imageOffsetInfo: offsetModel,
    scaleValue: scale,
    rotate: rotation,
    TogglePercent: 0.2,
    imageListOffset: listOffset,
    listDirection: Axis.Horizontal
});

// 根据结果处理图片切换
if (leftExceeded) {
    // 切换到上一张
    switchToPrevious();
} else if (rightExceeded) {
    // 切换到下一张
    switchToNext();
}

6. 最佳实践

6.1 性能优化

  1. 缓存计算结果const maxOffset = getMaxAllowedOffset(winSize, imageSize, scale); // 多次使用maxOffset而不是重复计算
  2. 避免频繁更新// 使用防抖处理频繁的约束计算 const debouncedConstrain = debounce((info) => { constrainOffsetAndAnimation(info); }, 16);

6.2 错误处理

代码语言:typescript复制
function safeConstrainOffset(info: ConstrainOffsetAndAnimationType) {
    try {
        return constrainOffsetAndAnimation(info);
    } catch (error) {
        console.error('Constrain calculation failed:', error);
        return [false, false];
    }
}

通过合理使用图片约束处理,可以实现流畅的图片浏览体验。在实际开发中,要注意性能优化和边界情况处理,确保图片操作的准确性和流畅性。

95.HarmonyOS NEXT 图片约束处理教程:深入理解Constrain

温馨提示:本篇博客的详细代码已发布到 git : 可以下载运行哦!

HarmonyOS NEXT 图片约束处理教程:深入理解Constrain

1. 图片约束基础

1.1 核心概念

概念

说明

应用场景

图片适配类型

定义图片如何适应容器

图片展示方式

偏移约束

限制图片移动范围

拖拽和缩放

边界检测

判断是否超出显示范围

图片浏览

1.2 图片适配类型定义

代码语言:typescript复制
export enum ImageFitType {
    TYPE_WIDTH = 'width',
    TYPE_HEIGHT = 'height',
    TYPE_DEFAULT = 'default'
}

2. 偏移计算实现

2.1 最大偏移量计算

代码语言:typescript复制
export function getMaxAllowedOffset(
  winSize: number,
  imageSize: number,
  scale: number
) {
    const maxNum = Math.max(imageSize * scale, winSize);
    const minNum = Math.min(imageSize * scale, winSize);
    return (maxNum - minNum) / 2;
}

2.2 偏移约束实现

代码语言:typescript复制
function constrainOffset(
  offset: number,
  winSize: number,
  imageSize: number,
  scale: number
): number {
    let maxAllowedOffset = getMaxAllowedOffset(winSize, imageSize, scale);
    return Math.min(Math.max(offset, -maxAllowedOffset), maxAllowedOffset);
}

3. 图片切换判断

3.1 切换条件判断

代码语言:typescript复制
function isToggle(
  offset: number,
  winSize: number,
  imageSize: number,
  scale: number,
  TogglePercent: number
): boolean {
    let maxAllowedOffset = getMaxAllowedOffset(winSize, imageSize, scale);
    const deviation = Math.abs(offset) - maxAllowedOffset;
    const switchThreshold = winSize * TogglePercent;

    return deviation > switchThreshold;
}

3.2 参数说明

参数

说明

用途

offset

当前偏移量

记录当前位置

winSize

窗口大小

确定显示范围

imageSize

图片大小

计算实际尺寸

scale

缩放比例

处理缩放效果

TogglePercent

切换阈值

控制切换灵敏度

4. 图片尺寸处理

4.1 尺寸获取函数

代码语言:typescript复制
export function getImgSize(
  imageSize: image.Size,
  rotate: number,
  dimensionWH: ImageFitType.TYPE_WIDTH | ImageFitType.TYPE_HEIGHT
): number {
    const isStandardRotation = [90, 270].includes(Math.abs(rotate % 360));
    const Key = isStandardRotation ? 
      (dimensionWH == ImageFitType.TYPE_WIDTH ? 
        ImageFitType.TYPE_HEIGHT : 
        ImageFitType.TYPE_WIDTH) :
      dimensionWH;
    return imageSize[Key];
}

4.2 旋转处理

  1. 标准旋转判断const isStandardRotation = [90, 270].includes(Math.abs(rotate % 360));
  2. 维度切换const Key = isStandardRotation ? (dimensionWH == ImageFitType.TYPE_WIDTH ? ImageFitType.TYPE_HEIGHT : ImageFitType.TYPE_WIDTH) : dimensionWH;

5. 约束动画实现

5.1 约束和动画函数

代码语言:typescript复制
export function constrainOffsetAndAnimation(
  info: ConstrainOffsetAndAnimationType
): [boolean, boolean] {
    if (info.dimensionWH === ImageFitType.TYPE_DEFAULT) {
        return [false, false];
    }
    
    const WIN_SIZE = windowSizeManager.get();
    const IMG_SIZE = getImgSize(
      info.imageDefaultSize,
      info.rotate,
      info.dimensionWH
    );
    
    // 获取当前偏移量
    let currentOffset = info.imageOffsetInfo[
      `last${info.dimensionWH === ImageFitType.TYPE_WIDTH ? 'X' : 'Y'}`
    ];
    
    // 处理列表偏移
    if (info.dimensionWH === (
      info.listDirection === Axis.Horizontal ? 
        ImageFitType.TYPE_WIDTH : 
        ImageFitType.TYPE_HEIGHT
    )) {
        currentOffset += info.imageListOffset;
    }
    
    // 计算约束后的偏移量
    const CLAMPED_OFFSET = constrainOffset(
      currentOffset,
      WIN_SIZE[info.dimensionWH],
      IMG_SIZE,
      info.scaleValue
    );
    
    // 处理偏移量变化
    if (CLAMPED_OFFSET !== currentOffset) {
        let updateFn = () => {
            info.imageOffsetInfo[
              `current${info.dimensionWH == ImageFitType.TYPE_WIDTH ? 'X' : 'Y'}`
            ] = CLAMPED_OFFSET;
            info.imageOffsetInfo.stash();
        };
        
        runWithAnimation(updateFn);
        
        // 检查是否需要切换图片
        if (isToggle(
          currentOffset,
          WIN_SIZE[info.dimensionWH],
          IMG_SIZE,
          info.scaleValue,
          info.TogglePercent
        )) {
            const BOL = currentOffset >= 0;
            return [BOL, !BOL];
        }
    }
    
    return [false, false];
}

5.2 使用示例

代码语言:typescript复制
// 处理图片约束和动画
const [leftExceeded, rightExceeded] = constrainOffsetAndAnimation({
    dimensionWH: ImageFitType.TYPE_WIDTH,
    imageDefaultSize: imageSize,
    imageOffsetInfo: offsetModel,
    scaleValue: scale,
    rotate: rotation,
    TogglePercent: 0.2,
    imageListOffset: listOffset,
    listDirection: Axis.Horizontal
});

// 根据结果处理图片切换
if (leftExceeded) {
    // 切换到上一张
    switchToPrevious();
} else if (rightExceeded) {
    // 切换到下一张
    switchToNext();
}

6. 最佳实践

6.1 性能优化

  1. 缓存计算结果const maxOffset = getMaxAllowedOffset(winSize, imageSize, scale); // 多次使用maxOffset而不是重复计算
  2. 避免频繁更新// 使用防抖处理频繁的约束计算 const debouncedConstrain = debounce((info) => { constrainOffsetAndAnimation(info); }, 16);

6.2 错误处理

代码语言:typescript复制
function safeConstrainOffset(info: ConstrainOffsetAndAnimationType) {
    try {
        return constrainOffsetAndAnimation(info);
    } catch (error) {
        console.error('Constrain calculation failed:', error);
        return [false, false];
    }
}

通过合理使用图片约束处理,可以实现流畅的图片浏览体验。在实际开发中,要注意性能优化和边界情况处理,确保图片操作的准确性和流畅性。

本文标签: 95HarmonyOS NEXT 图片约束处理教程深入理解Constrain