我正在用Nextjs、React和Sanity作为CMS构建一个项目。
其中一个主要组件将是一个图像库,当您单击其中一个图像时,您将打开一个图像滑块库。图像是从CMS传入的数组。
它大致基于这个网站的工作方式。。https://www.garrodkirkwood.com/projects/
目前,我正在使用一个简单的setState切换来隐藏和显示图像库和幻灯片。代码远非完美,因为我意识到还有很多事情要做。
我需要帮助的是。。。。
我需要找到一种方法,将点击图像的索引传递给事件监听器,这样当你点击图像时,你就可以在同一图像上打开幻灯片。
我真的希望这是有道理的。
然后,用户将通过点击"显示缩略图"退出幻灯片放映
import React,{useState,useEffect,useRef}from"反应";;从"导入{css,jsx}@情感/核心";;从"导入ImageSliderContent"/ImageSliderContent";;从"导入样式"/ImageGrid.module.css;;从"导入ImageGrid"/ImageGrid";;从"导入ImageSlide"/ImageSlide";;从"导入箭头"/箭头";;从"导入点"/点";;从"导入imageUrlBuilder@健全性/图像url";;从"../.."导入客户端/客户端";;const-builder=imageUrlBuilder(客户端);const LocationsImageGallery=(props)=>{const{caption,image}=道具;const-images=props.image;const[state,setState]=使用状态({翻译:0,转变:0.45,活动幻灯片:0,});const[showSlider,setShowSlider]=useState(false);const{translate,transition,activeSlide,_slides}=状态;const size=useWindowSize();const-transitionRef=useRef();函数useWindowSize(){const isClient=窗口的类型==";对象";;函数getSize(){返回{width:isClient?window.innerWidth:未定义,};}const[windowSize,setWindowSize]=useState(getSize);useEffect(()=>{if(!isClient){return false;}函数句柄Resize(){setWindowSize(getSize());}window.addEventListener("resize",handleResize);return()=>window.removeEventListener("resize",handleResize);},[]);return windowSize;}const nextSlide=()=>{if(activeSlide===images.length-1){return setState({状态翻译:0,活动幻灯片:0,});}setState({状态activeSlide:activeSlide+1,translate:(activeSlide+1)*size.width,});};const prevSlide=()=>{if(activeSlide===0){return setState({状态translate:(images.length-1)*size.width,activeSlide:images.length-1,});}setState({状态activeSlide:activeSlide-1,translate:(activeSlide-1)*size.width,});};const show=()=>{setShowSlider(true);};const hide=()=>{setShowSlider(false);};返回(<div className={styles.root}><div className={styles.imageGridContainer}>{images.map((image,index)=><div className={styles.imageContainer}onClick={show}><imgsrc={builder.image(image).auto("format").width(2000).url()}className={styles.image}alt={image.cation}key={index}/><p className={styles.caption}>{image\caption}<p><div>))}<div>{显示Slider(<div className={styles.imageGalleryContainer}><div css={ImageSliderCSS}><ImageSliderContenttranslate={translate}transition={transition}width={size.width*images.length}>{images.map((image,index)=><图像幻灯片关键字={图像+索引}content={builder.image(image).auto("format").width(2000).url()}>lt/图片幻灯片>))}<ImageSliderContent><箭头方向=";"左";handleClick={prevSlide}/><箭头方向=";右";handleClick={nextSlide}/><点幻灯片={images}activeSlide={activeSlide}/><div><a href="quot;onClick={hide}>显示缩略图<a><div>)}<div>);};const ImageSliderCSS=css`位置:相对;高度:500px;宽度:750px;边距:0自动;溢出:隐藏;`;导出默认LocationsImageGallery
更新通过索引点击事件
import React, { useState, useEffect, useRef } from "react";
import { css, jsx } from "@emotion/core";
import ImageSliderContent from "./ImageSliderContent";
import styles from "./LocationsImageGallery.module.css";
import ImageGrid from "./ImageGrid";
import ImageSlide from "./ImageSlide";
import Arrow from "./Arrow";
import Dots from "./Dots";
import imageUrlBuilder from "@sanity/image-url";
import client from "../../client";
const builder = imageUrlBuilder(client);
const LocationsImageGallery = (props) => {
const { caption, image } = props;
const images = props.image;
const [state, setState] = useState({
translate: 0,
transition: 0.45,
activeSlide: 0,
});
const [showSlider, setShowSlider] = useState(false);
const [showGrid, setShowGrid] = useState(true);
const { translate, transition, activeSlide, _slides } = state;
const size = useWindowSize();
const transitionRef = useRef();
function useWindowSize() {
const isClient = typeof window === "object";
function getSize() {
return {
width: isClient ? window.innerWidth : undefined,
};
}
const [windowSize, setWindowSize] = useState(getSize);
useEffect(() => {
if (!isClient) {
return false;
}
function handleResize() {
setWindowSize(getSize());
}
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return windowSize;
}
const nextSlide = () => {
if (activeSlide === images.length - 1) {
return setState({
...state,
translate: 0,
activeSlide: 0,
});
}
setState({
...state,
activeSlide: activeSlide + 1,
translate: (activeSlide + 1) * size.width,
});
};
const prevSlide = () => {
if (activeSlide === 0) {
return setState({
...state,
translate: (images.length - 1) * size.width,
activeSlide: images.length - 1,
});
}
setState({
...state,
activeSlide: activeSlide - 1,
translate: (activeSlide - 1) * size.width,
});
};
const show = (index) => {
setShowGrid(false);
setShowSlider(true);
setState({ activeSlide: index });
};
const hide = () => {
setShowSlider(false);
setShowGrid(true);
};
return (
<div className={styles.root}>
<div className={styles.header}>
<a href="/locations">X</a>
</div>
{showGrid && (
<div className={styles.imageGrid}>
<div className={styles.imageGridContainer}>
{images.map((image, index, caption) => (
<div className={styles.imageContainer} onClick={() => show(index)}>
<img
src={builder.image(image).auto("format").width(2000).url()}
className={styles.image}
alt={image.caption}
key={index}
/>
<p className={styles.caption}>{image.caption}</p>
</div>
))}
</div>
</div>
)}
{showSlider && (
<div className={styles.imageGalleryContainer}>
<div className={styles.imageSlider}>
<ImageSliderContent
translate={translate}
transition={transition}
width={size.width * images.length}
>
{images.map((image, index, caption) => (
<>
<ImageSlide
key={image + index}
content={builder.image(image).auto("format").url()}
></ImageSlide>
</>
))}
</ImageSliderContent>
<Arrow direction="left" handleClick={prevSlide} />
<Arrow direction="right" handleClick={nextSlide} />
</div>
<div className={styles.infoBar}>
<p className={styles.infoCaption}>
Locations / <span>{image.caption}</span>
</p>
<a href="" onClick={hide} className={styles.infoThumbnails}>
Show Thumbnails
</a>
</div>
</div>
)}
</div>
);
};
export default LocationsImageGallery;
此版本似乎没有更新activeSlide的状态console.log和状态。。。
LocationsImageGallery.js?0692:94 {activeSlide: 8, state: {…}} activeSlide: 8 state: activeSlide: 0 transition: 0.45 translate: 0 proto: Object proto: Object
您可以更改show函数,将幻灯片索引作为参数:
const show = (index) => {
// set activeSlide accordingly
setState(...)
setShowSlider(true);
}
然后,在onClick函数中,传入索引:
onClick={() => show(index)}
如果我是您,我可能会删除showSlider
状态,并使用activeSlide: -1
或activeSlide: null
表示不显示滑块。
你能试着在img元素中添加一个自定义属性吗
data-index = {index}
然后你可以回到你原来的onClick处理程序的方式
onClick={show}
然后,您的show函数可以获取自定义属性,如下所示:
const show = (e) => {
setShowGrid(false);
setShowSlider(true);
setState({ activeSlide: e.target.getAttribute("data-index") });
};
在show函数中,您正在将状态设置为一个新对象。这将导致丢失状态对象中的其他数据。
const show = (index) => {
setShowGrid(false);
setShowSlider(true);
setState({ activeSlide: index });
};
// instead use
const show = (index) => {
setShowGrid(false);
setShowSlider(true);
setState(prevState => ({ ...prevState, activeSlide: index }));
};