|
@@ -1,23 +1,222 @@
|
|
|
import React, {useRef, useEffect, useState} from 'react'
|
|
|
import SliderImage from './SliderImage'
|
|
|
-export default ({images, current:propCurrent, onChange, ...props}) => {
|
|
|
- const [current, setCurrent] = useState(0)
|
|
|
- const currentImages = [images[(current + images.length -1) % images.length],
|
|
|
- images[current],
|
|
|
- images[(current + 1) % images.length]
|
|
|
- ]
|
|
|
-
|
|
|
- console.log(current, currentImages)
|
|
|
-
|
|
|
- const key = 'SliderSiblingOnly'
|
|
|
-
|
|
|
-
|
|
|
- return <SliderImage key={key} images={currentImages}
|
|
|
- onChange={current3 => {
|
|
|
- const newCurrent = (current + current3 -1 + images.length) % images.length
|
|
|
- onChange(newCurrent)
|
|
|
- setCurrent(newCurrent)
|
|
|
- }}
|
|
|
- current={1}
|
|
|
- {...props} />
|
|
|
+
|
|
|
+export default ({images = [], imgWidth=377, className, onChange, onClick, ref, siblingOnly, current:propCurrent=0, ...props}) => {
|
|
|
+ const containerRef = useRef()
|
|
|
+ const autoscroll = useRef(false)
|
|
|
+ const afterAutoscroll = useRef(false)
|
|
|
+ const inTouch = useRef(false)
|
|
|
+ const timeout = useRef(false)
|
|
|
+ const afterTimeout = useRef(false)
|
|
|
+
|
|
|
+ const imgs = useRef([])
|
|
|
+ const currentRef = useRef(propCurrent)
|
|
|
+ const diffRef = useRef(0)
|
|
|
+ //const [currentImages, setCurrentImages] = useState([])
|
|
|
+ //const [current, setCurrent] = useState(0)
|
|
|
+
|
|
|
+ const getCurrentImages = (current) => {
|
|
|
+ return [
|
|
|
+ images[(current + images.length -1) % images.length],
|
|
|
+ images[current],
|
|
|
+ images[(current + 1) % images.length]
|
|
|
+ ]
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ let currentImages = getCurrentImages(currentRef.current)
|
|
|
+
|
|
|
+ //useEffect(() => {
|
|
|
+ //if (containerRef.current){
|
|
|
+ //const scrollTo = imgs?.[0]?.getBoundingClientRect().width
|
|
|
+ //containerRef.current.scrollTo(scrollTo, 0)
|
|
|
+ //currentScrollPosition.current = scrollTo
|
|
|
+ //console.log('scrollTo', scrollTo)
|
|
|
+ //setCurrent(propCurrent)
|
|
|
+ //}
|
|
|
+ //},[propCurrent, containerRef.current])
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (containerRef.current)
|
|
|
+ containerRef.current.scrollTo({left: imgWidth, behavior: 'auto'})
|
|
|
+ }, [containerRef.current])
|
|
|
+
|
|
|
+ //useEffect(() => {
|
|
|
+ //autoscroll.current = true
|
|
|
+ //onScroll()
|
|
|
+ //}, [current])
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ const onTouchEnd = () => {
|
|
|
+ console.log('TOUCH END', inTouch.current, autoscroll.current, afterAutoscroll.current,
|
|
|
+ containerRef.current.scrollLeft, containerRef.current.scrollWidth)
|
|
|
+ //if (afterAutoscroll.current) {
|
|
|
+ //afterAutoscroll.current = false
|
|
|
+ //return;
|
|
|
+ //}
|
|
|
+ if (inTouch.current){
|
|
|
+ if (timeout.current) clearInterval(timeout.current)
|
|
|
+
|
|
|
+ timeout.current = setTimeout(onTouchEnd, 200)
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const {scrollLeft, scrollWidth} = containerRef.current;
|
|
|
+ const viewPortWidth = containerRef.current.getBoundingClientRect().width
|
|
|
+
|
|
|
+ console.log(scrollLeft, scrollWidth)
|
|
|
+
|
|
|
+ autoscroll.current = true
|
|
|
+ if (scrollLeft < imgWidth/2) {
|
|
|
+ console.log('left')
|
|
|
+ containerRef.current.scrollTo({left: 0, behavior: 'smooth'})
|
|
|
+ diffRef.current = -1
|
|
|
+ onScroll()
|
|
|
+ }
|
|
|
+ else if (scrollLeft >= scrollWidth - viewPortWidth*1.5) {
|
|
|
+ console.log('right', (scrollLeft - imgWidth * 2))
|
|
|
+ const toRight = imgWidth * 2
|
|
|
+ diffRef.current = +1
|
|
|
+ containerRef.current.scrollTo({left: toRight, behavior: 'smooth'})
|
|
|
+ onScroll()
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ console.log('center', containerRef.current.scrollWidth)
|
|
|
+ diffRef.current = 0
|
|
|
+ const toCurrent = imgWidth
|
|
|
+ if (toCurrent === scrollLeft){
|
|
|
+ autoscroll.current = false
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ containerRef.current.scrollTo({left: toCurrent, behavior: 'smooth'})
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const onScroll = () => {
|
|
|
+ if (autoscroll.current){
|
|
|
+ if (afterTimeout.current)
|
|
|
+ clearInterval(afterTimeout.current)
|
|
|
+
|
|
|
+ afterTimeout.current = setTimeout(() => {
|
|
|
+ const {scrollLeft, scrollWidth} = containerRef.current;
|
|
|
+ const {current} = currentRef
|
|
|
+ console.log('AFTER', scrollLeft, scrollWidth)
|
|
|
+ const newCurrent = ((currentRef.current + diffRef.current +images.length) % images.length)
|
|
|
+ let currentImages = getCurrentImages(newCurrent)
|
|
|
+ console.log('move from', diffRef.current, current, newCurrent, currentImages)
|
|
|
+ if (newCurrent !== current){
|
|
|
+ imgs.current[0].src = currentImages[0]
|
|
|
+ imgs.current[1].src = currentImages[1]
|
|
|
+ imgs.current[2].src = currentImages[2]
|
|
|
+ containerRef.current.scrollTo({left: imgWidth, behavior: 'auto'})
|
|
|
+
|
|
|
+ //afterAutoscroll.current = true
|
|
|
+ }
|
|
|
+
|
|
|
+ currentRef.current = newCurrent
|
|
|
+ autoscroll.current = false
|
|
|
+ diffRef.current = 0
|
|
|
+
|
|
|
+
|
|
|
+ console.log(diffRef.current, newCurrent)
|
|
|
+ }, 500)
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (timeout.current) clearInterval(timeout.current)
|
|
|
+
|
|
|
+ timeout.current = setTimeout(onTouchEnd, 200)
|
|
|
+ //e.preventDefault();
|
|
|
+ }
|
|
|
+
|
|
|
+ //useEffect(scrollToCurrent, [current])
|
|
|
+
|
|
|
+ const isTouchDevice = () => (navigator.maxTouchPoints || 'ontouchstart' in document.documentElement);
|
|
|
+
|
|
|
+ const onImgClick = (e, i) => {
|
|
|
+ const touchDevice = isTouchDevice()
|
|
|
+ if (touchDevice && typeof onClick === 'function'){
|
|
|
+ onClick(i)
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ const viewPortWidth = containerRef.current.getBoundingClientRect().width
|
|
|
+ const clickX = e.clientX -e.target.getBoundingClientRect().x
|
|
|
+ const {scrollLeft} = containerRef.current;
|
|
|
+ if (clickX > viewPortWidth * 0.75) {
|
|
|
+ if (i < images.length -1){
|
|
|
+ currentScrollPosition.current = scrollLeft + (imgs?.[i].getBoundingClientRect().width || 0)
|
|
|
+ setCurrent(i +1)
|
|
|
+ scrollToCurrent()
|
|
|
+ if (typeof onChange === 'function') onChange(i +1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (clickX < viewPortWidth * 0.25) {
|
|
|
+ if (i > 0){
|
|
|
+ currentScrollPosition.current = scrollLeft - (imgs?.[i-1].getBoundingClientRect().width || 0)
|
|
|
+ setCurrent(i -1)
|
|
|
+ scrollToCurrent()
|
|
|
+ if (typeof onChange === 'function') onChange(i -1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (typeof onClick === 'function'){
|
|
|
+ onClick(i)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const imgStyle = {
|
|
|
+ maxWidth: imgWidth + 'px',
|
|
|
+ minWidth: imgWidth + 'px',
|
|
|
+ width: imgWidth + 'px',
|
|
|
+ boxSizing: 'border-box'
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className={className}
|
|
|
+ style={{cssText: `overflow: auto; overflow-y: hidden; -ms-overflow-style: none; scrollbar-width: none; overscroll-behavior-x: none;`}}
|
|
|
+ onScroll={onScroll} //TODO: do it only on desktop, on touch devices use onTouchEnd
|
|
|
+ ref={containerRef}
|
|
|
+ {...isTouchDevice() ? {
|
|
|
+ onTouchStart(){
|
|
|
+ inTouch.current = true
|
|
|
+ autoscroll.current = false
|
|
|
+ },
|
|
|
+ onTouchEnd(){
|
|
|
+ inTouch.current = false
|
|
|
+ }
|
|
|
+ }: {}}
|
|
|
+ >
|
|
|
+ <div style={{minWidth: imgWidth*3 + 'px'}}>
|
|
|
+ <img src={currentImages[0]}
|
|
|
+ style={imgStyle}
|
|
|
+ key={`image_${(currentRef.current -1 +images.length) % images.length}`}
|
|
|
+ alt={`image ${(currentRef.current -1 +images.length) % images.length}`}
|
|
|
+ ref={img => imgs.current[0] = img}
|
|
|
+ />
|
|
|
+ <img src={currentImages[1]}
|
|
|
+ style={imgStyle}
|
|
|
+ key={`image_${currentRef.current}`}
|
|
|
+ alt={`image ${currentRef.current}`}
|
|
|
+ ref={img => imgs.current[1] = img}
|
|
|
+ onClick={e => onImgClick(e, currentRef.current)}
|
|
|
+ />
|
|
|
+ <img src={currentImages[2]}
|
|
|
+ style={imgStyle}
|
|
|
+ key={`image_${(currentRef.current +1 +images.length) % images.length}`}
|
|
|
+ alt={`image ${(currentRef.current +1 +images.length) % images.length}`}
|
|
|
+ ref={img => imgs.current[2] = img}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ //{currentImages.map((image, i) => <img src={image}
|
|
|
+ //key={`image_${(i + current -1 +images.length) % images.length}`}
|
|
|
+ //alt={`image ${(i + current -1 +images.length) % images.length}`}
|
|
|
+ //onClick={e => onImgClick(e, i)}
|
|
|
+ ///>)}
|