AMP

Wprowadzenie do złożonych animacji

W przypadku animacji, które nie mogą być obsługiwane przez dodawanie i usuwanie klas, AMP oferuje kilka specjalnych składników. Składniki te stosują zasady AMP do animacji: są szybkie, wydajne i zorientowane na użytkownika. AMP ogranicza właściwości CSS dozwolone wewnątrz ramek kluczowych, ale zapewnia korzyści takie, jak precyzyjne sterowanie, płynne animacje i zgodność z przeglądarkami bez dodatkowej pracy.

Jeśli chcesz ściśle kontrolować odtwarzanie, jak również precyzyjnie synchronizować wiele elementów animacji naraz, użyj składnika amp-animation.

Tworzenie podstawowej animacji AMP

Składnik amp-animation umożliwia stosowanie interfejsu API Web Animation w AMP.

Podstawowy składnik amp-animation to obiekt JSON utworzony z następujących głównych części:

<amp-animation layout="nodisplay" id="exampleAnimation">
<script type="application/json">
{
 "selector": "#elementID", //select the element to animate
 "duration": "1s", //timing property
 "iterations": 2, //timing property
 "fill": "both", //timing property
 "keyframes": {"opacity": 0, "transform": "scale(2)"} //keyframes
}
</script>
</amp-animation>
<!-- trigger -->
<button on="tap:exampleAnimation.start">

Pole selector

Podobnie jak CSS, składnik amp-animation łączy właściwości animacji z elementem poprzez zadeklarowanie nazwy znacznika elementu, klasy lub identyfikatora w polu "selector". Składnik animuje każdy element z zadeklarowaną nazwą typu znacznika lub nazwą klasy. Aby zapewnić animować pojedynczy element, użyj identyfikatora.

Właściwości synchronizacji

Właściwości synchronizacji sterują czasem trwania animacji, czasem jej odtwarzania oraz kierunkiem wykonywania ramek kluczowych.

Żadne właściwości synchronizacji nie są wymagane, ale animacja może nie działać, jeśli brakuje właściwości związanych z czasem i wyświetlaniem, takich jak duration i fill.

Ramki kluczowe

Chociaż CSS zezwala na płynną zmianę jednego stanu na drugi za pomocą przejść, musisz zadeklarować właściwości animacji jako ramki kluczowe, aby zaimplementować składnik amp-animation, które można wykorzystać do właściwości akcelerowanych przez GPU, które nie powodują powtórnego generowania układu i mogą animować w wątku narzędzia tworzenia kompozycji. Zapobiega to ingerencji animacji w AMP i proces renderowania przeglądarki.

Ramki kluczowe są albo definiowane bezpośrednio w składniku {amp-animation.

Wyzwalacz

Wyzwalacz uruchamia sekwencję animacji. Rozszerzenie amp-animation jest uruchamiane, gdy sekcja <body> staje się widoczna na stronie lub poprzez połączenie go z działaniem lub zdarzeniem AMP.

Wyzwalanie przy widoczności sekcji <body> jest użyteczne, gdy animacja powinna zostać uruchomiona od razu po załadowaniu strony, ponieważ pojawia się „nad treścią” lub w pierwszym okienku ekranu na stronie. Animacje są uruchamiane przez widoczność, dzięki dodaniu do składnika atrybutu trigger="visibility".

<amp-animation layout="nodisplay"
    trigger="visibility">
  ...
</amp-animation>

Animacje łączą się z działaniem lub zdarzeniem dzięki przypisaniu składnikowi </a>amp-animation właściwości id i powiązaniu tego id z żądanym wyzwalaczem zdarzenia, takim jak dotknięcie przycisku.

<amp-animation layout="nodisplay" id="exampleAnimation">
  ...
</amp-animation>

<button on="tap:exampleAnimation.start">

Tworzenie złożonych animacji

Utworzenie animacji w składniku amp-animation umożliwia szczegółowe sterowanie, wykraczające poza uruchamianie i zatrzymywanie animacji: można również wstrzymywać, odwracać i kierować do określonego punktu. Można nawet łączyć wiele animacji w łańcuchy i animować elementy w sekwencji.

Cele cząstkowe

Elementy tego samego znacznika lub klasy mogą mieć określone właściwości synchronizacji i zastępować wartości zmiennych zdefiniowanych w animacji najwyższego poziomu.

<body>
  <h1>Hello World!</h1>
  <h1>Hello World!</h1>
  <h1 id="helloMe">Hello World!</h1>
  <h1>Hello World!</h1>
  <amp-animation layout="nodisplay" id="animateThis">
    <script type="application/json">
      {
        "selector": "h1",
        "duration": "3s",
        "fill": "both",
        "keyframes": [
          {"transform": "translateX(0px)"},
          {"transform": "translateX(50%)"}
        ],
        "subtargets": [
          {
            "index": 1,
            "duration": "1s"
          },
          {
            "selector": "#helloMe",
            "direction": "reverse",
            "duration": "5s"
          }
        ]
      }
    </script>
  </amp-animation>
  <button on="tap:animateThis.start">start</button>
</body>
Otwórz ten fragment kodu w placu zabaw

Łańcuchy animacji

Wiele animacji można połączyć, aby utworzyć dużą sekwencję. Można tworzyć efekty czasowe, takie jak nakładki na film, wpisując animacje w tablicy animations w składniku amp-anmation.

<amp-animation id="overlaysAnim" layout="nodisplay">
  <script type="application/json">
    {
      "duration": "3s",
      "fill": "both",
      "animations": [{
          "selector": ".one",
          "keyframes": [{
              "opacity": "1",
              "offset": 0
            },
            {
              "opacity": "1",
              "offset": 0.04
            },
            {
              "opacity": "0",
              "offset": 0.0401
            },
            {
              "opacity": "0",
              "offset": 1
            }
          ]
        },
      ]
    }
  </script>
</amp-animation>

Ta konfiguracja powoduje odtwarzanie każdej animacji w sekwencji przez 3 sekundy.

W przypadku większych animacji, animacje w tablicy animations mogą odwoływać się do innych składników amp-animation.

<amp-animation id="addEnergy" layout="nodisplay">
  <script type="application/json">
  {
    "duration": "0.3s",
    "fill": "both",
    "direction": "alternate",
    "animations": [
      {
        "selector": "#energy",
        "keyframes": [
          {"transform": "scaleX(calc(num(width('#energy'))/10))"},
          {"transform": "scaleX(calc(num(width('#energy'))/10 + 3))"}
        ]
      },
      {
        "animation": "atomExcite"
      }
    ]
  }
  </script>
</amp-animation>
<amp-animation id="atomExcite" layout="nodisplay" trigger="visibility">
<script type="application/json">
  {
    "duration": "0.3s",
    "iterations": "2",
    "fill": "both",
    "direction": "alternate",
    "animations": [
      {
        "selector": ".atom",
        "keyframes": {
          "transform": "translate(20vw)"
        }
      }
    ]
  }
  </script>
</amp-animation>

Animowanie nieznanej liczby elementów

Używając wyrażeń [`var(/content/amp-dev/documentation/components/reference/amp-animation.md#css-extensions), można pisać złożone, synchronizowane animacje, które działają z dowolną liczbą elementów. Pozwala to na łatwe i płynne animowanie danych dynamicznych i generowanych przez użytkownika.

<head>
  <script
    async
    custom-element="amp-animation"
    src="https://cdn.ampproject.org/v0/amp-animation-0.1.js"
  ></script>
  <style amp-custom>
    .parent {
      perspective: 1000px;
      transform-style: preserve-3d;
      position: relative;
      margin: 10px;
      width: 239px;
      height: 335px;
    }
    .card {
      transform-origin: left;
      height: 50%;
      width: 50%;
    }
  </style>
</head>
<body>
  <amp-animation layout="nodisplay" id="cardAdmin">
    <script type="application/json">
      {
        "selector": ".card",
        "--duration": "2s",
        "duration": "var(--duration)",
        "delay": "calc((length() - index() - 1) * var(--duration))",
        "easing": "ease-in",
        "iterations": "1",
        "fill": "both",
        "keyframes": [
          {"transform": "translate3d(0px, 0px, 0px)"},
          {"transform": "translate3d(50%, 0px, 100px)"},
          {"transform": "translate3d(110%, 0px, 0px) rotateY(-20deg)"},
          {"transform": "translate3d(50%, 0px, -100px)"},
          {"transform": "translate3d(0px, 0px, -1px)"}
        ]
      }
    </script>
  </amp-animation>
  <div class="parent" on="tap:cardAdmin.start" tabindex="none" role="animation">
    <amp-img
      class="card"
      src="https://upload.wikimedia.org/wikipedia/commons/7/70/3C.svg"
      layout="fill"
    ></amp-img>
    <amp-img
      class="card"
      src="https://upload.wikimedia.org/wikipedia/commons/3/3a/3H.svg"
      layout="fill"
    ></amp-img>
    <amp-img
      class="card"
      src="https://upload.wikimedia.org/wikipedia/commons/e/e1/KC.svg"
      layout="fill"
    ></amp-img>
  </div>
</body>
Otwórz ten fragment kodu w placu zabaw

Ten przykład działa poprzez:

  • Zadeklarowanie zmiennej duration i nadanie jej wartości dwóch sekund.
  • Ustawienie właściwości duration na wartość zmiennej --duration.
  • Obliczenie opóźnienia zastosowanego do każdego elementu, który spełnia kryteria selektora .card. 1. [Rozszerzenie length(/content/amp-dev/documentation/components/reference/amp-animation.md#css-length()-extension) oblicza liczbę wybranych elementów.card2. Następnie length odejmuje od każdego elementu.cardwartość [index(/content/amp-dev/documentation/components/reference/amp-animation.md#css-index()-extension) 3. Otrzymana wartość jest mnożona przez wartość zmiennej--duration` 4. Końcowa wartość w sekundach jest stosowana do opóźnienia tego elementu.
  • Animacja jest stosowana do każdego elementu z osobna, tak aby elementy cards były odtwarzane jeden po drugim, a nie wszystkie naraz.

Otwórz animację w placu zabaw AMP i dodaj więcej elementów amp-img, aby przetestować ten sposób działania.

Wyglądają wspaniale, wszędzie.

Animacje mogą zawierać warunki (/content/amp-dev/documentation/components/reference/amp-animation.md#supports-condition) w instrukcji switch.

<head>
  <style amp-custom>
    .drop {
      width: 20px;
      height: 20px;
      background: blue;
      margin-top: 1em;
      border-radius: 50%;
    }
    .right {
      position: absolute;
      right: 0;
      background: red;
    }
  </style>
  <script
    async
    custom-element="amp-animation"
    src="https://cdn.ampproject.org/v0/amp-animation-0.1.js"
  ></script>
</head>
<body>
  <amp-animation id="mediaAnimation" layout="nodisplay">
    <script type="application/json">
      {
        "duration": "1s",
        "iterations": "4",
        "fill": "both",
        "direction": "alternate",
        "animations": [
          {
            "media": "(min-width: 300px)",
            "selector": ".drop",
            "keyframes": {
              "transform": "translate(100vw)"
            }
          },
          {
            "media": "(max-width: 300px)",
            "selector": ".drop",
            "keyframes": {
              "transform": "translate(50vw)"
            }
          },
          {
            "media": "(min-width: 300px)",
            "selector": ".right",
            "keyframes": {
              "transform": "translate(-100vw)"
            }
          },
          {
            "media": "(max-width: 300px)",
            "selector": ".right",
            "keyframes": {
              "transform": "translate(-50vw)"
            }
          }
        ]
      }
    </script>
  </amp-animation>

  <div class="rain">
    <div class="drop"></div>
    <div class="drop right"></div>
    <div class="drop"></div>
    <div class="drop right"></div>
    <div class="drop"></div>
    <div class="drop right"></div>
    <div class="drop"></div>
    <div class="drop right"></div>
  </div>
  <button on="tap:mediaAnimation.start">Start</button>
</body>
Otwórz ten fragment kodu w placu zabaw