Ivan Asmer 3 rokov pred
rodič
commit
d81bcb2f13
6 zmenil súbory, kde vykonal 128 pridanie a 19 odobranie
  1. 3 3
      .prettierrc
  2. 6 2
      example/src/App.js
  3. 9 0
      example/src/index.css
  4. 4 1
      package.json
  5. 106 4
      src/index.js
  6. 0 9
      src/styles.module.css

+ 3 - 3
.prettierrc

@@ -2,9 +2,9 @@
   "singleQuote": true,
   "jsxSingleQuote": true,
   "semi": false,
-  "tabWidth": 2,
-  "bracketSpacing": true,
+  "tabWidth": 4,
+  "bracketSpacing": false,
   "jsxBracketSameLine": false,
-  "arrowParens": "always",
+  "arrowParens": "avoid",
   "trailingComma": "none"
 }

+ 6 - 2
example/src/App.js

@@ -1,10 +1,14 @@
 import React from 'react'
 
-import { ExampleComponent } from 'react-scrollable-slider'
+import { SliderImage } from 'react-scrollable-slider'
 import 'react-scrollable-slider/dist/index.css'
 
+const images = ["images/7eda725de98d7b4a23489988a334e726_375.jpeg", "images/fa0cfb2c2f540f33eb179ab1af2a4416_375.jpeg", "static/media/banner_hor2.a5496732.png", "images/7eda725de98d7b4a23489988a334e726_375.jpeg", ].map(img => "https://mo-cosmetics.com/" + img)
+
 const App = () => {
-  return <ExampleComponent text="Create React Library Example 😄" />
+  return (
+        <SliderImage images={images} className="SliderImage"/>
+  )
 }
 
 export default App

+ 9 - 0
example/src/index.css

@@ -12,3 +12,12 @@ code {
   font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
     monospace;
 }
+
+.SliderImage {
+    max-width: 375px;
+}
+.SliderImage::-webkit-scrollbar {
+    display: none;
+}
+
+

+ 4 - 1
package.json

@@ -4,7 +4,10 @@
   "description": "made in love with JS and in hate with CSS",
   "author": "asmer",
   "license": "MIT",
-  "repository": "asmer/react-scrollable-slider",
+  "repository": {
+    "type": "git",
+    "url": "git@gitlab.a-level.com.ua:gitgod/react-scrollable-slider"
+  },
   "main": "dist/index.js",
   "module": "dist/index.modern.js",
   "source": "src/index.js",

+ 106 - 4
src/index.js

@@ -1,6 +1,108 @@
-import React from 'react'
-import styles from './styles.module.css'
+import React, {useRef, useEffect, useState} from 'react'
 
-export const ExampleComponent = ({ text }) => {
-  return <div className={styles.test}>Example Component: {text}</div>
+export const SliderImage = ({images = [], className, ...props}) => {
+    const divRef                = useRef()
+    const containerRef          = useRef()
+    const autoscroll            = 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
+
+            console.log(imgs)
+
+            const totalWidth = imgs.reduce((total, img) => total + (img?.getBoundingClientRect().width || 0),0)
+            div.style.width = 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
+            console.log()
+            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 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++
+                }
+            }
+            console.log(newCurrent, currentScrollPosition.current)
+            setCurrent(newCurrent)
+            if (newCurrent === current) scrollToCurrent()
+        }, 200)
+
+    }
+
+    useEffect(scrollToCurrent, [current])
+
+    return (
+        <div className={className} 
+             style={{cssText: `overflow: auto; -ms-overflow-style: none; scrollbar-width: none`}}
+             onScroll={onScroll}
+             ref={containerRef}>
+            <div ref={divRef}>
+                {images.map((image, i) => <img  src={image} 
+                                                key={`image_${i}`} 
+                                                alt={`image ${i}`} 
+                                                onLoad={e => {imgs[i] = e.target; setImgs([...imgs]) }}
+                                                />)}
+            </div>
+        </div>
+    )
 }

+ 0 - 9
src/styles.module.css

@@ -1,9 +0,0 @@
-/* add css module styles here (optional) */
-
-.test {
-  margin: 2em;
-  padding: 0.5em;
-  border: 2px solid #000;
-  font-size: 2em;
-  text-align: center;
-}