Ant Design Card 组件展示图片

本文介绍了如何在AntDesign框架中使用Card组件展示图片,包括理解组件结构、隐藏内容区域,实现下拉加载更多和分页加载图片列表,以及显示文件名和卡片操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Ant Design Card 组件展示图片

官方文档:
Card卡片组件 https://4x.ant.design/components/card-cn/#Card
ProCard高级卡片 https://procomponents.ant.design/components/card

Card卡片
通用卡片容器。

何时使用#
最基础的卡片容器,可承载文字、列表、图片、段落,常用于后台概览页面。

理解card组件结构

在这里插入图片描述如上图,Card组件分成如上组成部分,

  1. header这部分 是,title属性来配置
  2. 卡片封面 是sove属性来配置
  3. 卡片内容区域 Card.Meta 来配置
  4. 卡片动作部分,是action属性来配置

隐藏卡片内容区域

我们使用一个名为 custom-card 的类名来设置卡片容器的样式,并通过 bodyStyle 属性将内容区域的样式设置为 display: none,完全隐藏内容区域。

在这里插入图片描述

下拉时加载图片卡片

需求是展示支持分页的图片,并且希望在下拉时加载新的图片卡片,可以使用 Ant Design 的 List 组件和滚动事件来实现。

容器的高度自适应,并且卡片在宽度不足时自动换行显示,可以使用 CSS 中的 Flexbox 布局来实现

  return (
    <div style={{ display: 'flex', flexWrap: 'wrap' }} onScroll={handleScroll}>
      <List
        grid={{ gutter: 16, column: 4 }}
        dataSource={data}
        loading={loading}
        loadMore={loading ? <Spin /> : undefined}
        renderItem={(item) => (
          <List.Item style={{ flexBasis: '25%' }}>
            <Card cover={<img alt="Example Image" src={item} />} />
          </List.Item>
        )}
      />
    </div>
  );

我们将容器的样式设置为 display: ‘flex’,并使用 flexWrap: ‘wrap’ 让卡片在宽度不足时自动换行显示。

将卡片项的样式设置为 flexBasis: ‘20%’,这样每个卡片项将占据容器宽度的 20%。通过将 column 属性设置为 5,我们让 List 组件一行显示 5 个卡片。

加载更多

将List组件的 loadMore 属性的值设置为一个函数,用于触发加载更多数据的操作。

在这里插入图片描述
将 handleLoadMore 定义为一个函数,用于触发加载更多数据的操作。如果正在加载中,将 handleLoadMore 设置为空函数;否则,将其设置为 fetchData 函数,以触发加载更多数据。

通过这个修改,当滚动到底部时,将触发加载更多数据的操作,并通过模拟异步加载数据的方式展示加载更多的效果。

代码

import { List, Card, Spin } from 'antd';
import { useEffect, useState } from 'react';

const ImageList: React.FC = () => {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState<string[]>([]);

  const fetchData = () => {
    setLoading(true);

    // 模拟异步加载数据
    setTimeout(() => {
      const newData = Array.from({ length: 10 }, (_, index) => `https://via.placeholder.com/300?text=Image${index + 1}`);
      setData((prevData) => [...prevData, ...newData]);
      setLoading(false);
    }, 1000);
  };

  useEffect(() => {
    fetchData();
  }, []);

  const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
    const { scrollTop, clientHeight, scrollHeight } = e.currentTarget;
    const isAtBottom = scrollTop + clientHeight === scrollHeight;

    if (isAtBottom && !loading) {
      fetchData();
    }
  };

  const handleLoadMore = loading ? () => {} : null;

  return (
    <div style={{ display: 'flex', flexWrap: 'wrap' }} onScroll={handleScroll}>
      <List
        grid={{ gutter: 16, column: 5 }}
        dataSource={data}
        loading={loading}
        loadMore={handleLoadMore}
        renderItem={(item) => (
          <List.Item style={{ flexBasis: '20%' }}>
            <Card cover={<img alt="Example Image" src={item} />} />
          </List.Item>
        )}
        
      />
    </div>
  );
};

export default ImageList;

分页的方式加载图片列表【推荐】

使用分页的方式可以更加可控地展示数据,并提供更好的用户体验。通过显示当前页数、总页数以及提供页码切换的功能,用户可以清楚地知道当前所处的页面位置,并且可以自由地在不同页面之间进行切换。

实现思路

我更喜欢使用分页而不是加载更多的方式来展示数据,您可以结合 Ant Design 的 Pagination 组件来实现分页效果

代码demo

import { List, Card, Pagination } from 'antd';
import { useEffect, useState } from 'react';

const ImageList: React.FC = () => {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState<string[]>([]);
  const [page, setPage] = useState(1);
  const pageSize = 12; // 每页显示的图片数量

  const fetchData = () => {
    setLoading(true);

    // 模拟异步加载数据
    setTimeout(() => {
      const newData = Array.from({ length: pageSize }, (_, index) => `https://via.placeholder.com/300?text=Image${(page - 1) * pageSize + index + 1}`);
      setData(newData);
      setLoading(false);
    }, 1000);
  };

  useEffect(() => {
    fetchData();
  }, [page]);

  const handlePageChange = (pageNumber: number) => {
    setPage(pageNumber);
  };

  return (
    <div>
      <List
        grid={{ gutter: 16, column: 4 }}
        dataSource={data}
        loading={loading}
        renderItem={(item) => (
          <List.Item>
            <Card cover={<img alt="Example Image" src={item} />} />
          </List.Item>
        )}
      />
      <Pagination current={page} pageSize={pageSize} total={100} onChange={handlePageChange} />
    </div>
  );
};

export default ImageList;

缩略图

import { List, Card, Pagination } from 'antd';
import axios from 'axios';
import { useEffect, useState } from 'react';

const ImageList: React.FC = () => {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState<string[]>([]);
  const [page, setPage] = useState(1);
  const pageSize = 12; // 每页显示的图片数量

  const fetchData = async () => {
    setLoading(true);

    try {
      let token = localStorage.getItem('token');
      if (null === token) {
          token = '';
      }

      const response = await axios.get('/api/v1/imageManage/listThumbImages', {
        params: {
          page: page,
          pageSize: pageSize,
        },
        headers: {
          Authorization: `Bearer ${token}`,  // 替换为您的 Bearer Token
        },
      });

      console.log("listThumbImages  response data: ", response.data)
		  //前端只通过 Base64 字符串无法确定图片的格式。Base64 只是一种表示图像数据的编码方式,并不能直接指示图像的格式。
		  //在前端展示 Base64 图片时,通常需要提供图像的 MIME 类型来指示图像的格式。MIME 类型是一种标识数据类型的字符串,例如 "image/jpeg" 表示 JPEG 图像,"image/png" 表示 PNG 图像。
		  // 将图像的 MIME 类型一并返回,这样前端就能够根据提供的 MIME 类型来正确解析和显示图像

      //根据文件名组装图像的 MIME 类型
      const updatedData = response.data.map(item => {
        const fileExtension = item.FileName.split('.').pop().toLowerCase();
        let imageFormat = "image/jpeg"; // 默认格式为 JPEG
        if (fileExtension === "png") {
          imageFormat = "image/png";
        } else if (fileExtension === "gif") {
          imageFormat = "image/gif";
        }
  
        return {
          ...item,
          ImageFormat: imageFormat,
        };
      });


      setData(updatedData);
      setLoading(false);
    } catch (error) {
      console.error('Error fetching thumbnails:', error);
      setLoading(false);
    }
  };


  useEffect(() => {
    fetchData();
  }, [page]);


  const handlePageChange = (pageNumber: number) => {
    setPage(pageNumber);
  };

  return (
    <div>
      <List
        grid={{ gutter: 16, column: 6 }}
        dataSource={data}
        loading={loading}
        renderItem={(item: any) => (
          <List.Item>
            <Card
              cover={
                item.ThumbnailBase64 ? (
                  <img alt="Example Image" src={`data:${item.ImageFormat};base64,${item.ThumbnailBase64}`} />
                ) : (
                  <div>No Thumbnail</div>
                )
              }
            />
          </List.Item>
        )}
      />
      <Pagination current={page} pageSize={pageSize} total={100} onChange={handlePageChange} />
    </div>
  );
};

export default ImageList;

代码细节解释:

  1. 每行显示多个?
<List
    grid={{ gutter: 16, column: 6 }}  

grid 属性设置为 { gutter: 16, column: 6 },表示创建一个具有 6 列的网格布局,并且网格项之间的间距为 16 像素。

在 List 组件中,grid 属性用于定义网格布局的样式。它接受一个对象作为参数,该对象包含两个属性:gutter 和 column。

  • gutter:用于设置网格项之间的间距。可以将其设置为一个数字来表示像素值,或者设置为一个数组 [水平间距, 垂直间距] 来分别表示水平和垂直方向上的间距。
  • column:用于设置网格的列数。可以将其设置为一个数字来表示列数,或者设置为一个数组 [列数, 列宽] 来分别表示列数和列宽。
  1. 分页?
    如下,添加 分页组件Pagination即可
    在这里插入图片描述
    为 Card 添加预览、下载和删除功能的按钮

通过以上修改,预览、下载和删除的图标会在鼠标悬停在 Card 上时放大并显示。
在上述 CSS 文件中,我们通过设置 .image-actions 类的样式来实现鼠标悬停时的显示效果,并使用 .custom-card:hover .image-actions 选择器来控制悬停时图标的显示。我们还设置了 .icon 类的样式,用于调整图标的大小和颜色。

实现鼠标悬停时图标变色的效果,你可以使用 CSS 的 :hover 伪类选择器来设置图标的样式

  .icon-wrapper {
    display: flex;
    gap: 10px;
  }
  
  .icon-wrapper .icon {
    font-size: 24px;
    color: #000;
    cursor: pointer;
  }
  
  .icon-wrapper .icon:hover {
    color: #ff0000; /* 设置图标的悬停颜色 */
  }

在card组件下发显示图片文件名

Meta官方说明:https://4x.ant.design/components/card-cn/#Card.Meta

要将文件名显示在卡片的底部,您可以在 Card 组件中添加一个位于底部的 Meta 组件,并将文件名作为 Meta 组件的 description 属性。

在这里插入图片描述
可以利用 Card.Meta 支持更灵活的内容

卡片操作

官方文档:https://4x.ant.design/components/card-cn/#Card
使用 actions 卡片操作组,位置在卡片底部

在这里插入图片描述

分页

分页组件用法:

<Pagination current={page} pageSize={pageSize} total={totalRecords} onChange={handlePageChange} />

分页相关变量

  const [page, setPage] = useState(1);
  const pageSize = 10; // 每页显示的图片数量
  const [totalRecords, setTotalRecords] = useState(0);

在 fetchData 函数中的成功回调中,使用 setPage 和 setTotalRecords来更新 page 和 totalRecords状态。这样就能确保在获取数据后及时更新这些状态。

获取数据后,设置分页信息变量

// 获取分页信息
  const pagination = responseData.pagination;
  console.log("获取分页信息 pagination: ",pagination)

  setPage(pagination.page);
  setTotalRecords(pagination.totalItems);

注意:在 Pagination 组件中,total 属性应该是总记录数。前端会根据 total 属性和每页显示的数量自动计算出分页的页数。这样做可以确保在数据更新或动态加载时,分页组件能够正确地显示页码和处理分页逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西京刀客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值