利用 AEM Headless 的最佳化影像 images-with-aem-headless

影像是開發豐富、極具吸引力的AEM Headless體驗的重要方面。 AEM Headless支援影像資產的管理及其最佳化傳送。

AEM Headless內容模型中使用的內容片段,通常會參照要在Headless體驗中顯示的影像資產。 AEM的GraphQL查詢可以寫入,以根據影像參考來源提供URL給影像。

ImageRef型別有四個URL選項供內容參照使用:

  • _path是AEM中的參考路徑,不包含AEM來源(主機名稱)
  • _dynamicUrl是影像資產網頁最佳化傳遞的URL。
    • _dynamicUrl不包含AEM來源,因此網域(AEM Author或AEM Publish服務)必須由使用者端應用程式提供。
  • _authorUrl是AEM作者上影像資產的完整URL
    • AEM Author可用於提供Headless應用程式的預覽體驗。
  • _publishUrl是AEM Publish上影像資產的完整URL
    • AEM Publish通常是Headless應用程式的生產部署顯示影像的位置。

_dynamicUrl是建議用於影像資產傳送的URL,應儘可能取代使用_path_authorUrl_publishUrl

AEM as a Cloud Service
AEM AS A CLOUD SERVICE RDE
AEM SDK
AEM 6.5
支援Web最佳化的影像?

內容片段模型

確定包含影像參考的內容片段欄位是​ 內容參考 ​資料型別。

內容片段模型中檢閱欄位型別,方法是選取欄位並檢查右側的​ 屬性 ​索引標籤。

內容片段模型參考影像

GraphQL持續查詢

在GraphQL查詢中,傳回欄位作為ImageRef型別,並要求_dynamicUrl欄位。 例如,在WKND網站專案中查詢冒險並在其primaryImage欄位中包含影像資產參考的影像URL,可以使用定義如下wknd-shared/adventure-image-by-path的新持續查詢:

query($path: String!, $imageFormat: AssetTransformFormat=JPG, $imageSeoName: String, $imageWidth: Int, $imageQuality: Int) {
  adventureByPath(
    _path: $path
    _assetTransform: {
      format: $imageFormat
      width: $imageWidth
      quality: $imageQuality
      preferWebp: true
    }
  ) {
    item {
      _path
      title
      primaryImage {
        ... on ImageRef {
          _dynamicUrl
        }
      }
    }
  }
}

查詢變數

{
  "path": "/content/dam/wknd-shared/en/adventures/bali-surf-camp/bali-surf-camp",
  "imageFormat": "JPG",
  "imageWidth": 1000,
}

_path篩選器中使用的$path變數需要內容片段的完整路徑(例如/content/dam/wknd-shared/en/adventures/bali-surf-camp/bali-surf-camp)。

_assetTransform定義如何建構_dynamicUrl以最佳化提供的影像轉譯。 您也可以變更URL的查詢引數,在使用者端上調整Web最佳化的影像URL。

GraphQL引數
說明
必填
GraphQL變數值
format
影像資產的格式。
GIFPNGPNG8JPGPJPGBJPGWEBPWEBPLLWEBPLY
seoName
URL中的檔案區段名稱。 若未提供,則會使用影像資產名稱。
英數、-_
crop
裁切影格從影像中取出,必須在影像大小範圍內
正整數,定義原始影像尺寸範圍內的裁切區域
size
輸出影像的大小(高度和寬度),以畫素為單位。
正整數
rotation
影像的旋轉,以度為單位。
R90, R180, R270
flip
翻轉影像。
HORIZONTAL, VERTICAL, HORIZONTAL_AND_VERTICAL
quality
影像品質,以原始品質的百分比表示。
1-100
width
輸出影像的寬度(畫素)。 提供size時,會忽略width
正整數
preferWebP
如果true和AEM在瀏覽器支援的情況下提供WebP,則無論format為何。
truefalse

GraphQL回應

產生的JSON回應包含要求的欄位,其中包含影像資產的網頁最佳化URL。

{
  "data": {
    "adventureByPath": {
      "item": {
        "_path": "/content/dam/wknd-shared/en/adventures/bali-surf-camp/bali-surf-camp",
        "title": "Bali Surf Camp",
        "primaryImage": {
          "_dynamicUrl": "/adobe/dynamicmedia/deliver/dm-aid--a38886f7-4537-4791-aa20-3f6ef0ac3fcd/adobestock_175749320.jpg?preferwebp=true&width=1000&quality=80"
        }
      }
    }
  }
}

若要載入應用程式中參照影像的網頁最佳化影像,請使用primaryImage_dynamicUrl做為影像的來源URL。

在React中,從AEM Publish顯示網頁最佳化影像的外觀如下:

// The AEM host is usually read from a environment variable of the SPA.
const AEM_HOST = "https://publish-p123-e456.adobeaemcloud.com";
...
let dynamicUrl = AEM_HOST + data.adventureByPath.item.primaryImage._dynamicUrl;
...
<img src={dynamicUrl} alt={data.adventureByPath.item.title}/>

請記住,_dynamicUrl不包含AEM網域,因此您必須提供所要的原點以供影像URL解析。

回應式URL

上述範例顯示使用單一大小的影像,不過在網頁體驗中,通常需要回應式影像集。 可以使用img srcsets圖片元素實作回應式影像。 下列程式碼片段顯示如何使用_dynamicUrl作為基底。 width是URL引數,您可以將其附加至_dynamicUrl以支援不同的回應式檢視。

// The AEM host is usually read from a environment variable of the SPA.
const AEM_HOST = "https://publish-p123-e456.adobeaemcloud.com";
...
// Read the data from GraphQL response
let dynamicUrl = AEM_HOST + data.adventureByPath.item.primaryImage._dynamicUrl;
let alt = data.adventureByPath.item.title;
...
{/*-- Example img srcset --*/}
document.body.innerHTML=`<img>
    alt="${alt}"
    src="${dynamicUrl}&width=1000}"
    srcset="`
      ${dynamicUrl}&width=1000 1000w,
      ${dynamicUrl}&width=1600 1600w,
      ${dynamicUrl}&width=2000 2000w,
      `"
    sizes="calc(100vw - 10rem)"/>`;
...
{/*-- Example picture --*/}
document.body.innerHTML=`<picture>
      <source srcset="${dynamicUrl}&width=2600" media="(min-width: 2001px)"/>
      <source srcset="${dynamicUrl}&width=2000" media="(min-width: 1000px)"/>
      <img src="${dynamicUrl}&width=400" alt="${alt}"/>
    </picture>`;

React範例

讓我們建立簡易的React應用程式,顯示遵循回應式影像模式的網頁最佳化影像。 回應式影像的主要模式有兩種:

具有srcset的Img元素

具有srcset的Img元素與sizes屬性搭配使用,為不同的熒幕大小提供不同的影像資產。 針對不同的熒幕大小提供不同的影像資產時,影像資料集相當實用。

圖片元素

圖片元素與多個source元素搭配使用,為不同的熒幕大小提供不同的影像資產。 為不同的熒幕大小提供不同的影像轉譯時,圖片元素相當實用。

範常式式碼

這個簡單的React應用程式使用AEM Headless SDK查詢AEM Headless API以取得Adventure內容,並使用具有srcset🔗picture element的img元素來顯示網頁最佳化的影像。 srcsetsources使用自訂setParams函式,將Web最佳化傳遞查詢引數附加至影像的_dynamicUrl,因此請變更根據網頁使用者端需求傳遞的影像轉譯。

在使用AEM Headless SDK🔗的自訂React勾點useAdventureByPath中執行針對AEM的查詢。

// src/App.js

import "./App.css";
import { useAdventureByPath } from './api/persistedQueries'

const AEM_HOST = process.env.AEM_HOST;

function App() {

  /**
   * Update the dynamic URL with client-specific query parameters
   * @param {*} imageUrl the image URL
   * @param {*} params the AEM web-optimized image query parameters
   * @returns the dynamic URL with the query parameters
   */
  function setOptimizedImageUrlParams(imageUrl, params) {
    let url = new URL(imageUrl);
    Object.keys(params).forEach(key => {
      url.searchParams.set(key, params[key]);
    });
    return url.toString();
  }

  // Get data from AEM using GraphQL persisted query as defined above
  // The details of defining a React useEffect hook are explored in How to > AEM Headless SDK
  // The 2nd parameter define the base GraphQL query parameters used to request the web-optimized image
  let { data, error } = useAdventureByPath(
        "/content/dam/wknd-shared/en/adventures/bali-surf-camp/bali-surf-camp",
        { imageFormat: "JPG" }
      );

  // Wait for AEM Headless APIs to provide data
  if (!data) { return <></> }

  const alt = data.adventureByPath.item.title;
  const imageUrl =  AEM_HOST + data.adventureByPath.item.primaryImage._dynamicUrl;

  return (
    <div className="app">

      <h1>Web-optimized images</h1>

      {/* Render the web-optimized image img with srcset for the Adventure Primary Image */}
      <h2>Img srcset</h2>

      <img
        alt={alt}
        src={setOptimizedImageUrlParams(imageUrl, { width: 1000 })}
        srcSet={
            `${setOptimizedImageUrlParams(imageUrl, { width: 1000 })} 1000w,
             ${setOptimizedImageUrlParams(imageUrl, { width: 1600 })} 1600w,
             ${setOptimizedImageUrlParams(imageUrl, { width: 2000 })} 2000w`
        }
        sizes="calc(100vw - 10rem)"/>

       {/* Render the web-optimized picture for the Adventure Primary Image */}
        <h2>Picture element</h2>

        <picture>
          {/* When viewport width is greater than 2001px */}
          <source srcSet={setOptimizedImageUrlParams(imageUrl, { width : 2600 })} media="(min-width: 2001px)"/>
          {/* When viewport width is between 1000px and 2000px */}
          <source srcSet={setOptimizedImageUrlParams(imageUrl, { width : 2000})} media="(min-width: 1000px)"/>
          {/* When viewport width is less than 799px */}
          <img src={setOptimizedImageUrlParams(imageUrl, { width : 400, crop: "550,300,400,400" })} alt={alt}/>
        </picture>
    </div>
  );
}

export default App;
recommendation-more-help
e25b6834-e87f-4ff3-ba56-4cd16cdfdec4