在 React.Js 使用 img 標籤顯示 svg 圖片

前言

由於 React 是使用jsx在組裝 HTML
jsx會要求以駝蜂式命名 HTML 標籤

若svg是由程式產生、user上傳而得到的話
就不太可能再花心力轉換成 jsx 語法再由React渲染成正常的 HTML
不但最終的結果是一樣的,還得多執行一段 JavaScript…怎麼想都覺得很蠢= =

React 有提供dangerouslySetInnerHTML來使用正常的 HTML 語法
只是這命名就讓人感覺很危險XD,而且也特別冗長

但其實可以透過原生 img 來呈現 svg,且對 SEO 也較友好!

作法

程式碼很簡單

<img src={`data:image/svg+xml;charset=utf-8,${encodeURIComponent(RAW_SVG_STRING)}`} />

由於 svg 字串會有單雙引號造成 js 執行時期誤判,所以要加上encodeURIComponent()做編碼轉換

React FC 直接使用

以下順便提供 React functional component 直接拷貝使用

const SvgImg = ({rawSvgString, width, height, alt}) => {
    return (<>
        <img src={`data:image/svg+xml;charset=utf-8,${encodeURIComponent(rawSvgString)}`}
             alt={alt} width={width} height={height} />
    </>);
};

export default SvgImg;

透過上傳取得的圖片檔要直接呈現在 HTML 裡

若圖片檔是由 user 上傳的話
則可以透過 FileReader 直接轉換使用

const getImage = (file: File): Promise<ArrayBuffer> => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = e => resolve(e.target!.result)
        reader.readAsDataURL(file)
    })
}

// 以下是在 React 裡面使用
const image = await getImage(IMAGE_BY_USER_UPLOAD);

<img src={image} />

雖然取到的型別是ArrayBuffer,但把他印出來看
會發現前面已包含了 img 裡的基本型式data:image/png;base64,(圖片內容省略)

則只需要將整個字串丟入 img 的 src 裡就行嘍!