HarmonyOS鸿蒙Next中 Lottie 动画偶尔不展示、随机空白,请问如何解决?

HarmonyOS鸿蒙Next中 Lottie 动画偶尔不展示、随机空白,请问如何解决? 我在写 动画的时候 ,首次加载成功了 ,后续切换 动画时 时重新加载了整个组件,然后导致 动画有时候不展示 也不占,有时候时占位但是空白

5 回复

未复现问题,使用以下可以正常加载Lottie 动画,您也可以参考:lottie使用示例,还是不行的话可以提供下复现问题的demo嘛

import lottie, { AnimationItem } from '@ohos/lottie';
import { ComponentContent } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';

@Builder
function buildLottie(param: Params) {
  Column() {
    // 关联画布
    Canvas(param.canvas)
      .width(200)
      .height(200)
      .backgroundColor('rgba(247, 206, 0, 0.11)')
      .onReady(() => {
        param.loadAnimation();
      });
  }
  .backgroundColor(Color.Pink)
  .width(100)
  .height(100)
  .alignItems(HorizontalAlign.Center)
  .justifyContent(FlexAlign.Center);
}

class Params {
  canvas: CanvasRenderingContext2D;
  loadAnimation: () => void = () => {
  };

  constructor(canvas: CanvasRenderingContext2D, loadAnimation: () => void) {
    this.canvas = canvas;
    this.loadAnimation = loadAnimation;
  }
}

@Entry
@Component
struct LottiePage {
  canvas: CanvasRenderingContext2D = new CanvasRenderingContext2D(new RenderingContextSettings(true));
  canvas2: CanvasRenderingContext2D = new CanvasRenderingContext2D(new RenderingContextSettings(true));
  private animateItem1: AnimationItem | null = null;
  private animateItem2: AnimationItem | null = null;
  private animateName: string = 'animationName1';
  private animateName2: string = 'animationName2';
  private uiContext = this.getUIContext();
  @State contentNode1: ComponentContent<ESObject> | undefined = undefined;
  @State contentNode2: ComponentContent<ESObject> | undefined = undefined;
  @State isClose1: boolean = true;
  @State isClose2: boolean = true;
  loadAnimation1 = () => {
    this.animateItem1 = lottie.loadAnimation({
      container: this.canvas,
      renderer: 'canvas', // canvas 渲染模式
      loop: true,
      autoplay: false,
      name: this.animateName,
      contentMode: 'Contain',
      path: 'tabBar1.json',
    });
    this.animateItem1.addEventListener('DOMLoaded', (): void => {
      this.animateItem1!.changeColor([225, 25, 100, 1]);
      this.animateItem1!.play();
    });
  };
  loadAnimation2 = () => {
    this.animateItem2 = lottie.loadAnimation({
      container: this.canvas2,
      renderer: 'canvas', // canvas 渲染模式
      loop: true,
      autoplay: false,
      name: this.animateName2,
      contentMode: 'Contain',
      path: 'tabBar3.json',
    });
    this.animateItem2.addEventListener('DOMLoaded', (): void => {
      this.animateItem2!.changeColor([225, 25, 100, 1]);
      this.animateItem2!.play();
    });
  };

  build() {
    Column({ space: 8 }) {
      Button('openLottieDialog')
        .enabled(this.isClose1 && this.isClose2)
        .onClick(() => {
          this.isClose1 = false;
          this.isClose2 = false;
          let promptAction = this.uiContext.getPromptAction();
          this.contentNode1 =
            new ComponentContent(this.uiContext, wrapBuilder(buildLottie),
              new Params(this.canvas, this.loadAnimation1));
          this.contentNode2 =
            new ComponentContent(this.uiContext, wrapBuilder(buildLottie),
              new Params(this.canvas2, this.loadAnimation2));
          try {
            promptAction.openCustomDialog(this.contentNode1, {
              isModal: false,
              offset: { dx: 0, dy: -120 },
              onDidDisappear: () => {
                this.animateItem1!.removeEventListener('DOMLoaded');
                lottie.destroy(this.animateName);
                this.animateItem1 = null;
              }
            });
            promptAction.openCustomDialog(this.contentNode2, {
              isModal: false,
              offset: { dx: 0, dy: 100 },
              onDidDisappear: () => {
                this.animateItem2!.removeEventListener('DOMLoaded');
                lottie.destroy(this.animateName2);
                this.animateItem2 = null;
              }
            });
          } catch (error) {
            let message = (error as BusinessError).message;
            let code = (error as BusinessError).code;
            console.error(`OpenCustomDialog args error code is ${code}, message is ${message}`);
          }
          ;
        });
      Button('closeLottieDialog1').onClick(() => {
        if (this.contentNode1) {
          console.info('关闭弹窗1');
          this.uiContext.getPromptAction().closeCustomDialog(this.contentNode1);
          this.isClose1 = true;
        }
      });
      Button('closeLottieDialog2').onClick(() => {
        if (this.contentNode2) {
          console.info('关闭弹窗2');
          this.uiContext.getPromptAction().closeCustomDialog(this.contentNode2);
          this.isClose2 = true;
        }
      });
    }
    .width('100%')
    .alignItems(HorizontalAlign.Center);
  }
}

【背景知识】

  • Canvas:提供画布组件,用于自定义绘制图形。
  • CanvasRenderingContext2D:使用CanvasRenderingContext2D在Canvas画布组件上进行绘制,绘制对象可以是矩形、文本、图片等。
  • lottie:适用于OpenHarmony的动画库,它可以解析json格式的动画,并在移动设备上进行本地渲染。

更多关于HarmonyOS鸿蒙Next中 Lottie 动画偶尔不展示、随机空白,请问如何解决?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


好的感谢,

可以提供多一点的信息,比如部分代码、效果。这样更清晰。

鸿蒙Next中Lottie动画异常可能由以下原因导致:

  1. 资源加载问题:检查动画JSON文件是否完整,网络或本地路径是否稳定。
  2. 内存与性能:动画复杂度过高或频繁创建/销毁可能导致渲染失败,需优化资源管理。
  3. 系统兼容性:确认Lottie库版本与鸿蒙Next系统版本匹配,避免API不兼容。
  4. 异步处理:确保动画加载完成后再执行播放逻辑,避免时序错误。

建议排查资源完整性、简化动画或更新依赖库版本。

在HarmonyOS Next中遇到Lottie动画随机空白或不展示的问题,通常与动画资源加载、组件生命周期或渲染流程有关。以下排查方向供参考:

  1. 检查资源加载状态
    确保动画JSON文件路径正确且资源完整。可在onPageShow或组件aboutToAppear中确认资源是否加载成功,避免因异步加载未完成时渲染导致的空白。

  2. 管理组件生命周期
    若切换动画时重新加载整个组件,需注意aboutToDisappearonPageHide中是否意外释放了动画资源。建议在组件内使用@State@Link管理动画数据,避免重复触发初始化。

  3. 控制动画实例重建
    使用LottieAnimation组件时,若src属性频繁变更,可能触发动画实例重建。可通过enableMerge属性尝试合并更新,或使用key标识动画版本,减少不必要的重建。

  4. 排查布局与渲染冲突
    空白但占位的情况可能与布局计算相关。检查动画容器的尺寸是否明确(避免AutoSize异常),并确认是否被其他组件覆盖。可尝试添加背景色辅助调试。

  5. 监控异步流程
    若动画依赖网络资源,需确保加载失败时有重试或降级逻辑。可监听LottieAnimationonFinishonFailure事件,记录异常信息。

若问题仍存,建议提供最小化复现代码片段,以便进一步定位。

回到顶部