简体   繁体   English

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

[英]Image modal in ReactJS with slideshow using JavaScript

I am trying to use this image lightbox in a React app:我正在尝试在 React 应用程序中使用此图像灯箱:

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

This is the code sandbox link what have tried这是尝试过的代码沙箱链接

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

The image modal works fine for me.图像模式对我来说很好。 But it seems to be not working when I try to implement a slider.I want implement the slider for eachlist.但是当我尝试实现 slider 时,它似乎不起作用。我想为每个列表实现 slider。 I am getting the image data from a backend.我正在从后端获取图像数据。

Here is how I am getting all the image data:这是我获取所有图像数据的方式:

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

This is my render method for showing the images:这是我显示图像的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>
        );
    }
}

And this is the function I wrote for showing the slider:这是我为展示 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";
    }

When the image modal opens, I am tring to turn it into a slide on click on my next and previous buttons.当图像模式打开时,我想在单击我的下一个和上一个按钮时将其变成幻灯片。 What i am doing wrong?我做错了什么?

First of all, you are not using React in a correct way.首先,你没有以正确的方式使用 React。 The function showSlides uses DOM manipulation directly. function showSlides直接使用 DOM 操作。 Always avoid manipulating DOM directly instead update the state to desired value and let React handle the DOM for you.始终避免直接操作 DOM,而是将state更新为所需的值,让 React 为您处理 DOM。

Having said that, let me explain how your slider will work in a reactive way by just updating the state .话虽如此,让我解释一下您的 slider 将如何通过更新state以被动方式工作。 So far you have managed to make the modal work.到目前为止,您已经设法使模态工作。 The slider logic will be as follows ( codesandbox link ): slider 逻辑如下( 代码框链接):

Your imageListData is a list of list.您的 imageListData 是一个列表列表。 For clarity I will be referring the outer list as section为清楚起见,我将外部列表称为section

1 - On clicking any image, update the state with following data: 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 - On clicking the Next or Previous button, we will only update the state mentioned in step 1 and the slider will work. 2 - 单击NextPrevious按钮时,我们将仅更新步骤 1 中提到的 state,slider 将起作用。 The only thing to think about is the logic to update the state with correct values.唯一需要考虑的是用正确的值更新 state 的逻辑。 I will try to explain it through comments.我将尝试通过评论来解释它。 All the logic is in plusSlides function.所有逻辑都在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
    });
  }

I hope it helps.我希望它有所帮助。 Let me know if there is any doubt.如果有任何疑问,请告诉我。 The working code is available in the link工作代码在链接中可用

You need to save images in an array: Save those images into state then change the img inside of "mySlides" to be like this:您需要将图像保存在数组中:将这些图像保存到 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