Просмотр исходного кода

onTouchEnd for mobile, onScroll with timeout for desktop

Ivan Asmer 3 лет назад
Родитель
Сommit
5e028d64fc
2 измененных файлов с 45 добавлено и 41 удалено
  1. 0 3
      example/src/index.css
  2. 45 38
      src/index.js

+ 0 - 3
example/src/index.css

@@ -15,15 +15,12 @@ code {
 
 .SliderImage {
     max-width: 375px;
-    margin-left: 200px;
 }
 .SliderImage::-webkit-scrollbar {
     display: none;
 }
 
 div {
-    margin: 10px;
-    padding: 20px;
 }
 
 img {

+ 45 - 38
src/index.js

@@ -44,52 +44,57 @@ export const SliderImage = ({images = [], className, onChange, onClick, ...props
         //if (milaCount !== current +1) set(current +1)
     }
 
+    const onTouchEnd = () => {
+        const {scrollLeft, scrollWidth} = containerRef.current;
+        const viewPortWidth             = containerRef.current.getBoundingClientRect().width
+
+        let newCurrent;
+        if (scrollLeft === 0) {
+            newCurrent = 0
+            currentScrollPosition.current = 0
+        }
+        else if (scrollLeft >= scrollWidth - viewPortWidth) {
+            newCurrent = (images.length -1)
+            currentScrollPosition.current = scrollWidth - viewPortWidth
+        }
+        else {  
+            let imgsWidth = 0
+            let i         = 0
+            for (const img of imgs){
+                const imgWidth = img?.getBoundingClientRect().width || 0
+                imgsWidth += imgWidth
+                if (imgsWidth > scrollLeft){
+                    break;
+                }
+                i++
+            }
+            const offset = imgsWidth  - scrollLeft
+            newCurrent   = i
+            currentScrollPosition.current = imgsWidth - (imgs?.[i].getBoundingClientRect().width || 0)
+            if (offset < viewPortWidth/2){
+                currentScrollPosition.current = imgsWidth 
+                newCurrent++
+            }
+        }
+        setCurrent(newCurrent)
+        if (newCurrent === current) scrollToCurrent()
+        else if (typeof onChange === 'function') onChange(newCurrent)
+    }
+
     const onScroll = e => {
         if (autoscroll.current) return;
-        const {scrollLeft, scrollWidth} = e.target;
-        const viewPortWidth             = e.target.getBoundingClientRect().width
 
         if (timeout.current) clearInterval(timeout.current)
 
-        timeout.current = setTimeout(() => {
-            let newCurrent;
-            if (scrollLeft === 0) {
-                newCurrent = 0
-                currentScrollPosition.current = 0
-            }
-            else if (scrollLeft >= scrollWidth - viewPortWidth) {
-                newCurrent = (images.length -1)
-                currentScrollPosition.current = scrollWidth - viewPortWidth
-            }
-            else {  
-                let imgsWidth = 0
-                let i         = 0
-                for (const img of imgs){
-                    const imgWidth = img?.getBoundingClientRect().width || 0
-                    imgsWidth += imgWidth
-                    if (imgsWidth > scrollLeft){
-                        break;
-                    }
-                    i++
-                }
-                const offset = imgsWidth  - scrollLeft
-                newCurrent   = i
-                currentScrollPosition.current = imgsWidth - (imgs?.[i].getBoundingClientRect().width || 0)
-                if (offset < viewPortWidth/2){
-                    currentScrollPosition.current = imgsWidth 
-                    newCurrent++
-                }
-            }
-            setCurrent(newCurrent)
-            if (newCurrent === current) scrollToCurrent()
-            else if (typeof onChange === 'function') onChange(newCurrent)
-        }, 200)
+        timeout.current = setTimeout(onTouchEnd, 200)
     }
 
     useEffect(scrollToCurrent, [current])
 
+    const isTouchDevice = () => (navigator.maxTouchPoints || 'ontouchstart' in document.documentElement);
+
     const onImgClick = (e, i) => {
-        const touchDevice = (navigator.maxTouchPoints || 'ontouchstart' in document.documentElement);
+        const touchDevice = isTouchDevice()
         if (touchDevice && typeof onClick === 'function'){
             onClick(i)
         }
@@ -122,8 +127,10 @@ export const SliderImage = ({images = [], className, onChange, onClick, ...props
     return (
         <div className={className} 
              style={{cssText: `overflow: auto; -ms-overflow-style: none; scrollbar-width: none`}}
-             onScroll={onScroll}
-             ref={containerRef}>
+             //onScroll={onScroll} //TODO: do it only on desktop, on touch devices use onTouchEnd
+             ref={containerRef} 
+             {...(isTouchDevice() ? {onTouchEnd} : {onScroll})}
+            >
             <div ref={divRef}>
                 {images.map((image, i) => <img  src={image} 
                                                 key={`image_${i}`}