Technologie & KIEinblickeÜber unsKarriere Gespräch buchen

Blog-Artikel

Lottie-Animationen optimieren: Best Practices

Lottie-Animationen optimieren: lottie-web in React und Next.js performant einsetzen – mit Lazy Loading, useEffect, useMemo und Code-Splitting.

Autor

Incresco Team

Incresco Team

Incresco Redaktion

Mit der Bibliothek lottie-web lassen sich Lottie-Animationen unkompliziert in Webanwendungen einbinden. Lottie verarbeitet aus Adobe After Effects exportierte Animationen und rendert sie nativ auf mobilen Plattformen sowie im Web.

Mit nur wenigen Codezeilen können Sie über lottie-web hochwertige Animationen in Ihre Webanwendung integrieren. Installieren Sie das Paket zunächst mit folgendem Befehl im Terminal:

npm install lottie-web

Nach der Installation importieren Sie lottie-web in Ihren JavaScript-Code. Anschließend laden Sie die gewünschte Animation mit der Funktion loadAnimation. So kann die Einbindung in einer Webanwendung aussehen:

import lottie from 'lottie-web';

lottie.loadAnimation({
    container: document.getElementById('animation-container'),
    renderer: 'svg',
    loop: true,
    autoplay: true,
    path: '/path/to/animation.json',
});

In diesem Beispiel erhält loadAnimation ein Optionsobjekt. Die Eigenschaft container legt das DOM-Element fest, in dem die Animation gerendert wird. Über renderer wählen Sie den Renderer – entweder svg oder canvas. path verweist auf die JSON-Datei mit den Animationsdaten. Die Eigenschaften loop und autoplay steuern die Wiedergabe.

Wenn Sie bisher die Lottie-Komponente aus lottie-react verwendet haben, ersetzen Sie diese durch das DOM-Element, das die Animation aufnehmen soll. Dafür eignet sich beispielsweise ein div-Element:

import React from 'react';

const MyComponent = () => {
    return (
        <div id="animation-container" />
    );
};

Danach können Sie die Animation über lottie.loadAnimation innerhalb der Lebenszykluslogik der Komponente laden, etwa mit componentDidMount oder useEffect. Das folgende Beispiel zeigt die Umsetzung:

import React, { useEffect } from 'react';
import lottie from 'lottie-web';

const MyComponent = () => {
    useEffect(() => {
        lottie.loadAnimation({
            container: document.getElementById('animation-container'),
            renderer: 'svg',
            loop: true,
            autoplay: true,
            path: '/path/to/animation.json',
        });
    }, []);

    return (
        <div id="animation-container” />
    );
};

Lottie-Animationen in React und Next.js optimieren

Mit den folgenden Maßnahmen verbessern Sie die Performance von lottie-react in einer Next.js-Anwendung:

  • Rendering mit useEffect steuern: Mit dem useEffect-Hook legen Sie fest, wann die Animation gerendert und wann sie wieder entfernt wird. Dadurch lassen sich unnötige Rendering-Vorgänge reduzieren.

  • Rendering mit useMemo optimieren: Der useMemo-Hook verhindert unnötige Neuberechnungen, indem die Animation nur dann neu gerendert wird, wenn sich Animationsdaten oder Optionen ändern.

  • Einen useLazyLottie-Hook verwenden: Mit einem eigenen useLazyLottie-Hook können Sie eine Lottie-Animation verzögert laden und ihr Rendering über eine einfache Hook-API steuern. Das ist eine praktische Möglichkeit, Lottie-Animationen in Next.js performanter einzusetzen.

Lottie-Rendering mit useEffect steuern

Der React-Hook useEffect ermöglicht es, Seiteneffekte in funktionalen Komponenten auszuführen. Bei einer Lottie-Animation können Sie damit steuern, wann die Animation geladen und wieder entfernt wird.

Importieren Sie dafür useEffect aus React und definieren Sie eine Funktion, die die Animation lädt und bei Bedarf bereinigt. So kann die Umsetzung mit lottie-web aussehen:

import React, { useRef, useEffect } from 'react';
import lottie from 'lottie-web';

const MyComponent = () => {
    const containerRef = useRef(null);

    useEffect(() => {
        const animation = lottie.loadAnimation({
            container: document.getElementById('animation-container'),
            renderer: 'svg',
            loop: true,
            autoplay: true,
            path: '/path/to/animation.json',
        });

        return () => {
            animation.destroy();
        };
    }, []);

    return (
        <div id="animation-container" />
    );
};

In diesem Beispiel lädt die in useEffect definierte Funktion die Lottie-Animation, sobald die Komponente eingebunden wird. Die Funktion gibt eine Cleanup-Funktion zurück, die beim Entfernen der Komponente aufgerufen wird und die Animation mit destroy beendet. So wird die Animation nur dann geladen und gerendert, wenn sie tatsächlich benötigt wird – das kann die Performance der Anwendung verbessern.

Den Lottie-Container mit useRef referenzieren

Um mit lottie-web auf das Container-Element einer Lottie-Animation zu verweisen, erstellen Sie über den useRef-Hook eine Referenz und übergeben diese als container-Option an loadAnimation. In einer React-Komponente kann das folgendermaßen aussehen:

import React, { useRef, useEffect } from 'react';
import lottie from 'lottie-web';

const MyComponent = () => {
    const containerRef = useRef(null);

    useEffect(() => {
        const animation = lottie.loadAnimation({
            container: containerRef.current,
            renderer: 'svg',
            loop: true,
            autoplay: true,
            path: '/path/to/animation.json',
        });

        return () => {
            animation.destroy();
        };
    }, []);

    return (
        <div ref={containerRef} />
    );
};

Hier erzeugt useRef eine veränderbare Referenz auf das Container-Element und speichert sie in containerRef. Die Referenz wird dem div über die Eigenschaft ref zugewiesen, sodass der Code der Komponente auf das Element zugreifen kann. useEffect definiert die Funktion, die die Lottie-Animation beim Einbinden der Komponente lädt. Dabei wird containerRef.current als container-Option an loadAnimation übergeben und bestimmt so das DOM-Element für das Rendering.

Lottie-Animationen mit useMemo optimieren

Der React-Hook useMemo kann das Rendering einer Komponente optimieren, indem er das Ergebnis einer aufwendigen Berechnung zwischenspeichert. Bei lottie-web lässt sich damit das an loadAnimation übergebene Optionsobjekt memoizieren.

Importieren Sie dazu useMemo und useEffect aus React. Anschließend definieren Sie die Optionen und laden die Animation in einer React-Komponente wie folgt:

import React, { useMemo, useEffect } from 'react';
import lottie from 'lottie-web';

const MyComponent = () => {
    const containerRef = useRef(null);
    const options = useMemo(() => {
        return {
            container: containerRef.current,
            renderer: 'svg',
            loop: true,
            autoplay: true,
            path: '/path/to/animation.json',
        };
    }, []);

    useEffect(() => {
        const animation = lottie.loadAnimation(options);

        return () => {
            animation.destroy();
        };
    }, [options]);

    return (
        <div ref={containerRef} />
    );
};

Lazy Loading für Lottie-Animationen mit eigenem useLazyLottie-Hook

useLazyLottie ist ein benutzerdefinierter Hook, mit dem Sie das Lazy Loading einer Lottie-Animation in einer funktionalen Komponente umsetzen können. Er gehört weder zu lottie-react noch zu lottie-web, lässt sich aber als eigener Hook entwickeln. Dafür werden useEffect und useRef kombiniert, um eine Animation erst bei Bedarf zu laden.

Das folgende Beispiel zeigt eine mögliche Implementierung von useLazyLottie mit lottie-web:

import { useEffect, useRef } from 'react';
import lottie from 'lottie-web';

const useLazyLottie = (options) => {
  const containerRef = useRef(null);
  const animationRef = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver((entries) => {
      if (entries[0].isIntersecting) {
        const animation = lottie.loadAnimation({
          ...options,
          container: containerRef.current,
        });
        animationRef.current = animation;
        observer.disconnect();
      }
    });
    observer.observe(containerRef.current);

    return () => {
      if (animationRef.current) {
        animationRef.current.destroy();
      }
     	observer.disconnect();
    };
  }, [options]);

  return { containerRef, animationRef };
};

Der useLazyLottie-Hook nutzt in diesem Beispiel die IntersectionObserver-API, um zu erkennen, wann die Animation im sichtbaren Bereich erscheint. Sobald sie sichtbar wird, lädt der Hook die Animation über lottie-web und speichert eine Referenz auf die Animationsinstanz in animationRef. Außerdem gibt der Hook containerRef und animationRef zurück. Damit können Sie im Komponentencode sowohl auf das Container-Element als auch auf die Animationsinstanz zugreifen.

Optionen übergeben Sie an useLazyLottie in Form eines Optionsobjekts. Dieses sollte alle Einstellungen enthalten, die später an die Funktion loadAnimation von lottie-web weitergereicht werden sollen.

So verwenden Sie den useLazyLottie-Hook mit einem Optionsobjekt:

import React from 'react';
import { useLazyLottie } from './useLazyLottie';

const MyComponent = () => {
  const { containerRef, animationRef } = useLazyLottie({
    renderer: 'svg',
    loop: true,
    autoplay: true,
    path: '/path/to/animation.json',
  });

  return (
    <div ref={containerRef} />
  );
};

In diesem Beispiel wird useLazyLottie mit einem Optionsobjekt aufgerufen, das die Eigenschaften renderer, loop, autoplay und path für loadAnimation enthält. Sobald die Animation im sichtbaren Bereich erscheint, übergibt der Hook diese Optionen an die Funktion.

Lottie mit Code-Splitting und dynamischem Import optimieren

Für Code-Splitting mit lottie-web in einer Next.js-Anwendung können Sie die von Next.js bereitgestellte Funktion dynamic verwenden. Damit lassen sich sowohl die Bibliothek lottie-web als auch die Animationsdaten verzögert laden.

Das folgende Beispiel zeigt Code-Splitting mit lottie-web und Next.js:

import React, { useEffect, useRef } from 'react';
import dynamic from 'next/dynamic';

const Lottie = dynamic(() => import('lottie-web'), { ssr: false });

const MyComponent = () => {
  const containerRef = useRef(null);

  useEffect(() => {
    const animation = lottie.loadAnimation({
      container: containerRef.current,
      renderer: 'svg',
      loop: true,
      autoplay: true,
      path: '/path/to/animation.json',
    });

    return () => {
      animation.destroy();
    };
  }, []);

  return (
    <div ref={containerRef} />
  );
};

export default MyComponent;

In diesem Beispiel lädt dynamic die Bibliothek lottie-web und die Animationsdaten erst bei Bedarf. Die Option ssr ist auf false gesetzt, damit die Bibliothek beim serverseitigen Rendering nicht auf dem Server geladen wird. Anschließend lädt useEffect die Animation beim Einbinden der Komponente. Über containerRef wird das Container-Element für die Animation referenziert.

Bereit, das Experimentieren zu beenden und
in den produktiven Betrieb zu starten?