【发布时间】:2022-01-15 03:26:14
【问题描述】:
我正在尝试使用 Gatsby JS (SSG) 和成帧器运动构建图像滑块。我遇到了一个问题,即在页面上不可见的图像(除了选项卡 1 之外的所有选项卡)没有被预渲染,尽管 GatsbyImage 提供了 loading="eager" 属性。
我已经构建了一个图像提供程序来查询图像滑块中的图像:
const ImageProvider = ({ fileName, alt, imgStyle, style, loading, placeholder }) => {
const { allImageSharp } = useStaticQuery(graphql`
{
allImageSharp {
nodes {
parent {
... on File {
base
}
}
gatsbyImageData
}
}
}
`)
const image = allImageSharp.nodes.find(node => node.parent.base === fileName).gatsbyImageData;
if (!image) return null;
return (
<GatsbyImage image={image} alt={alt} imgStyle={imgStyle} style={style} loading={loading} placeholder={placeholder} />
)
}
export default ImageProvider;
这是图像滑块:
export const TabSlider = ({
tabs,
}) => {
const [[page, direction], setPage] = useState([0, 0]);
const elementRef = useRef(null);
const elementSize = useElementSize(elementRef);
// We only have 3 images, but we paginate them absolutely (ie 1, 2, 3, 4, 5...) and
// then wrap that within 0-2 to find our image ID in the array below. By passing an
// absolute page index as the `motion` component's `key` prop, `AnimatePresence` will
// detect it as an entirely new image. So you can infinitely paginate as few as 1 images.
// const imageIndex = wrap(0, images.length, page);
const paginate = (newDirection) => {
setPage([page + newDirection, newDirection]);
};
return (
<Container>
<ImageProvider style={{ width: "100%" }} alt="" loading="eager" placeholder="none" />
<AnimateSharedLayout>
<TabsContainer>
<TabsHeader>
{tabs.map(({ title }, i) => {
const isActive = i === page;
return (
<TabItem
key={i}
className={isActive ? "active-header" : ""}
onClick={() => {
// set page and determine which direction we're going
setPage([i, i - page]);
}}
>
<TabHeaderContainer>
<TabHeader>{title}</TabHeader>
</TabHeaderContainer>
{isActive && (
<Underline as={motion.div} layoutId="underline" />
)}
</TabItem>
);
})}
<UnderlineBg />
</TabsHeader>
</TabsContainer>
<ContentContainer>
<AnimatePresence initial={false} custom={direction}>
<Section
as={motion.section}
ref={elementRef}
key={page}
custom={direction}
variants={variants}
initial="enter"
animate="center"
exit="exit"
transition={{
x: { type: "spring", stiffness: 300, damping: 30, duration: 2 },
opacity: { duration: 0.2 }
}}
drag="x"
dragConstraints={{ left: 0, right: 0 }}
dragElastic={1}
onDragEnd={(e, { offset, velocity }) => {
const swipe = swipePower(offset.x, velocity.x);
if (swipe < -swipeConfidenceThreshold) {
paginate(1);
} else if (swipe > swipeConfidenceThreshold) {
paginate(-1);
}
}}
>
<Background height={elementSize.height} />
<Wrapper>
<SlideContainer ref={elementRef}>
<CopywritingContainer>
<H2Header>{tabs[page].header}</H2Header>
<Text>{tabs[page].text}</Text>
</CopywritingContainer>
<ImageContainer>
<ImageProvider fileName={tabs[page].imageFilename} style={{ width: "50%" }} alt="" loading="eager" placeholder="none" />
</ImageContainer>
</SlideContainer>
</Wrapper>
</Section>
</AnimatePresence>
</ContentContainer>
</AnimateSharedLayout>
</Container>
);
};
我看不出哪里出了问题,非常感谢任何指导。
谢谢!
【问题讨论】:
-
您能否提供一个 CodeSandbox 或添加一些日志以查看问题所在?或者添加滑块的更多部分?有一个
Image组件但滑块有一个ImageProvider,它们是一样的吗? -
@FerranBuireu 我无法将工作的 CodeSandbox 组合在一起,但我已经提供了图像提供程序和选项卡滑块组件的完整代码。我注意到这个问题发生在屏幕上不可见的任何图像上。我构建了另一个组件,它基于布尔状态值在两个图像之间切换,并且第二个图像总是会在延迟后弹出,尽管 loading="eager" 被硬编码到我的 ImageProvider 的 GatsbyImage 组件中。
-
我可以看到,在清除 Gatsby 的缓存后,图像并未预渲染,而是在首次显示在屏幕上时被下载。
-
@FerranBuireu 你知道是否可以从尚未加入 vDOM 的组件中预渲染图像?
-
应该是可以的。尝试将该责任委托给滑块依赖项而不是 Gatsby 图像
标签: gatsby