繁体   English   中英

ReactJS 中的图像模式,带有幻灯片,使用 JavaScript

[英]Image modal in ReactJS with slideshow using JavaScript

我正在尝试在 React 应用程序中使用此图像灯箱:

https://www.w3schools.com/howto/howto_js_lightbox.asp

这是尝试过的代码沙箱链接

https://codesandbox.io/s/reactjs-practice-vbxwt

图像模式对我来说很好。 但是当我尝试实现 slider 时,它似乎不起作用。我想为每个列表实现 slider。 我正在从后端获取图像数据。

这是我获取所有图像数据的方式:

{
    "results": [{
        "data": [{
            "id": "f06f2cdf-1bb8-4388-a655-4e916a2703ce",
            "visitRequirementList": [{
                "imageName": "dining pic 1",
                "imagePath": "visitImageDirectory/0297b1ef-644b-45fc-9760-4e5693f54ac0.png",
            }, {
                "imageName": "dining pic 2",
                "imagePath": "visitImageDirectory/1b4915c1-733a-4bdb-a8d7-59ce3a095d44.png",
            }]
        }, {
            "id": "ce059d7a-d3d4-462c-a90f-62be13f24a29",
            "visitRequirementList": [{
                "imageName": "bedroom pic 1",
                "imagePath": "visitImageDirectory/64960b86-f9bf-4de9-816f-f27487245c53.png",
            }]
        }]
    }],
    "message": "data Found",
    "status": "success"
}

这是我显示图像的render方法:

import React, { Component } from 'react';

export default class extends Component {
    state = {
        showModal: false,
        caption: '',
        modalSrc: '',
        ioImageListing: [],

        // ...rest of the state
    };
    componentDidMount() {
        this.getAllProjectRequirementImageList();
    }
    getAllProjectRequirementImageList = () => {
        axios.get(this.state.apiUrl+'/api/v1/visitRequirement/getAllByProjectId', {
            params: {   projectId: this.state.projectId }
        }).then((response) => {
            console.log("get with list ImageData",response.data.data);
            this.setState({ ioImageListing: response.data.data  });
        }).catch((error)=>{  console.log("error",error); this.setState({ ioImageListing: []  });   });
    }



    render() {
        return (
            <div>
                <div style={{}}>
                    {this.state.ioImageListing.map((io, key) =>
                        <Grid container spacing={24}>
                            {io.visitRequirementList.map((pic, key) => [
                                <Grid style={{position: 'relative'}} item xs={3} key={key}>
                                <span key={key}>
                                    <img
                                        src={this.state.apiUrl + '/api/v1/visitImageRequirementInfo/getImageByImagePathId?imagePath=' + pic.imagePath}
                                        onClick={() => {
                                            this.setState({
                                                showModal: true,
                                                caption: `${pic.imageName}`,
                                                slideIndex: `${io.visitRequirementList.length}`,
                                                modalSrc: `${this.state.apiUrl}/api/v1/visitImageRequirementInfo/getImageByImagePathId?imagePath=${pic.imagePath}`,
                                                count: `${key}`
                                            });
                                        }}
                                    />
                                </span>
                                </Grid>
                            ])}
                        </Grid>
                    )}
                </div>
                <div id="myModal" className="modal" style={{display: this.state.showModal ? 'block' : 'none'}}>
                    <div>
                        <span className="close" onClick={() => this.setState({showModal: false})}>&times;</span>
                        <div className="mySlides"><img className="modal-content" id="img01" src={this.state.modalSrc}/>
                        </div>
                        <a className="prev" onClick={() => {
                            this.plusSlides(-1)
                        }}>&#10094;</a>
                        <a className="next" onClick={() => {
                            this.plusSlides(1)
                        }}>&#10095;</a>
                    </div>
                </div>
            </div>
        );
    }
}

这是我为展示 slider 而写的 function:

    plusSlides = (n) => {
        var slideIndex=parseFloat(this.state.count);
        slideIndex=slideIndex+n
        this.setState({ count: slideIndex  });

        this.showSlides(slideIndex, n);
    }

  showSlides(slideIndex,n) {
        var i;
        var slides = document.getElementsByClassName("mySlides");
        if (n > slides.length) {slideIndex = 1}
        if (n < 1) {slideIndex = slides.length}
        for (i = 1; i < slides.length; i++) {
            slides[i].style.display = "none";
        }
        slides[slideIndex-1].style.display = "block";
    }

当图像模式打开时,我想在单击我的下一个和上一个按钮时将其变成幻灯片。 我做错了什么?

首先,你没有以正确的方式使用 React。 function showSlides直接使用 DOM 操作。 始终避免直接操作 DOM,而是将state更新为所需的值,让 React 为您处理 DOM。

话虽如此,让我解释一下您的 slider 将如何通过更新state以被动方式工作。 到目前为止,您已经设法使模态工作。 slider 逻辑如下( 代码框链接):

您的 imageListData 是一个列表列表。 为清楚起见,我将外部列表称为section

1 - 单击任何图像时,使用以下数据更新 state:

showModal // to toggle the visibility of modal
caption // caption for current image
modalSrc // current image source
sectionIndex // current index of outer list
imageIndex // index of current image
currentSectionLength // outer list, i.e. section length

2 - 单击NextPrevious按钮时,我们将仅更新步骤 1 中提到的 state,slider 将起作用。 唯一需要考虑的是用正确的值更新 state 的逻辑。 我将尝试通过评论来解释它。 所有逻辑都在plusSlides function 中。

plusSlides = n => {
    const { ioImageListing, imageIndex, sectionIndex, currentSectionLength } = this.state; // extract all the current values from the state

    const nextIndex = imageIndex + n; // add or subtract 1 to get nextIndex. This is temporary. We will use this to determine next image on the slider.
    const numberOfSections = ioImageListing.length; // count of number of outer list.

    if (nextIndex < 0 && sectionIndex === 0) {
      // this means we are at the 1st image of 1st section. Hence no more left navigation, and the function returns. No more execution.
      alert("NO MORE LEFT IMAGE");
      return;
    }

    if (sectionIndex === numberOfSections - 1 && nextIndex > ioImageListing[numberOfSections - 1].visitRequirementList.length - 1) {
      // this condition says we are at the last image of last section. Hence no more right navigation, and the function returns. No more execution.
      alert("NO MORE RIGHT IMAGE");
      return;
    }

    let nextImage, nextImageIndex, nextSectionIndex, nextSectionLength; // these variables will hold the value for next image to be shown determined by the following logic

    if (nextIndex >= 0 && nextIndex < currentSectionLength) {
      // if the nextIndex is >=0 and less than the length of currentSectionLength, it means our next/previous image is in the same section. So we only need to update nextImage data whereas section data remains same
      nextImage = ioImageListing[sectionIndex].visitRequirementList[nextIndex];
      nextImageIndex = nextIndex;
      nextSectionIndex = sectionIndex;
      nextSectionLength = currentSectionLength;
    } else if (nextIndex < 0) {
      // if the nextIndex is less than 0, it means our previous image is in the previous section and it has to be the last image of previous section. So we update both nextImage data and section data accordingly.
      nextImage = ioImageListing[sectionIndex - 1].visitRequirementList[ioImageListing[sectionIndex - 1].visitRequirementList.length - 1];
      nextImageIndex = ioImageListing[sectionIndex - 1].visitRequirementList.length - 1;
      nextSectionIndex = sectionIndex - 1;
      nextSectionLength = ioImageListing[sectionIndex - 1].visitRequirementList.length
    } else {
      // atlast if the nextIndex >= currentSectionLength, it means our next image is in the next section and it has to be the first image of next section. So we update both nextImage data and section data accordingly.
      nextImage = ioImageListing[sectionIndex + 1].visitRequirementList[0];
      nextImageIndex = 0;
      nextSectionIndex = sectionIndex + 1;
      nextSectionLength = ioImageListing[sectionIndex + 1].visitRequirementList.length;
    }

    // finally we update the state with current next values, and the slider works as expected.
    this.setState({
      caption: nextImage.imageName,
      modalSrc: nextImage.imagePath,
      imageIndex:nextImageIndex,
      sectionIndex: nextSectionIndex,
      currentSectionLength:nextSectionLength
    });
  }

我希望它有所帮助。 如果有任何疑问,请告诉我。 工作代码在链接中可用

您需要将图像保存在数组中:将这些图像保存到 state 然后将“mySlides”中的 img 更改为如下所示:

/** -- snip -- **/
// Inside of "mySlides" div
<img 
    className="modal-content" 
    id="img01" 
    src={this.state.images[this.state.count]}
/>

暂无
暂无

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

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