React Gatsbyjs 根据宽高比向 gatsby-image 添加 class

React Gatsbyjs add class to gatsby-image based on aspect ratio

gatsby-image 用 gatsby-image-wrapper div 包裹每个图像,它填充 100% 的可用视口宽度。这个包装器 div 可以很容易地用 CSS 设置样式,但是 无法区分处理横向、纵向或方形图像。

如果您想让横向图像填充可用宽度的 80%-100%,但纵向和方形图像填充不超过视口宽度的 40-50%,该怎么办?

因此,理想情况下,每个 gatsby-image-wrapper div 都会根据其宽高比添加一个 class,这可能是; landscapeportraitsquare

一种方法是使用 childImageSharp 附带的宽高比编写一些条件语句:

      edges {
        node {
          name
          childImageSharp {
            fluid(maxWidth: 915, quality: 90) {
              aspectRatio
              ...GatsbyImageSharpFluid_withWebp
            }
          }
        }
      }

当我映射我所有的图库图像时,我可以获取宽高比并使用 className 将其添加到每个 gatsby-image-wrapper,但它作为返回数据的原始格式不是很有用对于 aspectRatio 是数字,例如 0.6666666666666666 用于肖像图像或 1.5003750937734435 用于风景。拥有上面提到的那些 classes 会更好; landscapeportraitsquare

这就是我如何从当前 post 获取我的所有图库图片以及它们的 aspectRatio

export default ({ data }) => {
  return (
    <Layout>
      <article>
        {data.allFile.edges.map(({ node }, index) => (
          <div>
            <Img
              key={index}
              className={node.childImageSharp.fluid.aspectRatio}
              alt={node.name}
              fluid={node.childImageSharp.fluid}
            />
            <span>{node.childImageSharp.fluid.aspectRatio}</span>
          </div>
        ))}
      </article>
    </Layout>
  );
};

我使用的完整 GraphQL 查询是:

export const query = graphql`
  query($slug: String!, $absolutePathRegex: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
        date
        modified
        caption
        description
        cover {
          publicURL
          childImageSharp {
            fluid(maxWidth: 915, quality: 90) {
              ...GatsbyImageSharpFluid_withWebp
            }
          }
        }
      }
      fields {
        slug
      }
    }
    allFile(
      filter: {
        extension: { regex: "/(jpg)|(png)|(tif)|(tiff)|(webp)|(jpeg)/" }
        absolutePath: { regex: $absolutePathRegex }
      }
    ) {
      edges {
        node {
          name
          childImageSharp {
            fluid(maxWidth: 915, quality: 90) {
              aspectRatio
              ...GatsbyImageSharpFluid_withWebp
            }
          }
        }
      }
    }
  }
`;

必须有一个简单的解决方案,使用 React 中的条件语句,在其中映射所有图像,采用纵横比 然后将原始数据转换为所需的 classes.

所以代替:

<div class="1.5003750937734435 gatsby-image-wrapper"></div>
<div class="0.6666666666666666 gatsby-image-wrapper"></div>
<div class="0.6666666666666666 gatsby-image-wrapper"></div>
<div class="1.0000000000000000 gatsby-image-wrapper"></div>
<div class="1.5003750937734435 gatsby-image-wrapper"></div>

你会得到:

<div class="landscape gatsby-image-wrapper"></div>
<div class="portrait gatsby-image-wrapper"></div>
<div class="portrait gatsby-image-wrapper"></div>
<div class="square gatsby-image-wrapper"></div>
<div class="landscape gatsby-image-wrapper"></div>

然后可以使用 css 轻松设置样式。

除非我遗漏了什么,你不是已经完成了 99% 了吗?您可以在 map 中编写条件,或者更好的是,编写一个包装 <Img>:

的组件
import React from 'react'
import Img from 'gatsby-image'

// we only care about `aspectRatio`, the rest will be passed directly to `Img`
// also take out `className` so it be merged with our generated `orientation` class name
const ImgWithOrient = ({ aspectRatio, className, ...props }) => {
  let orientation
  if (aspectRatio > 1) orientation = 'landscape'
  if (aspectRatio < 1) orientation = 'portrait'
  else orientation = 'square'

  return <Img className={`${className} ${orientation}`} {...props} />
}

export default ({ data }) => {
  return (
    <Layout>
      <article>
        {data.allFile.edges.map(({ node }, index) => (
          <div key={index}>
            <ImgWithOrient
              key={index}
              aspectRatio={node.childImageSharp.fluid.aspectRatio}
              className="other class name"
              alt={node.name}
              fluid={node.childImageSharp.fluid}
            />
            <span>{node.childImageSharp.fluid.aspectRatio}</span>
          </div>
        ))}
      </article>
    </Layout>
  )
}

另请注意,当您遍历某些内容时,您需要将 key 放在最外层的组件中——在本例中,外层 <div>,而不是 <Img>.