使用Javacript的带有幻灯片的reactjs中的图像模态

时间:2020-06-14 11:20:04

标签: javascript reactjs lightbox image-gallery

我正在尝试在React应用中使用此图片灯箱:

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

这是尝试的代码沙箱链接

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

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

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

{
    "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>
        );
    }
}

这是我编写的用于显示滑块的功能:

    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";
    }

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

2 个答案:

答案 0 :(得分:1)

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

话虽如此,我仅通过更新state来说明您的滑块如何以响应方式工作。到目前为止,您已经成功完成了模态工作。滑块逻辑如下(codesandbox link):

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

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

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中提到的状态,并且滑块将起作用。唯一需要考虑的是用正确的值更新状态的逻辑。我将尝试通过评论来解释它。所有逻辑都在plusSlides函数中。

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
    });
  }

我希望它会有所帮助。让我知道是否有任何疑问。工作代码位于link

答案 1 :(得分:0)

您需要将图像保存在数组中:将这些图像保存为状态,然后将“ mySlides”内部的img更改为这样:

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