文档管理中心
FAQ应用框架开发UI框架UI界面图片旋转时闪烁

图片旋转时闪烁

问题现象

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

背景知识

  • Image为图片组件,常用于在应用中显示图片。
  • rotate:设置组件旋转。
  • animation:组件的某些通用属性变化时,可以通过属性动画实现渐变过渡效果,提升用户体验。

问题定位

  1. 使用DevEco Testing查看问题组件,该组件为Image组件。

  2. 查看该Image组件的设置,该组件未使用animation属性对图片旋转设置动画效果,导致旋转设备时图片闪烁。
    收起
    自动换行
    深色代码主题
    复制
    1. import sensor from '@ohos.sensor';
    2. import base from '@ohos.base';
    3. import { window } from '@kit.ArkUI';
    4. import { common } from '@kit.AbilityKit';
    5. export function onDegree(callback: base.Callback<number>): void {
    6. // 监听屏幕旋转角度变化
    7. sensor.on(sensor.SensorId.GRAVITY, (data: sensor.GravityResponse) => {
    8. let degree: number = 0;
    9. degree = CalDegree(data.x, data.y, data.z);
    10. console.info('degree is ', degree);
    11. callback(degree);
    12. });
    13. }
    14. function CalDegree(x: number, y: number, z: number): number {
    15. let degree: number = 0;
    16. // 3为*有效_增量_角度_阈值_系数*
    17. if ((x * x + y * y) * 3 < z * z) {
    18. return degree;
    19. }
    20. degree = 90 - (Number)(Math.round(Math.atan2(y, -x) / Math.PI * 180));
    21. return degree >= 0 ? degree % 360 : degree % 360 + 360;
    22. }
    23. @Component
    24. @Entry
    25. struct Index {
    26. @State @Watch('changeMyRotate') degree: number = 0;
    27. @State myRotate: number = 0;
    28. changeMyRotate() {
    29. if (this.degree - this.myRotate > 180) {
    30. this.myRotate = this.degree - 360;
    31. } else {
    32. this.myRotate = this.degree;
    33. }
    34. }
    35. aboutToAppear() {
    36. let callback = async (degree: number) => {
    37. this.degree = degree;
    38. };
    39. onDegree(callback);
    40. let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
    41. window.getLastWindow(context).then((lastWindow) => {
    42. lastWindow.setWindowLayoutFullScreen(true);
    43. let systemBarProperties: window.SystemBarProperties = {
    44. statusBarColor: '#00000000',
    45. statusBarContentColor: '#ffffff'
    46. };
    47. lastWindow.setWindowSystemBarProperties(systemBarProperties);
    48. });
    49. }
    50. build() {
    51. Stack() {
    52. // 背景刻度
    53. Image($r('app.media.bg')) // $r('app.media.bg')需要替换为开发者需要的图片资源文件
    54. .width(400)
    55. .height(400)
    56. .objectFit(ImageFit.Contain)
    57. // 指针
    58. Image($r('app.media.compass')) // $r('app.media.compass')需要替换为开发者需要的图片资源文件
    59. .rotate({ angle: -this.myRotate }) // 图片旋转
    60. .width(250)
    61. .height(250)
    62. .objectFit(ImageFit.Contain)
    63. // 图片旋转时未设置动画效果
    64. }
    65. .height('100%')
    66. .width('100%')
    67. .backgroundColor(Color.Black)
    68. }
    69. }

分析结论

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

修改建议

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

收起
自动换行
深色代码主题
复制
  1. import sensor from '@ohos.sensor';
  2. import base from '@ohos.base';
  3. import { window } from '@kit.ArkUI';
  4. import { common } from '@kit.AbilityKit';
  5. export function onDegree(callback: base.Callback<number>): void {
  6. // 监听屏幕旋转角度变化
  7. sensor.on(sensor.SensorId.GRAVITY, (data: sensor.GravityResponse) => {
  8. let degree: number = 0;
  9. degree = CalDegree(data.x, data.y, data.z);
  10. console.info('degree is ', degree);
  11. callback(degree);
  12. });
  13. }
  14. function CalDegree(x: number, y: number, z: number): number {
  15. let degree: number = 0;
  16. // 3 为 有效_增量_角度_阈值_系数
  17. if ((x * x + y * y) * 3 < z * z) {
  18. return degree;
  19. }
  20. degree = 90 - (Number)(Math.round(Math.atan2(y, -x) / Math.PI * 180));
  21. return degree >= 0 ? degree % 360 : degree % 360 + 360;
  22. }
  23. @Component
  24. @Entry
  25. struct Index {
  26. @State @Watch('changeMyRotate') degree: number = 0;
  27. @State myRotate: number = 0;
  28. changeMyRotate() {
  29. if (this.degree - this.myRotate > 180) {
  30. this.myRotate = this.degree - 360;
  31. } else {
  32. this.myRotate = this.degree;
  33. }
  34. }
  35. aboutToAppear() {
  36. let callback = async (degree: number) => {
  37. this.degree = degree;
  38. };
  39. onDegree(callback);
  40. let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
  41. window.getLastWindow(context).then((lastWindow) => {
  42. lastWindow.setWindowLayoutFullScreen(true);
  43. let systemBarProperties: window.SystemBarProperties = {
  44. statusBarColor: '#00000000',
  45. statusBarContentColor: '#ffffff'
  46. };
  47. lastWindow.setWindowSystemBarProperties(systemBarProperties);
  48. });
  49. }
  50. build() {
  51. Stack() {
  52. // 背景刻度
  53. Image($r('app.media.bg')) // $r('app.media.bg')需要替换为开发者需要的图片资源文件
  54. .width(400)
  55. .height(400)
  56. .objectFit(ImageFit.Contain);
  57. // 指针
  58. Image($r('app.media.compass')) // $r('app.media.compass')需要替换为开发者需要的图片资源文件
  59. .rotate({ angle: -this.myRotate }) // 图片旋转
  60. .width(250)
  61. .height(250)
  62. .objectFit(ImageFit.Contain)
  63. // 对图片旋转添加动画
  64. .animation({
  65. duration: 500,
  66. curve: Curve.EaseOut,
  67. playMode: PlayMode.Normal
  68. });
  69. }
  70. .height('100%')
  71. .width('100%')
  72. .backgroundColor(Color.Black);
  73. }
  74. }

效果图如下:

在 FAQ 中进行搜索
请输入您想要搜索的关键词