Browse Source

yet another buggy version like for prod

Ivan Asmer 3 years ago
parent
commit
8e1f6194ba
2 changed files with 220 additions and 21 deletions
  1. 1 1
      src/SliderImage.js
  2. 219 20
      src/SliderSiblingOnly.js

+ 1 - 1
src/SliderImage.js

@@ -1,6 +1,6 @@
 import React, {useRef, useEffect, useState} from 'react'
 
-export default ({images = [], className, onChange, onClick, ref, siblingOnly, current:propCurrent, ...props}) => {
+export default ({images = [], className, onChange, onClick, ref, current:propCurrent, ...props}) => {
     const divRef                = useRef()
     const containerRef          = useRef()
     const autoscroll            = useRef(false)

+ 219 - 20
src/SliderSiblingOnly.js

@@ -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)}
+                                                ///>)}