如何使用 gatsby-image 显示图像而不进行裁剪?

Posted

技术标签:

【中文标题】如何使用 gatsby-image 显示图像而不进行裁剪?【英文标题】:How to display images without cropping using gatsby-image? 【发布时间】:2019-12-23 19:42:43 【问题描述】:

实时示例(图片可能加载缓慢):https://suhadolnik-photo.surge.sh/portreti

我正在使用 GatsbyJS 制作一个摄影网站,并使用以下模板作为我一直在更改的基础网站:https://github.com/LekoArts/gatsby-starter-portfolio-emilia

作为 graphql 的新手,在用户单击卡片以显示“肖像”子页面后,我遇到了显示图像的问题。这些图像都以我不想要的固定宽度和高度显示。我需要用它们的原生宽度和高度显示它们,只需调整大小以适应网格。

我尝试更改 project.js 文件中的 graphql 查询,在该文件中将 maxWidth: 1600 设置为无济于事,以及在查询的下方设置了 resize(width: 800)。后来我发现通过开发工具更改gatsby-image-wrapper 上的margin 给了我预期的结果,但这需要更改核心gatsby-image 插件并且必须单独为每个图像手动更改margin,这不是解决办法。

project.js

import React from 'react'
import Img from 'gatsby-image'
import PropTypes from 'prop-types'
import  graphql  from 'gatsby'
import styled from 'styled-components'

import  Layout, ProjectHeader, ProjectPagination, SEO  from '../components'
import config from '../../config/site'

const BG = styled.div`
  background-color: $props => props.theme.colors.bg;
  position: relative;
  padding: 2rem 0 0 0;
`

const OuterWrapper = styled.div`
  padding: 0 $props => props.theme.contentPadding;
  margin: -10rem auto 0 auto;
`

const InnerWrapper = styled.div`
  position: relative;
  max-width: $props => `$props.theme.maxWidths.projectpx`;
  margin: 0 auto;
`

const Grid = styled.div`
  display: grid;
  grid-template-columns: repeat($props => props.theme.gridColumnsProject, 1fr);
  grid-gap: 20px;

  @media (max-width: 768px) 
    grid-template-columns: 1fr;
  
`

const Project = ( pageContext:  slug, prev, next , data:  project: postNode, images  ) => 
  const project = postNode.frontmatter

  return (
    <Layout customSEO>
      <SEO postPath=slug postNode=postNode postSEO />
      <ProjectHeader
        name=config.name
        date=project.date
        title=project.title
        areas=project.areas
        text=postNode.body
      />
      <BG>
        <OuterWrapper>
          <InnerWrapper>
            <Grid>
              images.nodes.map(image => (
                <Img
                  alt=image.name
                  key=image.childImageSharp.fluid.src
                  fluid=image.childImageSharp.fluid
                  style= margin: '2rem 0' 
                />
              ))
            </Grid>
          </InnerWrapper>
          <ProjectPagination next=next prev=prev />
        </OuterWrapper>
      </BG>
    </Layout>
  )


export default Project

Project.propTypes = 
  pageContext: PropTypes.shape(
    slug: PropTypes.string.isRequired,
    next: PropTypes.object,
    prev: PropTypes.object,
  ),
  data: PropTypes.shape(
    project: PropTypes.object.isRequired,
    images: PropTypes.object.isRequired,
  ).isRequired,


Project.defaultProps = 
  pageContext: PropTypes.shape(
    next: null,
    prev: null,
  ),


export const pageQuery = graphql`
  query($slug: String!, $absolutePathRegex: String!) 
    images: allFile(
      filter: 
        absolutePath:  regex: $absolutePathRegex 
        extension:  regex: "/(jpg)|(png)|(tif)|(tiff)|(webp)|(jpeg)/" 
      
      sort:  fields: name, order: ASC 
    ) 
      nodes 
        name
        childImageSharp 
          fluid(maxWidth: 1600, quality: 90) 
            ...GatsbyImageSharpFluid_withWebp
          
        
      
    
    project: mdx(fields:  slug:  eq: $slug  ) 
      body
      excerpt
      parent 
        ... on File 
          mtime
          birthtime
        
      
      frontmatter 
        cover 
          childImageSharp 
            resize(width: 800) 
              src
            
          
        
        date(formatString: "DD.MM.YYYY")
        title
        areas
      
    
  
`

Card.js父组件:

import React from 'react'
import styled from 'styled-components'
import PropTypes from 'prop-types'
import  useSpring, animated, config  from 'react-spring'
import  rgba  from 'polished'
import Img from 'gatsby-image'
import  Link  from 'gatsby'

const CardItem = styled(Link)`
  min-height: 500px;
  position: relative;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.2);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  color: $props => props.theme.colors.color;
  transition: all 0.3s ease-in-out;

  &:hover 
    color: white;
    transform: translateY(-6px);
  

  @media (max-width: $props => props.theme.breakpoints.s) 
    min-height: 300px;
  
`

const Cover = styled.div`
  width: 100%;
  height: 100%;
  position: absolute;
`

const Content = styled.div`
  padding: 1rem;
  position: relative;
  transition: all 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
  opacity: 0;
  background: $props => rgba(props.theme.colors.link, 0.65);
  height: 0;

  $CardItem:hover & 
    opacity: 1;
    height: 120px;
  
`

const Bottom = styled.div`
  margin-top: 0.5rem;
  display: flex;
  align-items: center;
  font-size: 0.85rem;
  div:first-child 
    margin-right: 1rem;
  
`

const Name = styled.h2`
  margin-bottom: 0;
  margin-top: 0;
`

const Card = ( path, cover, date, areas, title, delay ) => 
  const springProps = useSpring(
    config: config.slow,
    delay: 200 * delay,
    from:  opacity: 0, transform: 'translate3d(0, 30px, 0)' ,
    to:  opacity: 1, transform: 'translate3d(0, 0, 0)' ,
  )

  return (
    <animated.div style=springProps>
      <CardItem to=path>
        <Cover>
          <Img fluid=cover />
        </Cover>
        <Content>
          <Name>title</Name>
          <Bottom>
            <div>date</div>
            <div>
              areas.map((area, index) => (
                <React.Fragment key=area>
                  index > 0 && ', '
                  area
                </React.Fragment>
              ))
            </div>
          </Bottom>
        </Content>
      </CardItem>
    </animated.div>
  )


export default Card

Card.propTypes = 
  path: PropTypes.string.isRequired,
  cover: PropTypes.object.isRequired,
  date: PropTypes.string.isRequired,
  areas: PropTypes.array.isRequired,
  title: PropTypes.string.isRequired,
  delay: PropTypes.number.isRequired,


我希望图像以其原始宽度和高度显示,但会调整大小以适应网格。在下面提供有关它现在的外观和预期结果的可视化表示。 Current result 和 expected result

干杯!

【问题讨论】:

你有一个可行的例子吗? 我能提供的最好的就是我使用过的模板的演示页面:emilia.lekoarts.de 你没有做一些改变吗? 我添加了一个现场演示:suhadolnik-photo.surge.sh/portreti 【参考方案1】:

从主页上的封面组件中删除height:100%position:absolute

const Cover = styled.div`
  width: 100%;
`

另外,如果您不知道,您可以将 styleimgStyle 属性传递给 Gatsby image to change it's css.

| style            | object | Spread into the default styles of the wrapper element         |  
| imgStyle         | object | Spread into the default styles of the actual img element      |
| placeholderStyle | object | Spread into the default styles of the placeholder img element |

因此,在您的项目模板中,您可以像这样更改对象适合样式:

<Img
  alt=image.name
  key=image.childImageSharp.fluid.src
  fluid=image.childImageSharp.fluid
  imgStyle= objectFit: 'contain' 
/>

【讨论】:

这仅修复了主页上的问题,而不是单个项目页面上的问题。 添加imgStyle= objectFit: 'contain' 解决了这个问题。另外我不知道图像可以采用样式,所以也谢谢你! 酷。是的,它就埋在文档的底部,所以通常不会有很多人知道gatsby-image

以上是关于如何使用 gatsby-image 显示图像而不进行裁剪?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 gatsby-image 从数组中查询多个图像?

如何查询 gatsby-image?

gatsby-image:如何将处理后的图像导入 css 并与 background-image 属性一起使用

如何使用 Gatsby 显示 Contentul 图像

GatsbyJS:从 WPGraphQL 查询 Gatsby-image 以获取高级自定义字段

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