React Gatsbyjs 根据纵横比向 gatsby-image 添加类

Posted

技术标签:

【中文标题】React Gatsbyjs 根据纵横比向 gatsby-image 添加类【英文标题】:React Gatsbyjs add class to gatsby-image based on aspect ratio 【发布时间】:2019-11-11 22:27:19 【问题描述】:

gatsby-image 使用 gatsby-image-wrapper div 包装每个图像,该 div 填充 100% 的可用视口宽度。这个包装器 div 可以很容易地使用 CSS 设置样式,但 没有办法将横向、纵向或方形图像区别对待。

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

因此,理想情况下,每个 gatsby-image-wrapper div 都会根据其纵横比添加一个类,可以是; landscapeportraitsquare

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

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

当我映射所有画廊图像时,我可以获取纵横比并使用 className 将其添加到每个 gatsby-image-wrapper 但它的原始格式不是很有用,因为 aspectRatio 的返回数据是像 @987654326 这样的数字@ 用于纵向图像或1.5003750937734435 用于横向。使用上面提到的那些类会更好; landscapeportraitsquare

这就是我从当前帖子中获取所有图库图片的方式,以及他们的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 中使用条件语句映射所有图像,获取纵横比 然后将原始数据转换为所需的类。

所以而不是:

<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 设置样式。

【问题讨论】:

【参考方案1】:

除非我遗漏了什么,否则你不是已经有 99% 了吗?您可以在map 中编写条件,或者更好的是,编写一个包装&lt;Img&gt; 的组件:

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 放在最外层的组件中——在本例中,是最外层的&lt;div&gt;,而不是&lt;Img&gt;

【讨论】:

谢谢 Derek,你的回答让这个工作正常了。我不得不使用小于/大于操作符来获得预期的结果。这是我根据你的代码得到的:const ImgWithOrient = ( aspectRatio, className, ...props ) =&gt; let orientation; if (aspectRatio &gt;= 1.2) orientation = "landscape"; if (aspectRatio &lt;= 0.8) orientation = "portrait"; if (aspectRatio &gt; 0.8 &amp;&amp; aspectRatio &lt; 1.2) orientation = "square"; return &lt;Img className=`$className $orientation` ...props /&gt;; ;

以上是关于React Gatsbyjs 根据纵横比向 gatsby-image 添加类的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React Native 中设置 Android 屏幕、分辨率、纵横比和大小?

根据窗口大小和纵横比缩放图像

根据宽度和纵横比计算新高度

根据屏幕大小设置纵横比的公式是啥

根据宽度和高度保持纵横比

根据纵横比将媒体元素居中