Jelajahi Sumber

stop autoscroll on touch start/on scroll

Ivan Asmer 3 tahun lalu
induk
melakukan
c6933be31f
2 mengubah file dengan 2 tambahan dan 162 penghapusan
  1. 0 3
      package.json
  2. 2 159
      src/index.js

+ 0 - 3
package.json

@@ -34,18 +34,15 @@
     "babel-eslint": "^10.0.3",
     "cross-env": "^7.0.2",
     "eslint": "^6.8.0",
-    "eslint-config-prettier": "^6.7.0",
     "eslint-config-standard": "^14.1.0",
     "eslint-config-standard-react": "^9.2.0",
     "eslint-plugin-import": "^2.18.2",
     "eslint-plugin-node": "^11.0.0",
-    "eslint-plugin-prettier": "^3.1.1",
     "eslint-plugin-promise": "^4.2.1",
     "eslint-plugin-react": "^7.17.0",
     "eslint-plugin-standard": "^4.0.1",
     "gh-pages": "^2.2.0",
     "npm-run-all": "^4.1.5",
-    "prettier": "^2.0.4",
     "react": "^16.13.1",
     "react-dom": "^16.13.1",
     "react-scripts": "^3.4.1"

+ 2 - 159
src/index.js

@@ -1,159 +1,2 @@
-import React, {useRef, useEffect, useState} from 'react'
-
-export const SliderImage = ({images = [], className, onChange, onClick, ...props}) => {
-    const divRef                = useRef()
-    const containerRef          = useRef()
-    const autoscroll            = useRef(false)
-    const inTouch               = useRef(false)
-    const timeout               = useRef(false)
-
-    const [imgs, setImgs]       = useState([])
-    const [current, setCurrent] = useState(0)
-    const currentScrollPosition = useRef(0)
-
-
-    useEffect(() => {
-        if (divRef.current){
-            const div  = divRef.current
-
-            const totalWidth = imgs.reduce((total, img) => total + (img?.getBoundingClientRect().width || 0),0)
-            div.style.minWidth = totalWidth + 'px'
-        }
-    }, [divRef, imgs])
-
-    const scrollToCurrent = () => {
-        if (autoscroll.current || !containerRef.current) return;
-
-        const el = containerRef.current
-
-        const step = () => {
-            if (!el) return;
-
-            autoscroll.current = true
-            const {scrollLeft} =  el
-            const diff = (currentScrollPosition.current - scrollLeft) /5
-            if (Math.abs(diff) > 1){
-                el.scrollTo(scrollLeft + diff, 0)
-                setTimeout(step, 20)
-            }
-            else {
-                el.scrollTo(currentScrollPosition.current, 0)
-                autoscroll.current = false
-            }
-        }
-        step()
-        //if (milaCount !== current +1) set(current +1)
-    }
-
-    const onTouchEnd = () => {
-        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
-
-        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;
-
-        if (timeout.current) clearInterval(timeout.current)
-
-        timeout.current = setTimeout(onTouchEnd, 200)
-    }
-
-    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)
-            }
-        }
-    }
-
-    return (
-        <div className={className} 
-             style={{cssText: `overflow: auto; -ms-overflow-style: none; scrollbar-width: none`}}
-             onScroll={onScroll} //TODO: do it only on desktop, on touch devices use onTouchEnd
-             ref={containerRef} 
-            {...isTouchDevice() ? {
-                onTouchStart(){
-                    inTouch.current = true
-                },
-                onTouchEnd(){
-                    inTouch.current = false
-                }
-            }: {}}
-            >
-            <div ref={divRef}>
-                {images.map((image, i) => <img  src={image} 
-                                                key={`image_${i}`} 
-                                                alt={`image ${i}`} 
-                                                onLoad={e => {imgs[i] = e.target; setImgs([...imgs]) }}
-                                                onClick={e => onImgClick(e, i)}
-                                                />)}
-            </div>
-        </div>
-    )
-}
+import SliderImage from './SliderImage'
+export {SliderImage}