如何使用 gatsby-image 在不裁剪的情况下显示图像?

IT技术 javascript reactjs graphql gatsby
2021-05-06 14:04:00

现场示例(图像可能加载缓慢):https : //suhadolnik-photo.surge.sh/portreti

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

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

我已经尝试更改project.js文件中的 graphql 查询,在那里您将 设置maxWidth: 1600为无效,以及resize(width: 800)查询进一步向下。后来我发现通过开发工具更改marginongatsby-image-wrapper给了我预期的结果,但这需要更改核心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.project}px`};
  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,
}

我希望图像以它们的原始宽度和高度显示,但调整大小以适应网格。在下面提供有关它现在的外观和预期结果的视觉表示。 当前结果预期结果

干杯!

1个回答

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

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

此外,如果您不知道,您可以将styleimgStyle props传递Gatsby 图像以更改其 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' }}
/>