Erstellen eines coolen Sticky-Effekts für einen Schieberegler bei React

Es gibt viele verschiedene Bibliotheken zum Implementieren eines Schiebereglers mit allen möglichen Effekten. Einige der besten für React sind: ReactSlick und Swiper . Als für mein Projekt ein horizontaler Klebeeffekt erforderlich war, wurde nichts Passendes gefunden.



In diesem Artikel werden wir versuchen, nach und nach einen solchen Schieberegler zu erstellen. Vielleicht brauchen Sie ihn auch!


Installieren Sie die erforderlichen Pakete


Wir werden die Create React App verwenden , um das Projekt zu erstellen .


Erstellen Sie eine Anwendung:


npx create-react-app my-app 

Wir werden den Schieberegler nicht von Grund auf neu erstellen , sondern die Swiper- Bibliothek verwenden. Es gibt die am besten geeigneten Ereignisse, für die Sie eine Verbindung herstellen müssen (dazu später mehr). Dann müssen wir die folgenden Pakete installieren:


 npm i swiper react-id-swiper 

Und das letzte Paket (optional) zur Verwendung des Sass-Präprozessors:


 npm i node-sass 

Das Ergebnis ist package.json:


package.json


 { "name": "sticky-slider", "version": "0.1.0", "private": true, "dependencies": { "node-sass": "^4.13.0", "react": "^16.11.0", "react-dom": "^16.11.0", "react-id-swiper": "^2.3.2", "react-scripts": "3.2.0", "swiper": "^5.2.0" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": "react-app" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } } 

Großartig, jetzt beginnen wir mit der Implementierung des Schiebereglers.


Erstellen Sie einen einfachen Schieberegler


Beginnen wir mit der Erstellung einer kleinen Datei mit unseren Folien.


src/data.json


 [ { "title": "Slide 1", "color": "#aac3bf" }, { "title": "Slide 2", "color": "#c9b1bd" }, { "title": "Slide 3", "color": "#d5a29c" }, { "title": "Slide 4", "color": "#82a7a6" }, { "title": "Slide 5", "color": "#e6af7a" }, { "title": "Slide 6", "color": "#95be9e" }, { "title": "Slide 7", "color": "#97b5c5" } ] 

Danach erstellen wir einen regulären Schieberegler mit Standardeffekten.


 // src/components/StickySlider/StickySlider.jsx import React from 'react'; import Swiper from 'react-id-swiper'; import 'react-id-swiper/lib/styles/css/swiper.css'; import data from '../../data'; const StickySlider = () => { const params = { slidesPerView: 3, }; return ( <Swiper {...params}> {data.map((item, idx) => ( <div key={idx}> {item.title} </div> ))} </Swiper> ); }; export default StickySlider; 

Dementsprechend erstellen wir eine Indexdatei für die Komponente.


 // src/components/StickySlider/index.js export { default } from './StickySlider'; 

Der einzige Parameter, den wir beschrieben haben, ist slidesPerView (die Anzahl der sichtbaren Folien). Wir brauchen nichts anderes, aber alle möglichen Parameter des Swipers finden Sie hier .


Erstellen Sie eine separate Komponente Folie, damit das Erscheinungsbild des Schiebereglers fertig ist.


 // src/components/Slide/Slide.jsx import React from 'react'; import css from './Slide.module.scss'; const Slide = ({ children, color }) => { return ( <div className={css.container}> <div className={css.content} style={{ background: color }} /> <footer className={css.footer}> {children} </footer> </div> ); }; export default Slide; 

Stile für die Folie.


 // src/components/Slide/Slide.module.scss .container { margin: 0 1em; border-radius: 4px; overflow: hidden; background-color: #fff; } .content { box-sizing: border-box; padding: 50% 0; } .footer { color: #333; font-weight: 700; font-size: 1.25em; text-align: center; padding: 1em; } 

Und dementsprechend die Indexdatei:


 // src/components/Slide/index.js export { default } from './Slide'; 

Und aktualisiere StickySlider ein bisschen.


 // src/components/StickySlider/StickySlider.jsx import React from 'react'; import Swiper from 'react-id-swiper'; import 'react-id-swiper/lib/styles/css/swiper.css'; import Slide from '../Slide'; import data from '../../data'; const StickySlider = () => { const params = { slidesPerView: 3, }; return ( <Swiper {...params}> {data.map((item, idx) => ( <div key={idx}> {/*   */} <Slide color={item.color}> {item.title} </Slide> </div> ))} </Swiper> ); }; export default StickySlider; 

App.jsx nun diesen Schieberegler in App.jsx und legen Sie gleichzeitig die minimale Seitenstruktur fest.


 // App.jsx import React from 'react'; import StickySlider from './components/StickySlider'; import css from './App.module.scss'; const App = () => { return ( <div className={css.container}> <h1 className={css.title}>Sticky slider</h1> <div className={css.slider}> <StickySlider /> </div> </div> ); }; export default App; 

Und in die entsprechende scss-Datei schreiben wir einige Stile.


 // App.module.scss .container { padding: 0 15px; } .title { font-weight: 700; font-size: 2.5em; text-align: center; margin: 1em 0; } .slider { margin: 0 -15px; } 

Bisher haben wir einen solchen Schieberegler:



Cool, ein Anfang ist gemacht, wir werden weiterhin tun, was wir von diesem Schieberegler brauchen.


Fügen Sie einen klebrigen Effekt hinzu


Der Swiper verfügt über zwei Ereignisse setTranslate und setTransition , die setTranslate setTransition .


EigentumWann wird ausgelöstWas zurückkommt
setTranslateEs funktioniert, wenn wir den Schieberegler bewegen und wenn wir ihn absenkenGibt den Wert zurück, um den der Schieberegler gerade verschoben wird, und in dem Fall, in dem wir ihn freigeben, den Wert, auf den er automatisch gebracht wird
setTransitionDies funktioniert, wenn wir den Schieberegler bewegen, wenn wir ihn loslassen und wenn der Schieberegler in die gewünschte Position gebracht wirdGibt den Übergangswert in Millisekunden zurück

Fügen Sie dies zu unserer StickySlider Komponente hinzu und leiten Sie es sofort an Slider . Dort wird es nützlich sein:


 // src/components/StickySlider/StickySlider.jsx import React, { useState, useEffect } from 'react'; import Swiper from 'react-id-swiper'; import 'react-id-swiper/lib/styles/css/swiper.css'; import Slide from '../Slide'; import data from '../../data'; const StickySlider = () => { const [swiper, updateSwiper] = useState(null); const [translate, updateTranslate] = useState(0); const [transition, updateTransition] = useState(0); const params = { slidesPerView: 3, }; useEffect(() => { if (swiper) { swiper.on('setTranslate', (t) => { updateTranslate(t); }); swiper.on('setTransition', (t) => { updateTransition(t); }); } }, [swiper]); return ( <Swiper getSwiper={updateSwiper} {...params}> {data.map((item, idx) => ( <div key={idx}> <Slide translate={translate} transition={transition} color={item.color} > {item.title} </Slide> </div> ))} </Swiper> ); }; export default StickySlider; 

Ich rate Ihnen, den Schieberegler zu bewegen und genauer zu sehen, was in diesem Moment angezeigt wird:


 // src/components/StickySlider/StickySlider.jsx // ... useEffect(() => { if (swiper) { swiper.on('setTranslate', (t) => { console.log(t, 'translate'); updateTranslate(t); }); swiper.on('setTransition', (t) => { console.log(t, 'transform'); updateTransition(t); }); } }, [swiper]); // .. 

Ich benutze Haken, um den Status zu speichern. Wenn Sie mit ihnen nicht vertraut sind, empfehle ich Ihnen, die Dokumentation (in russischer Sprache) zu lesen.


Außerdem wird das Schwierigste in der Slide passieren.


Wir benötigen den Einrückungsstatus vom linken Rand des Schiebereglers und die Breite der aktuellen Folie:


 // src/components/StickySlider/StickySlider.jsx // ... const container = useRef(null); const [offsetLeft, updateOffsetLeft] = useState(0); const [width, updateWidth] = useState(1); // ... 

Sie werden bei der Elementinitialisierung einmal hinzugefügt und nicht geändert. Daher verwenden wir useEffect mit einem leeren Array. Gleichzeitig erhalten wir die Parameter nicht der Folie selbst, sondern ihres technischen Wrappers über parentElement , da wir den aktuellen Wrapper mithilfe der transform Eigenschaft konvertieren.


 // src/components/StickySlider/StickySlider.jsx // ... useEffect(() => { setTimeout(() => { const parent = container.current.parentElement; updateOffsetLeft(parent.offsetLeft); updateWidth(parent.offsetWidth); }, 0); }, []); // ... 

Der wichtigste Moment. Wir betrachten diese ganze Sache und werfen sie in die Stile:


 // src/components/Slide/Slide.jsx // ... const x = -translate - offsetLeft; const k = 1 - x / width; // [0 : 1] const style = x >= -1 ? { transform: `translateX(${x}px) scale(${k * 0.2 + 0.8})`, // [0.8 : 1] opacity: k < 0 ? 0 : k * 0.5 + 0.5, // [0.5 : 1] transition: `${transition}ms`, } : {}; // ... 

Die Eigenschaft translate kommt vom übergeordneten Element zu uns und ist für alle Folien gleich. Um eine einzelne Übersetzung für eine Folie zu finden, subtrahieren Sie daher offsetLeft davon.


Die Variable k ist ein Wert von 0 bis 1. Mit diesem Wert führen wir die Animation durch. Dies ist eine Schlüsselvariable, da damit beliebige Effekte erzielt werden können.


Jetzt berechnen wir die Stile. Die Bedingung x >= -1 ist erfüllt, wenn sich die Folie in der Animationszone befindet. Wenn sie ausgeführt wird, hängen wir die Stile an die Seite. Die scale und opacity können nach Ihren Wünschen ausgewählt werden. Die folgenden Intervalle schienen mir am besten geeignet zu sein: [0.8 : 1] für den scale und [0.5 : 1] für die opacity .


Die transition wird direkt vom Bibliotheksereignis bereitgestellt.


Folgendes passiert, nachdem alle oben genannten Elemente hinzugefügt wurden:


 // src/components/Slide/Slide.jsx import React, { useRef, useEffect, useState } from 'react'; import css from './Slide.module.scss'; const Slide = ({ children, translate, transition, color }) => { const container = useRef(null); const [offsetLeft, updateOffsetLeft] = useState(0); const [width, updateWidth] = useState(1); useEffect(() => { setTimeout(() => { const parent = container.current.parentElement; updateOffsetLeft(parent.offsetLeft); updateWidth(parent.offsetWidth); }, 0); }, []); const x = -translate - offsetLeft; const k = 1 - x / width; // [0 : 1] const style = x >= -1 ? { transform: `translateX(${x}px) scale(${k * 0.2 + 0.8})`, // [0.8 : 1] opacity: k < 0 ? 0 : k * 0.5 + 0.5, // [0.5 : 1] transition: `${transition}ms`, } : {}; return ( <div ref={container} style={style} className={css.container}> <div className={css.content} style={{ background: color }} /> <footer className={css.footer}> {children} </footer> </div> ); }; export default Slide; 

Fügen Sie nun der Folienstildatei die folgenden Eigenschaften hinzu:


 // src/components/Slide/Slide.module.scss .container { // ... transform-origin: 0 50%; //      transition-property: opacity, transform; // ,   } // ... 

Nun, das ist es, unser Effekt ist fertig! Sie können das fertige Beispiel auf meinem Github sehen .


Vielen Dank für Ihre Aufmerksamkeit!

Source: https://habr.com/ru/post/de474254/


All Articles