React实现多图片预览功能、预览图上下张切换(实战示例)

前言

在React项目中,展示和预览多张图片是一种常见的需求。本篇帖子将介绍如何使用React和antd库来实现这一功能,并探讨如何在预览模态框中切换到前一张或后一张图片。

背景

我们将以一个OCR图像列表展示的示例来演示代码的运用。假设我们有一个OCR系统,可以将图片文件中的文本提取出来。我们希望在前端展示从OCR系统返回的图像列表,并支持点击图片来进行预览。此外,我们还希望在预览模态框中能够实现切换到前一张或后一张图片的功能。下面是具体的操作示例:

操作示例:

  1. 首先,我们需要导入所需的组件和hooks:

    import React, {
          
           useEffect, useState } from 'react';
    import {
          
           Row, Col, Modal} from 'antd';
    
  2. 接下来,我们定义一个Splitor组件,该组件将用于展示多张图片和实现预览功能:

    const Splitor: React.FC = () => {
          
          
      const [ocrImageList, setOcrImageList] = useState<ETEST.ImageInfo[]>([]); // 图片列表的状态
      const [visible, setVisible] = useState(false); // 大图预览的可见性状态
      const [currentImage, setCurrentImage] = useState(""); // 当前点击的图片路径
    
      useEffect(() => {
          
          
        const intervalId = setInterval(updateOcrImageList, 1000 * 10); // 创建定时器,每 10 秒钟调用一次 updateOcrImageList 函数
        // 组件卸载时清除定时器
        return () => {
          
          
          clearInterval(intervalId);
        };
      }, []);
    
      const updateOcrImageList = async () => {
          
          
        try {
          
          
          const msg = await ocrList(); // 调用 ocrList 函数获取最新的图片列表
          console.log('ocrList响应数据=', msg.data);
          if (msg.isSuccess && msg.data.length > 0) {
          
          
            setOcrImageList(msg.data); // 更新图片列表状态
          }
        } catch (error) {
          
          
          console.error(error);
        }
      };
    
      const handleImageClick = (imagePath: string) => {
          
          
        setCurrentImage(imagePath); // 设置当前点击的图片路径
        setVisible(true); // 显示大图预览
      };
    
      return (
        <Row gutter={
          
          24}>
          {
          
          /* 遍历渲染图片列表 */}
          {
          
          ocrImageList.map((image) => (
            {
          
          /* 图片容器 */}
            <Col span={
          
          4} key={
          
          image.id}>
              {
          
          /* 图片元素 */}
              <div style={
          
          {
          
           border: '1px solid #ccc', borderRadius: '8px', padding: '16px', marginBottom: '20px' }}>
                <img
                  src={
          
          image.imgPath}
                  alt={
          
          image.id}
                  style={
          
          {
          
           width: '100%', objectFit: 'contain', cursor: 'pointer' }}
                  onClick={
          
          () => handleImageClick(image.imgPath)} // 点击图片时调用 handleImageClick 函数
                />
              </div>
              {
          
          /* 图片描述 */}
              <div style={
          
          {
          
           textAlign: 'center' }}>{
          
          image.content}</div> // 显示图片内容
            </Col>
          ))}
          
          {
          
          /* 大图预览弹窗 */}
          <Modal visible={
          
          visible} onCancel={
          
          () => setVisible(false)} footer={
          
          null} className="custom-modal">
            <img src={
          
          currentImage} alt="Preview" style={
          
          {
          
           height: "100%", width: "100%" }} />
          </Modal>
        </Row>
      );
    };
    

    在上述代码中,我们使用useState来维护了多个状态变量,包括ocrImageList(图片列表数据)、visible(控制模态框的显示与隐藏)、currentImage(当前要预览的图片路径)。

    我们通过updateOcrImageList函数来异步获取ocrImageList数据,并在handleImageClick函数中实现了点击图片触发预览的功能。

    在返回的JSX中,我们通过遍历ocrImageList并使用antdColRow组件来展示图片。图片被点击后,会调用handleImageClick函数来设置currentImagevisible状态,从而展示预览模态框。

拓展(预览图片切换):

  1. 导入新增
   import Lightbox from 'react-image-lightbox';
   import 'react-image-lightbox/style.css';
  1. 在预览模态框中切换到前一张或后一张图片。以下是相应的代码更改调整:
// ...

// 点击图片触发预览功能
const handleImageClick = (index: number) => {
    
    
    setPreviewIndex(index);
};

// 关闭预览
const handleClosePreview = () => {
    
    
    setPreviewIndex(-1);
};

// 创建预览图片路径数组
const previewImages = ocrImageList.map((image) => image.imgPath);

return (
    <Row gutter={
    
    24}>
        {
    
    /* 遍历渲染图片列表 */}
        {
    
    ocrImageList.map((image, index) => (
            <Col span={
    
    4} key={
    
    image.id}>
                {
    
    /* 图片容器 */}
                <div style={
    
    {
    
     border: '1px solid #ccc', borderRadius: '8px', padding: '16px', marginBottom: '20px' }}>
                    {
    
    /* 图片元素 */}
                    <img
                        src={
    
    image.imgPath}
                        alt={
    
    image.id}
                        style={
    
    {
    
     width: '100%', objectFit: 'contain', cursor: 'pointer' }}
                        onClick={
    
    () => handleImageClick(index)} // 点击图片时调用 handleImageClick 函数
                        />
                </div>
                {
    
    /* 图片描述 */}
                <div style={
    
    {
    
     textAlign: 'center' }}>{
    
    image.content}</div>
            </Col>
        ))}

        {
    
    /* 如果正在预览图片,渲染预览模态框 */}
        {
    
    previewIndex !== -1 && (
            <Lightbox
                // 配置预览相关属性
                mainSrc={
    
    previewImages[previewIndex]}
                nextSrc={
    
    previewImages[(previewIndex + 1) % previewImages.length]}
                prevSrc={
    
    previewImages[(previewIndex + previewImages.length - 1) % previewImages.length]}
                onCloseRequest={
    
    handleClosePreview}
                onMovePrevRequest={
    
    () => setPreviewIndex((previewIndex + previewImages.length - 1) % previewImages.length)}
                onMoveNextRequest={
    
    () => setPreviewIndex((previewIndex + 1) % previewImages.length)}
                />
        )}
    </Row>
);

// ...

在上面的代码中,我们使用了react-image-lightbox库来实现图片预览功能。当用户点击图片时,将打开预览模态框,并可以在预览模态框中切换到前一张或后一张图片。关闭预览模态框时,预览索引将被重置为-1

注意,上述代码仅为示例。你可以根据自己的需求进行进一步的样式和逻辑调整。

总结

本篇帖子介绍了如何使用React和antd库实现多图片预览功能,并在预览模态框中实现了切换到前一张或后一张图片的拓展功能。通过对状态的管理和处理用户点击事件,我们可以轻松地实现这一功能。希望本篇文章能帮助你理解和应用多图片预览的技术实现方法。

猜你喜欢

转载自blog.csdn.net/Da_zhenzai/article/details/133363236