简体   繁体   English

如何从数组中将背景图像动态设置为卡片组件?

[英]How to dynamically set background image to card component from an array?

Not sure exactly how to describe this.不确定如何描述这一点。 I have a grid of cards each displaying a different game and I'd like to set each background-image to an image of the game.我有一张卡片网格,每张卡片都显示不同的游戏,我想将每个背景图像设置为游戏图像。 Here is the code I have so far:这是我到目前为止的代码:

const games = [
  {
    id: 1,
    background: '../images/game1.png',
    name: 'Game 1',
    description:
      'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vel sapien arcu. Donec sapien eros, efficitur blandit dui vitae, imperdiet consectetur nibh.',
  },
  {
    id: 2,
    background: '../images/game2.png',
    name: 'Game 2',
    description:
      'Nunc efficitur tincidunt malesuada. Pellentesque blandit sapien sed orci tristique molestie. Donec ut metus a sapien gravida convallis sed maximus neque. Aliquam consequat fringilla porta. Curabitur eget semper tortor.',
  },
];

export const GameCard = () => {
  const [isOpen, setIsOpen] = useState(null);

  return (
    <div id="card_wrapper">
      {games.map((game) => (
        <motion.div
          transition={{ layout: { duration: 1, type: 'spring' } }}
          layout
          onClick={() => setIsOpen(!isOpen)}
          key={game.id}
          class="card"
          style={{
            backgroundImage: `url(${game.background}) no-repeat`,
          }}
        >
          <motion.h2 layout="position"> {game.name} </motion.h2>
          {isOpen && (
            <motion.div
              initial={{ opacity: 0 }}
              animate={{ opacity: 1 }}
              transition={{ duration: 1 }}
              class="expand"
            >
              <p> {game.description} </p>
            </motion.div>
          )}
        </motion.div>
      ))}
    </div>
  );
};

Specifically具体来说

        <motion.div
          transition={{ layout: { duration: 1, type: 'spring' } }}
          layout
          onClick={() => setIsOpen(!isOpen)}
          key={game.id}
          class="card"
          style={{
            backgroundImage: `url(${game.background}) no-repeat`,
          }}
        >

is where I'm trying to pass the image as a background but it doesn't work.是我试图将图像作为背景传递但它不起作用的地方。

Edit showing console: Shows image being passed through but not rendering编辑显示控制台:显示正在通过但不渲染的图像

Actually your onClick handler just handle open and close, you need define background img first as state on empty array before rendering on jsx, like so实际上,您的 onClick 处理程序仅处理打开和关闭,您需要先在空数组上将背景 img 定义为 state,然后再在 jsx 上渲染,就像这样

export const GameCard = () => {
const [isOpen, setIsOpen] = useState(null);
const [imgList, setImgList] = useState([]);
const imgRef = useRef()
const renderImgArr = (dataImg) => {
    setImgList([dataImg])
    /* ....define imgRef ...*/
}

return (
    <div id="card_wrapper">
      {games.map((game) => (
        <motion.div
          transition={{ layout: { duration: 1, type: 'spring' } }}
          layout
          // add renderImg and also possible to add setTimeOut on renderImgArr 
          onClick={() => setIsOpen(!isOpen) && renderImgArr}
          key={game.id}
          class="card"
          style={{
            backgroundImage: `url(${game.background}) no-repeat`,
          }}
        >
          <motion.h2 layout="position"> {game.name} </motion.h2>

         {/* render imgList with isOpen */}
          {isOpen && imgList && ( 
            <motion.div
              initial={{ opacity: 0 }}
             // define ref as a target reference 
              animate={imageRef.current.target, { opacity: 1 }}
              transition={{ duration: 1 }}
              class="expand"
            >
              <p> {game.description} </p>
            </motion.div>
          )}
        </motion.div>
      ))}
    </div>
  );
};

This not perfectly work but you can have imagine how it's work, hopefully:)这并不完美,但你可以想象它是如何工作的,希望:)

Maycie, this is because you are setting the property directly on the DOM. Maycie,这是因为您直接在 DOM 上设置属性。 When you render your components and access them on localhost , you are currently on the root folder of your project.当您渲染组件并在localhost上访问它们时,您当前位于项目的根文件夹中。 So what your code is trying to do is actually go one folder back.所以你的代码试图做的实际上是 go 一个文件夹。 It won't work.它行不通。 You have two alternatives:您有两种选择:

1th option第一个选项

Save your images on a public folder inside your project.将图像保存在项目内的公共文件夹中。 In the same level as your src folder, create a public folder在与您的 src 文件夹相同的级别中,创建一个公用文件夹

在此处输入图像描述

And save your backgrounds there.并将您的背景保存在那里。 This is an example from one of my projects.这是我的一个项目中的一个例子。 In my case, I would search for the background images on /assets/background/background.png .就我而言,我会在/assets/background/background.png上搜索背景图像。

Using this option (with my folder structure as example), your array would be the following, and you won't have to change the code in your component:使用此选项(以我的文件夹结构为例),您的数组将如下所示,并且您不必更改组件中的代码:

const games = [
  {
    id: 1,
    background: '/assets/background/game1.png',
    name: 'Game 1',
    description:
      'Lorem ipsum ...',
  }
];

2th option第二个选项

Set that property on your CSS.在 CSS 上设置该属性。 When you set background-image: url(../images/game1.png) in the style sheet, it will work, because when you set it, the component hasn't been rendered yet.当您在样式表中设置background-image: url(../images/game1.png)时,它将起作用,因为当您设置它时,组件还没有被渲染。 So when it is rendered, the actual URL will be one created by the compiler which will be able to find the image.因此,当它被渲染时,实际的 URL 将是由编译器创建的,它能够找到图像。 In order to do that, you would have to create a class, or something like that, for each of the games:为此,您必须为每个游戏创建一个 class 或类似的东西:

.game1{
    background-image: url('../images/game1.png'),
}

<motion.div
    transition={{ layout: { duration: 1, type: 'spring' } }}
    layout
    onClick={() => setIsOpen(!isOpen) && renderImgArr}
    key={game.id}
    class="card .game1"
>

Final considerations: I would use the first option.最后的考虑:我会使用第一个选项。 It is much cleaner and will save you to write and apply a lot of custom classes.它更简洁,可以节省您编写和应用大量自定义类的时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM