AMP
  • 網站

scrollbound 效果的基本概念

簡介

amp-position-observer 搭配 amp-animation 是一個強大的建構區塊,可以處理各種使用案例,例如scrollbound 動畫視差效果轉場效果,當元素進入和離開可視區域時。

在本教學課程中,我們將詳細介紹其中一些使用案例。

設定

amp-position-observer 是一個功能性元件,可監控元素在可視區域內的位置 (當使用者捲動時),並發送 enterexitscroll:<Position In Viewport As a Percentage> 事件。

這些事件反過來可用於 playpauseseekamp-animation 定義的動畫時間軸,以建立 scrollbound 和基於可見性的效果。

<script async custom-element="amp-position-observer" src="https://cdn.ampproject.org/v0/amp-position-observer-0.1.js"></script>

amp-animation 是一個 UI 元件,依賴 Web Animations API 在 AMP 文件中定義和執行關鍵影格動畫。

<script async custom-element="amp-animation" src="https://cdn.ampproject.org/v0/amp-animation-0.1.js"></script>

樣式

這些範例使用的 CSS 包含在此處以供參考。

這些規則僅僅是使範例運作所必需的,但對於此處涵蓋的概念而言並非根本。

<style amp-custom>

  /*
   * Fidget Spinner styles
   */
  .fidget-spinner-scene {
    margin: 10px 20%;
  }

  /*
   * Card transition styles
   */
  .card {
    margin: 10%;
    position: relative;
  }
  .card-title {
    padding: 5%;
    padding-right: 40%;
    font-size: 50%;
    font-weight: bold;
    color: #FAFAFA;
    transform: translateX(-100%);
  }

  /*
   * Parallax window styles
   */
  .parallax-image-window {
    overflow: hidden;
  }
  .parallax-image-window amp-img {
    margin-bottom: -30%;
  }

  /*
   * Carousel transition styles
   */
  .carousel-component {
    margin-right: -60%;
    margin-left: 60%;
  }
  .carousel-parent {
    overflow: hidden;
  }
</style>

Scrollbound 動畫

讓我們建立一個指尖陀螺,當使用者捲動頁面時會旋轉。

此範例展示了結合 amp-position-observeramp-animation 背後的核心概念:當元素透過捲動在可視區域中移動時,能夠在關鍵影格動畫時間軸中推進。

我們的指尖陀螺場景是一個包含 imagediv。我們新增一個 amp-position-observer 元素作為場景的子項,以監控其在可視區域中的進度。讓我們仔細看看細節

  • on:scroll:當使用者捲動時,當場景的位置發生變化時,位置觀察器會觸發此事件。該事件提供一個百分比值 (0 到 1 之間的十進制值),表示場景在其透過可視區域的進度的開始和結束之間的位置。
  • spinAnimation.seekTo(percent=event.percent):我們將在下一步定義一個 amp-animation 來進行旋轉,這裡我們透過在 scroll 事件發生時在動畫上觸發 seekTo 動作來耦合 amp-position-observeramp-animation。這就是我們指定我們希望當場景透過捲動在可視區域中移動時,在動畫時間軸中推進的方式。
  • intersection-ratios:定義在 amp-position-observer 觸發其任何事件之前,場景應在可視區域中可見多少。在這裡,我們希望僅在指尖陀螺完全可見時才發生旋轉,因此我們將其設定為 1
<div class="fidget-spinner-scene">

  <amp-position-observer on="scroll:spinAnimation.seekTo(percent=event.percent)" intersection-ratios="1" layout="nodisplay">
  </amp-position-observer>

  <amp-img id="fidgetSpinnerImage" width="1024" height="1114" layout="responsive" src="/static/samples/img/fidget.png" alt="Picture of a fidget spinner"></amp-img>
</div>

現在我們需要定義動畫本身

在這種情況下相當簡單,我們希望 fidgetSpinnerImage 旋轉 360 度,因此我們只需將 "transform": "rotate(360deg)" 定義為最後一個 (也是唯一的) 關鍵影格。讓我們仔細看看細節

  • id="spinAnimation":我們需要為動畫指定一個 Id,以便我們可以從位置觀察器引用它。
  • "duration": "1"duration 的值在這種情況下無關緊要,因為我們透過捲動在時間軸中推進,因此我們只需將其設定為 1
  • "direction": "reverse":由於 iOS 中 Web Animations 存在錯誤,因此需要這樣做。
  • "animations":在這裡我們可以定義一個或多個基於關鍵影格的動畫。在我們的例子中,我們只需要一個。
  • "selector""#fidgetSpinnerImage" 是針對指尖陀螺進行動畫處理的選取器。
  • "keyframes": 我們定義 "transform": "rotate(360deg)" 作為最後一個 (也是唯一的) 關鍵影格。請注意,如果未提供第一個關鍵影格,amp-animation 會自動填寫。

amp-animation 還有許多其他功能,請參閱 API 參考文件以瞭解更多關於 amp-animations 的資訊。

<amp-animation id="spinAnimation" layout="nodisplay">
  <script type="application/json">
    {
      "duration": "1",
      "fill": "both",
      "direction": "reverse",
      "animations": [
        {
          "selector": "#fidgetSpinnerImage",
          "keyframes": [
            { "transform": "rotate(360deg)" }
          ]
        }
      ]
    }
  </script>
</amp-animation>

淡入和滑動轉場效果

現在我們已經學習了 amp-position-observeramp-animation 背後的基本核心概念,讓我們深入探討更多有創意的方式,將它們結合起來以建立有趣的轉場效果。

在此範例中,我們將時間限制和 scrollbound 轉場效果結合在一起,以建立一種效果,其中卡片的透明度與其在可視區域中可見的程度 (scrollbound) 相關聯,並且卡片的標題在卡片進入和離開可視區域時會動畫顯示進/出 (時間限制)。

我們的卡片場景僅由影像和覆蓋的標題組成。在這裡,我們定義了兩個具有不同 intersection-ratios 值的位置觀察器

  • 第一個將在使用者捲動時控制影像的透明度。
  • 第二個將在場景變得大部分可見 (80%) 時為標題執行時間限制的滑動動畫,並在場景稍微離開可視區域 (20%) 時再次「反向」執行。
有機、新鮮的番茄和義大利麵!
<div class="card ampstart-card">

  <amp-position-observer on="scroll:fadeTransition.seekTo(percent=event.percent)" intersection-ratios="0" layout="nodisplay">
  </amp-position-observer>

  <amp-position-observer on="enter:slideTransition.start; exit:slideTransition.start,slideTransition.reverse" intersection-ratios="0.8" layout="nodisplay">
  </amp-position-observer>

  <amp-fit-text layout="fill">
    <div class="card-title">
      Organic, fresh tomatoes and pasta!
    </div>
  </amp-fit-text>

  <amp-img id="cardImage" width="1280" height="898" layout="responsive" src="/static/samples/img/food.jpg" alt="Picture of food table."></amp-img>
</div>

讓我們定義 scrollbound 淡入/淡出轉場效果的關鍵影格。

我們以 #cardImage 為目標,並以影像在時間軸的前 40% 內獲得完全不透明度,並在時間軸的最後 40% 內開始淡出的方式定義關鍵影格。

請注意,由於控制此動畫的位置觀察器將 intersection-ratios 設定為 0,因此當使用者捲動 ViewportHeight + 2 * SceneHeight 像素量時,我們將遍歷完整時間軸。

<amp-animation id="fadeTransition" layout="nodisplay">
  <script type="application/json">
    {
      "duration": "1",
      "fill": "both",
      "direction": "reverse",
      "animations": [
        {
          "selector": "#cardImage",
          "keyframes": [
            { "opacity": "0.3", "offset": 0 },
            { "opacity": "1", "offset": 0.4 },
            { "opacity": "1", "offset": 0.6 },
            { "opacity": "0.3", "offset": 1 }
          ]
        }
      ]
    }
  </script>
</amp-animation>

對於標題的滑入/滑出效果,我們只需定義一個 500 毫秒的動畫,即可沿 X 軸移動標題。

當場景大部分可見/不可見時,此動畫將僅透過第二個位置觀察器觸發 (以正常或反向方向)。

<amp-animation id="slideTransition" layout="nodisplay">
  <script type="application/json">
    {
        "duration": "500ms",
        "fill": "both",
        "easing": "ease-out",
        "iterations": "1",
        "animations": [
          {
            "selector": ".card-title",
            "keyframes": [
              { "transform": "translateX(-100%)" },
              { "transform": "translateX(0)" }
            ]
          }
        ]
      }
  </script>
</amp-animation>

視差影像視窗

視差是另一種可以透過結合 amp-animationamp-position-observer 實現的效果。

視差通常涉及在使用者捲動時在 Y 軸上平移元素。

在這裡,我們定義了一個場景,其高度小於其內部影像的高度,當使用者捲動時,我們移動影像,從而在影像中建立視差視窗。

<div class="parallax-image-window">

  <amp-position-observer on="scroll:parallaxTransition.seekTo(percent=event.percent)" intersection-ratios="0" layout="nodisplay">
  </amp-position-observer>

  <amp-img id="parallaxImage" width="1280" height="873" layout="responsive" src="/static/samples/img/elephant.jpg" alt="Picture of an elephant"></amp-img>
</div>

動畫本身只是透過 "transform": "translateY(-30%)" 向上移動影像

<amp-animation id="parallaxTransition" layout="nodisplay">
  <script type="application/json">
    {
      "duration": "1",
      "fill": "both",
      "direction": "reverse",
      "animations": [
        {
          "selector": "#parallaxImage",
          "keyframes": [
            { "transform": "translateY(-30%)" }
          ]
        }
      ]
    }
  </script>
</amp-animation>

我們也可以將這些效果與其他 AMP 元件一起使用,例如 amp-carousel

在此範例中,我們有一個輪播,其中第一個項目被推向右側,當輪播變得可見時,它會彈回原位,提供輪播可水平捲動的視覺「提示」。

<div class="carousel-parent">
  <amp-carousel class="carousel-component" height="300" layout="fixed-height" type="carousel">

    <amp-position-observer on="enter:carouselTransition.start" intersection-ratios="0.8" layout="nodisplay">
    </amp-position-observer>

    <amp-img src="https://unsplash.it/800/600?image=1003" width="400" height="300" alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/800/600?image=1043" width="400" height="300" alt="another sample image"></amp-img>
    <amp-img src="https://unsplash.it/800/600?image=1032" width="400" height="300" alt="and another sample image"></amp-img>
  </amp-carousel>
</div>

在這裡,我們定義了時間限制動畫,延遲 200 毫秒,這將在 500 毫秒內將輪播滑動到左側。

此動畫將僅由位置觀察器觸發一次,如上所述。

<amp-animation id="carouselTransition" layout="nodisplay">
  <script type="application/json">
    {
      "duration": "500ms",
      "fill": "both",
      "easing": "ease-in",
      "delay": "200ms",
      "animations": [
        {
          "selector": ".carousel-component",
          "keyframes": [
            { "transform": "translateX(-60%)" }
          ]
        }
      ]
    }
  </script>
</amp-animation>
需要更多說明嗎?

如果此頁面上的說明未涵蓋您的所有問題,請隨時與其他 AMP 使用者聯繫,討論您的確切使用案例。

前往 Stack Overflow
未說明的特性?

AMP 專案強烈鼓勵您的參與和貢獻!我們希望您能成為我們開放原始碼社群的持續參與者,但我們也歡迎您針對您特別感興趣的問題做出一次性貢獻。

在 GitHub 上編輯範例