图片旋转时闪烁
=======

#### 问题现象

用户旋转设备时，当前页面指针转动闪烁，影响用户体验。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c7/v3/4wIWXnsuTqGpiNizwiSPnA/zh-cn_image_0000002628394984.png?HW-CC-KV=V1&HW-CC-Date=20260709T134019Z&HW-CC-Expire=86400&HW-CC-Sign=B6F4E16F47CC4ADCB2D1410000B04E49DA407900F3D205850F6118CC4852C607 "点击放大")

#### 背景知识

*   [Image](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-image)为图片组件，常用于在应用中显示图片。
*   [rotate](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-transformation#rotate)：设置组件旋转。
*   [animation](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-animatorproperty)：组件的某些通用属性变化时，可以通过属性动画实现渐变过渡效果，提升用户体验。

#### 问题定位

1.  使用DevEco Testing查看问题组件，该组件为Image组件。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c1/v3/_j2wFIg9Sg2FTZOy2on1Sw/zh-cn_image_0000002658794249.png?HW-CC-KV=V1&HW-CC-Date=20260709T134019Z&HW-CC-Expire=86400&HW-CC-Sign=D8EF2E13E44221A6D4440C690E392DBF548449B6C3B14265F928F05469E5022C "点击放大")
    
2.  查看该Image组件的设置，该组件未使用animation属性对图片旋转设置动画效果，导致旋转设备时图片闪烁。
    
    import sensor from '@ohos.sensor';
    import base from '@ohos.base';
    import { window } from '@kit.ArkUI';
    import { common } from '@kit.AbilityKit';
    
    export function onDegree(callback: base.Callback<number>): void {
      _// 监听屏幕旋转角度变化_
      sensor.on(sensor.SensorId.GRAVITY, (data: sensor.GravityResponse) => {
        let degree: number = 0;
        degree = CalDegree(data.x, data.y, data.z);
        console.info('degree is ', degree);
        callback(degree);
      });
    }
    
    function CalDegree(x: number, y: number, z: number): number {
      let degree: number = 0;
      _// 3为\*有效\_增量\_角度\_阈值\_系数\*_
      if ((x \* x + y \* y) \* 3 < z \* z) {
        return degree;
      }
      degree = 90 - (Number)(Math.round(Math.atan2(y, -x) / Math.PI \* 180));
      return degree >= 0 ? degree % 360 : degree % 360 + 360;
    }
    
    @Component
    @Entry
    struct Index {
      @State @Watch('changeMyRotate') degree: number = 0;
      @State myRotate: number = 0;
    
      changeMyRotate() {
        if (this.degree - this.myRotate > 180) {
          this.myRotate = this.degree - 360;
        } else {
          this.myRotate = this.degree;
        }
      }
    
      aboutToAppear() {
        let callback = async (degree: number) => {
          this.degree = degree;
        };
        onDegree(callback);
        let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
        window.getLastWindow(context).then((lastWindow) => {
          lastWindow.setWindowLayoutFullScreen(true);
          let systemBarProperties: window.SystemBarProperties = {
            statusBarColor: '#00000000',
            statusBarContentColor: '#ffffff'
          };
          lastWindow.setWindowSystemBarProperties(systemBarProperties);
        });
      }
    
      build() {
        Stack() {
         _ // 背景刻度_
          Image($r('app.media.bg')) _// $r('app.media.bg')需要替换为开发者需要的图片资源文件_
            .width(400)
            .height(400)
            .objectFit(ImageFit.Contain)
          _// 指针_
          Image($r('app.media.compass')) _// $r('app.media.compass')需要替换为开发者需要的图片资源文件_
            .rotate({ angle: -this.myRotate }) _// 图片旋转_
            .width(250)
            .height(250)
            .objectFit(ImageFit.Contain)
           _ // 图片旋转时未设置动画效果_
        }
        .height('100%')
        .width('100%')
        .backgroundColor(Color.Black)
      }
    }
    

#### 分析结论

转动设备进行图片旋转时未设置旋转动画，导致跳帧，造成图片旋转时闪烁。

#### 修改建议

转动设备进行图片旋转时通过animation设置旋转动画。

import sensor from '@ohos.sensor';
import base from '@ohos.base';
import { window } from '@kit.ArkUI';
import { common } from '@kit.AbilityKit';

export function onDegree(callback: base.Callback<number>): void {
 _ // 监听屏幕旋转角度变化_
  sensor.on(sensor.SensorId.GRAVITY, (data: sensor.GravityResponse) => {
    let degree: number = 0;
    degree = CalDegree(data.x, data.y, data.z);
    console.info('degree is ', degree);
    callback(degree);
  });
}

function CalDegree(x: number, y: number, z: number): number {
  let degree: number = 0;
  _// 3 为 有效\_增量\_角度\_阈值\_系数_
  if ((x \* x + y \* y) \* 3 < z \* z) {
    return degree;
  }
  degree = 90 - (Number)(Math.round(Math.atan2(y, -x) / Math.PI \* 180));
  return degree >= 0 ? degree % 360 : degree % 360 + 360;
}

@Component
@Entry
struct Index {
  @State @Watch('changeMyRotate') degree: number = 0;
  @State myRotate: number = 0;

  changeMyRotate() {
    if (this.degree - this.myRotate > 180) {
      this.myRotate = this.degree - 360;
    } else {
      this.myRotate = this.degree;
    }
  }

  aboutToAppear() {
    let callback = async (degree: number) => {
      this.degree = degree;
    };
    onDegree(callback);
    let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
    window.getLastWindow(context).then((lastWindow) => {
      lastWindow.setWindowLayoutFullScreen(true);
      let systemBarProperties: window.SystemBarProperties = {
        statusBarColor: '#00000000',
        statusBarContentColor: '#ffffff'
      };
      lastWindow.setWindowSystemBarProperties(systemBarProperties);
    });
  }

  build() {
    Stack() {
     _ // 背景刻度_
      Image($r('app.media.bg')) _// $r('app.media.bg')需要替换为开发者需要的图片资源文件_
        .width(400)
        .height(400)
        .objectFit(ImageFit.Contain);
     _ // 指针_
      Image($r('app.media.compass')) _// $r('app.media.compass')需要替换为开发者需要的图片资源文件_
        .rotate({ angle: -this.myRotate }) _// 图片旋转_
        .width(250)
        .height(250)
        .objectFit(ImageFit.Contain)
        _// 对图片旋转添加动画_
        .animation({
          duration: 500,
          curve: Curve.EaseOut,
          playMode: PlayMode.Normal
        });
    }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.Black);
  }
}

效果图如下：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/9f/v3/3mjHp3dKRO2E4nBFWisgXA/zh-cn_image_0000002628554886.png?HW-CC-KV=V1&HW-CC-Date=20260709T134019Z&HW-CC-Expire=86400&HW-CC-Sign=1261C62E1E480B0DA0B420D256413D2B2F662D3A74847A709DA0E816AE706983 "点击放大")