Reputation: 123
I'm a junior dev and am struggling with an issue where there is a carousel with about 10 cards on top of the page. All cards do not fit at once on the screen, so there are 2 arrows in the corner to scroll them (arrow left and arrow right). When you click arrow right, the cards scroll to the end and when you click arrow left they move backwards from right to left.
How can I make it that when you click mouse down and hold the images and drag them they move left or right? I need to make them move not only with arrow clicks but with mouse drag also... Do i need to use some library (i found react-hammerjs, but didn't find any good docs/examples how to use it)? Thank you in advance for your help
Here's some code to reference:
export const CardsBlock = () => {
const scrollContainer = useRef(null)
const [scrolled, setScrolled] = useState(false)
const dispatch = useDispatch()
useEffect(() => {
const resizeListener = (e) => {
if (e.target.outerWidth <= sizes.mobile) {
setScrolled(null)
} else {
setScrolled(false)
}
}
window.addEventListener('resize', resizeListener)
return () => {
window.removeEventListener('resize', resizeListener)
}
}, [])
useEffect(() => {
if (scrolled) {
scrollTo(scrollContainer.current, scrollContainer.current.offsetWidth)
} else {
scrollTo(scrollContainer.current, 0)
}
}, [scrolled])
return (
<Well>
<Container>
<Wrapper padding={'0 0 16px'} justify={'space-between'} align={'center'}>
<TitleText width={'auto'}>{translator('specilization.title', true)}</TitleText>
<ArrowsContainer>
<Icon
onClick={() => setScrolled(false)}
cursor={'pointer'}
type={'arrow_left'}
color={scrolled ? 'black4' : 'black1'}
/>
<Icon
onClick={() => setScrolled(true)}
cursor={'pointer'}
type={'arrow_right'}
color={scrolled ? 'black1' : 'black4'}
/>
</ArrowsContainer>
</Wrapper>
<SpecializationsInnerContainer ref={scrollContainer}>
{specializations.map((specialization) =>
<SpecializationCard
key={specialization.id}
image={specialization.image}
title={specialization.title}
color={'black1'}
borderColor={'transparent'}
onClick={() => handleOnClick(specialization.id)}
/>
)}
<SpecializationCard borderColor={'black15'} image={'image.png'} isAll onClick={openSpecializationFilter} title={translator('specilization.all', true)} color={'transparent'}/>
</SpecializationsInnerContainer>
</Container>
</Well>
)
}
Upvotes: 1
Views: 13901
Reputation: 123
During more research found an answer in 'react-swipeable' npm module https://www.npmjs.com/package/react-swipeable
As the arrow icons onclick logic is already defined here, added the same logic to react swipeable component:
<Swipeable onSwipedLeft={() => setScrolled(true)} onSwipedRight={() => setScrolled(false)} trackMouse={true}>
<SpecializationsInnerContainer ref={scrollContainer}>
{specializations.map((specialization) =>
<SpecializationCard
key={specialization.id}
image={specialization.image}
title={specialization.title}
color={'black1'}
borderColor={'transparent'}
onClick={() => handleOnClick(specialization.id)}
/>
)}
<SpecializationCard borderColor={'black15'} image={'image.png'} isAll onClick={openSpecializationFilter} title={translator('specilization.all', true)} color={'transparent'}/>
</SpecializationsInnerContainer>
</Swipeable>
Upvotes: 1
Reputation: 140
Since you did not provide any snippet or source code, here is some basic example. It should get you started.
const slider = document.querySelector('.items');
let isDown = false;
let startX;
let scrollLeft;
slider.addEventListener('mousedown', (e) => {
isDown = true;
startX = e.pageX - slider.offsetLeft;
scrollLeft = slider.scrollLeft;
});
slider.addEventListener('mouseleave', () => {
isDown = false;
});
slider.addEventListener('mouseup', () => {
isDown = false;
});
slider.addEventListener('mousemove', (e) => {
if(!isDown) return;
e.preventDefault();
const x = e.pageX - slider.offsetLeft;
const walk = (x - startX) * 3; //scroll-fast
slider.scrollLeft = scrollLeft - walk;
});
https://codepen.io/toddwebdev/pen/yExKoj
Upvotes: 7