admin管理员组

文章数量:1291029

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>
  )
}

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>
  )
}
Share Improve this question edited Sep 15, 2020 at 7:12 ylsv asked Sep 14, 2020 at 14:35 ylsvylsv 1231 gold badge2 silver badges11 bronze badges 2
  • Hi, wele to StackOverflow. Please show us some code where you are struggling to find a solution, so that the team can help you. – Durga Prasad Commented Sep 14, 2020 at 16:07
  • Sorry about that, added some code – ylsv Commented Sep 15, 2020 at 7:13
Add a ment  | 

2 Answers 2

Reset to default 7

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

During more research found an answer in 'react-swipeable' npm module https://www.npmjs./package/react-swipeable

As the arrow icons onclick logic is already defined here, added the same logic to react swipeable ponent:

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

本文标签: javascriptHow to drag carousel on swipe in ReactStack Overflow