Closed pinktonio closed 3 years ago
Hi, @pinktonio! Please, provide a code sample.
Hi @maxmarinich, thanks for the quick reply. Here is the sample:
import React, { useState, useEffect } from 'react';
import AliceCarousel from 'react-alice-carousel';
import styles from './product.module.scss';
import Img from 'gatsby-image';
const Carousel = ({ product }) => {
const [activeIndex, setActiveIndex] = useState(0);
const [thumbnails, setThumbnails] = useState(
product.images.map((image, index) => (
<div className={styles.buttonContainer} key={`thumbnail-${index}`}>
<button onClick={() => slideTo(index)}>
<div
className={
index === activeIndex
? `${styles.overlay} ${styles.active}`
: styles.overlay
}
/>
<Img
className={styles.thumbnail}
fluid={image.localFile.childImageSharp.fluid}
/>
</button>
</div>
))
);
const [images] = useState(
product.images.map((image, index) => (
<Img
className={styles.image}
fluid={image.localFile.childImageSharp.fluid}
/>
))
);
const [responsive] = useState({
0: { items: 6 },
});
// Add class "active" to overlay in active thumbnail. Breaks slide transition in carousel for some indexes
useEffect(() => {
setThumbnails(
product.images.map((image, index) => (
<div className={styles.buttonContainer} key={`thumbnail-${index}`}>
<button onClick={() => slideTo(index)}>
<div
className={
activeIndex === index
? `${styles.overlay} ${styles.active}`
: styles.overlay
}
/>
<Img
className={styles.thumbnail}
fluid={image.localFile.childImageSharp.fluid}
/>
</button>
</div>
))
);
}, [activeIndex]);
const slideTo = index => setActiveIndex(index);
const slideNext = () => {
if (activeIndex < product.images.length - 1) {
setActiveIndex(activeIndex + 1);
} else {
setActiveIndex(0);
}
};
const slidePrev = () => {
if (activeIndex !== 0) {
setActiveIndex(activeIndex - 1);
} else {
setActiveIndex(product.images.length - 1);
}
};
return (
<div className={styles.sliderContainer}>
<div className={styles.activeImageCarouselContainer}>
<div className={styles.activeImageCarousel}>
<AliceCarousel
items={images}
autoHeight={true}
activeIndex={activeIndex}
infinite={true}
disableDotsControls={true}
disableButtonsControls={true}
onSlideChanged={e => setActiveIndex(e.slide)}
/>
</div>
<button className={styles.prev} onClick={slidePrev}>
Prev
</button>
<button className={styles.next} onClick={slideNext}>
Next
</button>
</div>
<div className={styles.thumbnailsCarousel}>
<AliceCarousel
items={thumbnails}
activeIndex={activeIndex}
autoWidth={true}
disableDotsControls={true}
disableButtonsControls={true}
responsive={responsive}
infinite={false}
/>
</div>
</div>
);
};
export default Carousel;
I think this is the similar error to what I was trying to explain in my mention as well.
@pinktonio, please update to v2.4. Use .alice-carousel__stage-item.__target
classname to highlight an item. Needed live example is here.
import React, { useState } from 'react';
import AliceCarousel from 'react-alice-carousel';
import 'react-alice-carousel/lib/alice-carousel.css';
const items = [
<div className="item" data-value="1">1</div>,
<div className="item" data-value="2">2</div>,
<div className="item" data-value="3">3</div>,
<div className="item" data-value="4">4</div>,
<div className="item" data-value="5">5</div>,
];
const thumbItems = (items, [setThumbIndex, setThumbAnimation]) => {
return items.map((item, i) => (
<div className="thumb" onClick={() => (setThumbIndex(i), setThumbAnimation(true))}>
{item}
</div>
));
};
const Carousel = () => {
const [mainIndex, setMainIndex] = useState(0);
const [mainAnimation, setMainAnimation] = useState(false);
const [thumbIndex, setThumbIndex] = useState(0);
const [thumbAnimation, setThumbAnimation] = useState(false);
const [thumbs] = useState(thumbItems(items, [setThumbIndex, setThumbAnimation]));
const slideNext = () => {
if (!thumbAnimation && thumbIndex < thumbs.length - 1) {
setThumbAnimation(true);
setThumbIndex(thumbIndex + 1);
}
};
const slidePrev = () => {
if (!thumbAnimation && thumbIndex > 0) {
setThumbAnimation(true);
setThumbIndex(thumbIndex - 1);
}
};
const syncMainBeforeChange = (e) => {
setMainAnimation(true);
if (e.type === 'action') {
setThumbAnimation(true);
}
};
const syncMainAfterChange = (e) => {
setMainAnimation(false);
if (e.type === 'action') {
setThumbIndex(e.item);
setThumbAnimation(false);
} else {
setMainIndex(thumbIndex);
}
};
const syncThumbs = (e) => {
setThumbIndex(e.item);
setThumbAnimation(false);
if (!mainAnimation) {
setMainIndex(e.item);
}
};
return [
<AliceCarousel
activeIndex={mainIndex}
animationType="fadeout"
animationDuration={800}
disableDotsControls
disableButtonsControls
infinite
items={items}
mouseTracking={!thumbAnimation}
onSlideChange={syncMainBeforeChange}
onSlideChanged={syncMainAfterChange}
touchTracking={!thumbAnimation}
/>,
<div className="thumbs">
<AliceCarousel
activeIndex={thumbIndex}
autoWidth
disableDotsControls
disableButtonsControls
items={thumbs}
mouseTracking={false}
onSlideChanged={syncThumbs}
touchTracking={!mainAnimation}
/>
<div className="btn-prev" onClick={slidePrev}>⟨</div>
<div className="btn-next" onClick={slideNext}>⟩</div>
</div>
]
};
Thanks for your efforts @maxmarinich! The styling of the active thumbnail works great now. I also had to wrap items
in a useMemo
to get the animations on the main carousel to work. Unfortunately the main carousel's animation now occurs after the thumbnail carousel's animation and not simultaneously. Is there a way to fix that?
I'm using two carousels which both share the same
activeIndex
through a state hook. One carousel acts as the thumbnail preview for the other by showing several slides at once with theresponsive
prop. Everything works well. However I would like to give theactiveIndex
item on the thumbnail carousel a different styling so users see it's the active slide. The items for both carousels are set using a state hook as that was the only way I could get both carousels and my custom prev/next buttons to work correctly and keep the carousel transitions onactiveIndex
change. Because the items are in a state I can not change the styling when theactiveIndex
changes without resetting the state. As mentioned that breaks the carousel transitions. Is there a way to change the items in a carousel, like changing a style, without breaking the transitions?