Gatsby:イメージ(画像)を表示させるための作法


Gatsby:イメージ(画像)を表示させるための作法

ダイナミックに読み込んで表示させる

これはいったい…?

デフォルトでトップページに貼られているスペースマン画像"gatsby-astronaut.png"。

このファイルはimagesフォルダの中にあって、それを読み込むトップページindex.jsは、

//index.js
<Image />

とだけある。

?????

どうやらcomponentsフォルダにあるimage.jsがハンドルしているようである(デフォルトで存在する)。

//components/image.js デフォルトのコード

import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"

const Image = () => {
  const data = useStaticQuery(graphql`
    query {
      placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
        childImageSharp {
          fluid(maxWidth: 300) {
            ...GatsbyImageSharpFluid
          }
        }
      }
    }
  `)

  return <Img fluid={data.placeholderImage.childImageSharp.fluid} />
}

export default Image

このコードを超訳すると、
gatsby-astronaut.pngというファイル名に一致するものを探し出してきて(8行目、 eq: "gatsby-astronaut.png" )自動で画像を最適化しレスポンシブで表示しする

さらに、dig down(追及)しないがLazy loadingまでやってくれる。ためしにgatsby-astronaut.pngを別のめっさ重い画像に取り換えてみて表示させると、ぼやけた状態からフェードインするようにハッキリした画像にスムーズに写り替わる。なかなか感動する。

したがって画像ファイルはすべてimagesフォルダに置いて、このgatsby-astronaut.pngというところを表示させたい画像ファイル名に変更して、表示させたいページ側で<Image />タグを書くだけで済む。

しかしそれでは画像はひとつしか使えないではないか…。

解決方法

多くの方がすでに解決方法を。image.jsを次のように変更。

//components/image.js

import React from "react"
import { StaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"

const Image = (props) => (
  <StaticQuery
    query={graphql`
      query {
        images: allFile {
          edges {
            node {
              relativePath
              name
              childImageSharp {
                fluid(maxWidth: 300) {
                  ...GatsbyImageSharpFluid
                }
              }
            }
          }
        }
      }
    `}

    /*
      サイズFIXしたい時は上記childImageSharp {...}の中を以下のように変更
              sizes(maxWidth: 300) {
                ...GatsbyImageSharpSizes
              }
    */
    render={(data) => {
      const image = data.images.edges.find(n => {
        return n.node.relativePath.includes(props.filename);
      });
      if (!image) { return null; }
      //const imageSizes = image.node.childImageSharp.sizes; ←サイズFIXしたい時
      return (
        /*<Img alt={props.alt} sizes={imageSizes} /> ←サイズFIXしたい時 */
        <Img fluid={image.node.childImageSharp.fluid} alt={props.alt} />
      );
    }}
  />
)
export default Image

表示させる側では次のように画像ファイル名を指定する。画像はもちろんデフォルトのsrc/imagesフォルダ配下に置くだけ。

// index.js
・・・・・・
<Image filename="gatsby-astronaut.png" alt="Gatsbyスペースマン" />
・・・・・・

スタティックに読み込んで表示させる

しかしどうしてもsrc=""といった読み込み方をしたい場合がある。たとえばReact bootstrapでCard.imgのsrc属性。以下のように

 <Card>
     <Card.Body>
        <Card.Img variant="top" src="" />
           <Card.Title>タイトル</Card.Title>
           <Card.Text>
       本文本文本文本文本文本文本文本文本文本文本文本文
           </Card.Text>
     </Card.Body>
</Card>

こんな場合に<Card.Img variant="top" src="./images/gatsby-astronaut.png" />とかやっても怒られる。ではどうするか?

まずインポートする

import gatsbyOjisanImg from './images/gatsby-astronaut.png'でインポートする。そしてgatsbyOjisanImgをsrcの引数に。

import React from "react"
import { Card } from 'react-bootstrap'
import gatsbyOjisanImg from './images/gatsby-astronaut.png' // ←ココ

 <Card>
     <Card.Body>
        <Card.Img variant="top" src={gatsbyOjisanImg } />
           <Card.Title>タイトル</Card.Title>
           <Card.Text>
       本文本文本文本文本文本文本文本文本文本文本文本文
           </Card.Text>
     </Card.Body>
</Card>

ステップがひとつ増えてめんどくさいかもしれないがそのかわり、画像の最適化をGatsbyがやってくれる。

以下はかなり大きな表画像をCard.imgに指定したがGatsbyが最適化して表示してくれたbootstrapカードの一例。

以上。

宣伝

microCMSのことは除き、Gatsbyの基本とnode APIの扱いについて踏み込んで解説・ハンズオンした電子書籍を上梓しましたので、よろしければお手に取ってみて下さい。

JAMStackを学ぼう Gatsby, React bootstrap, Netlifyでつくる企業サイト: もうレンタルサーバーはいらない ヤー・ビズテック



GatsbyとmicroCMSを組み合わせてのコーポレートサイト作成手順を解説・ハンズオンした続編を上梓しました。どうぞお手に取ってみて下さい。

JAMStackを学ぼう GatsbyとmicroCMSでつくるコーポレートサイト ~WordPressはもう古い~


参考:GatsbyJSのimageを使ってみよう