簡體   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