iT邦幫忙

2023 iThome 鐵人賽

DAY 12
0
Mobile Development

30天React Native之旅:從入門到活用系列 第 12

Day 12:Image組件的使用與技巧

  • 分享至 

  • xImage
  •  

圖片加載方式

首先,讓我們了解Image組件的四種加載方式:

  1. 靜態圖片:本地圖片。
    由於這些圖片已整合於應用程式包中,加載速度極快,性能很好。另外也建議對圖片都進行壓縮,以降低整體應用包的大小。

    <Image source={require('./my-icon.png')} />
    
  2. 網路圖片: 動態加載的圖片,通常是透過網路請求去拿。

    與靜態圖片不同,網路圖片一定要給其寬高。這是因為圖片下載前,React Native無法得知圖片寬高,所以會將圖片寬高預設為0,若不指定寬高,圖片將無法正確顯示。

    <Image source={{uri: 'https://reactjs.org/logo-og.png'}}
           style={{width: 400, height: 400}} />
    

    要注意的是,這裡要使用uri而非較常見的url。而且有個雷點,如果打成url,在iOS上能正常顯示,但是Android不行。所以如果在開發過程中只測試了iOS,可能會導致最後上線Android出現問題。

  3. 混合圖片: 指的是將圖片放在原生應用的資料夾中 (Xcode 的 asset 、 Android 的 drawable )。
    IOS

    <Image
      source={{ uri: 'app_icon' }}
      style={{ width: 40, height: 40 }}
    />
    

    Android

    <Image
      source={{ uri: 'asset:/app_icon.png' }}
      style={{ width: 40, height: 40 }}
    />
    

    這種做法在混合開發的情境中比較會出現,也就是專案是一部分React Native,一部分原生。

    利用這種方法可以讓圖片在同一位置,有助於節省資源。但缺點是React Native團隊與原生團隊之間的溝通成本會增加,可能需要更多的協調和調整。此外,兩者的更新和迭代速度可能不同,容易導致一些版本差異問題。是否要用這種方式,端看你或你的團隊怎麼權衡圖片複用效益和溝通、維護成本。

  4. Base64 圖片

    Base64 是將二進制資料轉換成由 64 個可見字符組成的字串的編碼方式。Base64 圖片就是將圖片以 Base64 格式編碼。

    <Image source={{ uri: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAAAAAAAD' }} />
    

    如所見,Base64 圖片並非一般的圖片地址,而是一長串由字母、數字和符號組成的字串。一般我們所見的圖片檔案,如 .jpg、.png,都是以二進制格式存在的。但當圖片進行 Base64 編碼後,它會轉變成一段由字母、數字和符號組成的字串。

    它的優點在於,Base64 編碼的圖片解析速度快,能迅速展示圖像。缺點是,最終打包後 Base64 圖片存在 Bundle 文件中,會導致Bundle體積變大,進而影響到Bundle下載速度,可能會拖慢 React Native 頁面的加載速度。

    通常建議只在體積較小的圖片上使用。

  • 小知識
    • 為什麼是uri,而不是url呢?
      URI (Uniform Resource Identifier) 和 URL (Uniform Resource Locator)其實有不同的含義,URI是一個更廣泛的概念,可以說URL只是URI的一個子集。

      在前面的例子,source={{ uri: 'app_icon' }} 中,app_icon 只是一個圖片名稱(URN),也並非URL。因此,React Native 選擇使用uri來表示滿合理的,其涵蓋的範圍較廣。

    • 為何不在所有情況都自動指定圖片尺寸?
      前面有提到,網路圖片在 React Native 中必須明確指定寬高。不過有Web開發經驗的開發者應該知道,在Web中,如果不給網路圖片指定寬高,圖片還是能正常顯示。瀏覽器處理時會先給0x0,然後圖片下載完後再依實際圖片寬高渲染圖片。

      那麼,為什麼 React Native 不選擇這種方式,這樣不是更方便嗎?

      這是個好問題,在React Native 官網也有特別提到,若用瀏覽器那種方式,圖片加載過程中容易出現頁面跳動。所謂頁面跳動,大家應該有經驗,有時候你想點某個按鈕,結果點下去時頁面跳了一下 導致你點到了別的地方, 這樣的使用體驗顯然不佳。React Native 想要避免這個問題,所以要求網路圖片要明確指定寬高,確保更穩定,也是一種是以用戶體驗為優先的設計。

實戰技巧與問題

  • 圖片預加載
    有時候我們希望將網路圖片先下載下來,之後用戶看到時就是會從緩存加載的圖片,圖片展示速度會快很多。我們可以用Image的prefetch方法來達成

    useEffect(() => {
        Image.prefetch('https://example.com/path/to/image.jpg');
    }, []);
    
  • 獲取圖片寬高
    使用Image.getSize()

    import { Image } from 'react-native'
    
    Image.getSize(imageUrl,(width,height)=>{ 
        console.log('寬度:',width,'高度:',height)
    })
    
  • 圖片增加模糊濾鏡
    React Native已經幫我們做好了,只要加上blurRadius屬性即可。
    blurRadius接受一個數字,代表模糊的程度。數值越高,模糊效果越強。

    <Image
      source={{ uri: 'https://example.com/my-image.jpg' }}
      style={{ width: 100, height: 100 }}
      blurRadius={10}
    />
    
  • 用神奇的tintColor改變圖片顏色
    依不同狀態改變icon顏色的需求是很常見的,如果不知道tintColor,你可能會用兩張不同顏色的圖片來開發這個需求。但其實Image組件的style中有一個tintColor屬性,能讓我們輕鬆的調整圖片顏色。

    範例:
    首先,這是我們的原始黑色圖片
    https://ithelp.ithome.com.tw/upload/images/20230927/20103365gV66maFzqR.png
    接著,透過設定tintColor為'green'
    https://ithelp.ithome.com.tw/upload/images/20230927/20103365QSlEUwO97i.png
    最後,這張圖片就變成了綠色。(實際上,tintColor是將圖片中非透明部分染色)

  • Android大圖問題
    在圖片的處理上,iOS平台表現得相對穩定,Android平台卻較容易遇到些小問題。
    筆者曾經遇到一個需求:APP中有一頁要用一張非常大的圖片展示。當我完成開發並在iOS上測試後,一切看起來都很完美。然後直覺圖片的展示在Android應該也是相似的,於是我就沒有特地測試Android,直接交給QA進行測試。結果QA就回饋表示在Android上圖片顯得非常模糊。

    這是因為Android在圖片處理上有所限制,尤其是大圖片。
    這裡做個範例,這是一張寬度375 高度5700的圖,左邊Android 右邊IOS,可以看到,Android平台上的圖片遠不如iOS清晰。
    https://ithelp.ithome.com.tw/upload/images/20230927/20103365cgeD054Qcy.png

    這問題主要有兩種解決方法:

    1. 切分圖片:將大圖片進行切分,例如一張高度為5000的圖片,可以切分成10張,每張高度為500,再組起來。
    2. 使用WebView: 在APP內開啟一個瀏覽器,然後將該大圖片放到此瀏覽器中進行展示。

    筆者後來是用第一種方法處理的,也是較為建議的方法,只有在真的沒有辦法時,才考慮使用第二種方法。因為使用WebView即意味著放棄原生的效能優勢。

圖片相關第三方套件推薦

  • FastImage:此套件基於 SDWebImage (iOS) 和 Glide (Android) 開發,可以帶來更出色的性能和效果。

  • AutoHeightImage
    在 React Native Image 組件中,要使圖片在特定寬度內完整展現,我們需要設置 resizeModestretch。但這種方式可能會改變圖片的原始比例,影響顯示效果。
    使用 AutoHeightImage 可以輕鬆解決這個問題。只需指定圖片寬度,此套件就會自動調整高度,保持圖片的原始比例。

小結

Image組件在React Native中,使用上相對直觀,但其實它很多細節是會直接影響到應用的性能和使用體驗,所以正確暸解和掌握Image組件的使用方法是相當重要的。


上一篇
Day 11:React Navigation 頁面導航與跳轉
下一篇
Day 13:React Native動畫入門:從基礎到實作
系列文
30天React Native之旅:從入門到活用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言