使用 React 映射图像数组时如何创建图像背景渐变
Posted
技术标签:
【中文标题】使用 React 映射图像数组时如何创建图像背景渐变【英文标题】:How to create an image background fade when mapping an array of images with React 【发布时间】:2020-09-25 14:08:00 【问题描述】:我正在使用 Sanity 无头 CMS 开发 React.js/Next.js 项目。
我有一个 hero 元素,它接受一组图像,但希望能够自动循环通过它来创建背景滑块效果。我很想使用光滑的滑块或类似的滑块,但如果可能的话,我想尝试使用纯 CSS 来实现这一点,因为该项目的 webpack 配置不会使导入外部 css 文件变得非常容易。
我的组件...
import React from "react";
import PropTypes from "prop-types";
import styles from "./Hero.module.css";
import client from "../../client";
import SimpleBlockContent from "../SimpleBlockContent";
import Cta from "../Cta";
import imageUrlBuilder from "@sanity/image-url";
const builder = imageUrlBuilder(client);
function Hero(props)
const heading, image, tagline, ctas = props;
const images = props.image;
return (
<div className=styles.root>
<div className=styles.content>
<h1 className=styles.title>heading</h1>
<div className=styles.tagline>tagline && <SimpleBlockContent blocks=tagline /></div>
<div>
images.map((image) => (
<img
className=styles.image
src=builder.image(image).url()
className=styles.image
alt=heading
/>
))
</div>
</div>
</div>
);
Hero.propTypes =
heading: PropTypes.string,
backgroundImage: PropTypes.object,
tagline: PropTypes.array,
ctas: PropTypes.arrayOf(PropTypes.object),
;
export default Hero;
我的 CSS
@import "../../styles/custom-properties.css";
.root
composes: center from "../../styles/shared.module.css";
position: relative;
color: var(--color-white, #fff);
background: none;
padding-bottom: 2rem;
@media (--media-min-medium)
padding-bottom: 1rem;
.content
width: 100vw;
min-height: 100vh;
padding: 0 1.5em;
box-sizing: border-box;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
.image
position: absolute;
z-index: -1;
left: 0;
top: 0;
overflow: hidden;
display: block;
width: 100vw;
height: 100vh;
object-fit: cover;
animation: fade 2s infinite;
.title
text-align: center;
text-transform: uppercase;
letter-spacing: 2px;
position: relative;
font-weight: 300;
font-size: var(--font-title2-size);
line-height: var(--font-title2-line-height);
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
margin: 0;
padding: 0;
@media (--media-min-medium)
font-size: var(--font-title1-size);
line-height: var(--font-title1-line-height);
padding-top: 0;
@keyframes fade
0%
opacity: 1;
100%
opacity: 0;
此代码确实淡入淡出数组中的第一个图像,但不会影响“坐在”第一个图像后面的其他图像。
希望这是有道理的,任何帮助将不胜感激!
编辑 - 简化的 StackBlitz 模型
https://stackblitz.com/edit/react-wmfcbp?
【问题讨论】:
如果您在 stackblitz 上分享有关该问题的工作演示会更容易提供帮助 感谢@AkberIqbal 添加了一个非常基本的内容,但希望能得到重点 【参考方案1】:问题在于您的 .image
类为所有图像设置了相同的 z-index 和动画属性。
尝试像这样设置延迟:
images.map((image, index) => (
<img
id=index
className="image"
src=image
style=
animationDelay: `$index * 4s`, // delay animation for next images
zIndex: `-$index + 1` // make images as layers, not same layer -1
/>
))
但是如果你使用 React,你也可以尝试在 React 中通过间隔和钩子来制作它,并通过应用类在 css 中为活动幻灯片制作动画:
import React, useRef, useState, useEffect from "react";
import "./Hero.css";
const images = [
" https://images.unsplash.com/photo-1470165451736-166cb1cc909d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2552&q=80",
"https://images.unsplash.com/photo-1537367075546-0529d021d198?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1500&q=80",
"https://images.unsplash.com/photo-1590064589331-f19edc8bed34?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1500&q=80"
]
function Hero(props)
const slidePresentationTime = 3000 // after how many ms slide will change - now 3s / 3000ms
const [currentSlide, setCurrentSlide] = useState(0) // value and function to set currrent slide index
const sliderInterval = useRef() // interval ref
useEffect(() =>
sliderInterval = setInterval(() =>
setCurrentSlide((currentSlide + 1) % images.length); // change current slide to next slide after 'slidePresentationTime'
, slidePresentationTime);
// cleanup interval when your component will unmount
return () =>
clearInterval(sliderInterval)
)
return (
<div className="root">
<div className="content">
<h1 className="title">Title</h1>
<div>
images.map((image, index) => (
<img
id=index
key=index
className=index === currentSlide ? 'image active' : 'image'
src=image
style=
zIndex: `-$index + 1`
/>
))
</div>
</div>
</div>
);
export default Hero;
在这里使用transition
而不是animation
会容易得多,只需按类更改过渡属性(不透明度)。
//styles
.image
position: absolute;
left: 0;
top: 0;
overflow: hidden;
display: block;
width: 100vw;
height: 100vh;
object-fit: cover;
transition: opacity 1s ease;
opacity: 0;
.active
opacity: 1;
这里是演示https://stackblitz.com/edit/react-2dd6iu
【讨论】:
非常好的解决方案,感谢@Robson。在将 babel 实施到我的项目中时,我遇到了一些问题,但我相信实际的源代码运行良好!以上是关于使用 React 映射图像数组时如何创建图像背景渐变的主要内容,如果未能解决你的问题,请参考以下文章
如何从 React 中的公共文件夹设置背景图像(创建 React 应用程序)