ReactJS响应式轮播从零开始

好吧,所以基本上我正在尝试从头开始为ReactJS编写一个轮播。
我已经完成了对导航,幻灯片等所需function的必须编码。

这样做的主要目的是为了使其响应,但这是我很难找出如何做。

carousel.js

import React from 'react' import { NavLink } from 'react-router-dom' import classNames from 'classnames' export default class Carousel extends React.Component { constructor(props) { super(props) this.handleNext = this.handleNext.bind(this) this.handlePrev = this.handlePrev.bind(this) this.state = { innerWidth: 0, navPrevDisabled: true } } componentWillMount() { var stateItems = [] for(let i in this.props.items) { stateItems.push( <div className="react-item movie" key={i}> <div className="front"> <div className="front-image" style={{backgroundImage: `url(${this.props.items[i].poster})`}}> </div> <div className="backdrop medium"> <div className="react-play-button fill"> <figure className="icon-content"></figure> </div> </div> </div> </div> ) } this.setState({ items: stateItems }) } componentWillUnmount() { window.removeEventListener("resize", this.updateCarousel, false) } updateCarousel = () => { var $reactItem = $('.carousel-wrapper .carousel-inner .react-item') var maxw = $('.carousel-wrapper').width() /*var slideItemsFit = $reactItem.filter(function () { return $(this).position().left < maxw }).length*/ var itemsFitSlide = Math.floor(maxw / $reactItem.outerWidth(true)) console.log(itemsFitSlide) var margin = $reactItem.outerWidth(true) * itemsFitSlide margin = (maxw - margin) / itemsFitSlide / 2 $reactItem.css({marginLeft: `${margin}px`, marginRight: `${margin}px`}) this.setState({ itemsShownTotal: itemsFitSlide, itemWidth: $reactItem.outerWidth(true), navNextDisabled: (itemsFitSlide === this.state.items.length), itemsFitSlide: itemsFitSlide }) } componentDidMount() { this.updateCarousel() window.addEventListener("resize", this.updateCarousel, false) } handleNext(e) { var state = this.state var maxw = $('.carousel-wrapper').width() var innerWidth = -Math.abs(state.innerWidth - (state.itemWidth * state.itemsFitSlide)) var itemsLeft = state.items.length - state.itemsShownTotal var lastSlide = state.itemsFitSlide > itemsLeft if(lastSlide) { innerWidth = -Math.abs(state.innerWidth - (state.itemWidth * itemsLeft)) } var itemsShownTotal = (lastSlide) ? state.itemsShownTotal + itemsLeft : state.itemsShownTotal + state.itemsFitSlide this.setState({ itemsShownTotal: itemsShownTotal, innerWidth: innerWidth, navPrevDisabled: false, navNextDisabled: itemsShownTotal === state.items.length }) } handlePrev(e) { var state = this.state var innerWidth = state.innerWidth + (state.itemWidth * state.itemsFitSlide) //var itemsLeft = state.itemsFitSlide - state.itemsShownTotal var firstSlide = false if(innerWidth >= 0) { firstSlide = true innerWidth = 0 } var itemsShownTotal = (firstSlide) ? state.itemsFitSlide : state.itemsShownTotal - state.itemsFitSlide this.setState({ itemsShownTotal: itemsShownTotal, innerWidth: innerWidth, navPrevDisabled: firstSlide, navNextDisabled: false }) } render() { var nav = { prev: classNames({ navigation: true, prev: true, disabled: this.state.navPrevDisabled, whiteframe: true }), next: classNames({ navigation: true, next: true, disabled: this.state.navNextDisabled, whiteframe: true }) } return ( <section className="block collection carousel portrait"> <div className="scaffold"> <i className={nav.prev} onClick={this.handlePrev}></i> <i className={nav.next} onClick={this.handleNext}></i> <header className="collection-header"> <NavLink to={this.props.route}> <h2>{this.props.title}</h2> </NavLink> </header> <div className="carousel-wrapper"> <div className="carousel-inner use-transition" style={{transform: `translateX(${this.state.innerWidth}px)`}}> {this.state.items} </div> </div> </div> </section> ) } } 

基本上我们假设在一张幻灯片中有5张图片,但是在包装中只有足够的宽度来容纳4张图片,然后我想重做4张图片的过程和边缘以适应包装的中心。

carousel.css

 .scaffold { position: relative; } .block.collection .collection-header { margin: 0 0 20px; position: relative; padding-top: 20px; } .block.collection .collection-header h2 { outline: none; text-decoration: none; margin: 0; color: #212d33; font-size: 2.6rem; letter-spacing: -0.01em; line-height: 36px; font-weight: normal; } .block.collection.carousel .carousel-wrapper { overflow: hidden; width: 100%; } .block.collection.carousel .carousel-wrapper .carousel-inner { display: inline-block; margin-right: 5px; white-space: nowrap; } .block.collection.carousel .carousel-wrapper .carousel-inner.use-transition { transition: transform 0.5s ease-out; } .block.collection.portrait .react-item { width: 186px; margin: 0 0px 20px 0px; } .block.collection.portrait .react-item.hidden { opacity: 0; } .block.collection .react-item { position: relative; display: inline-block; vertical-align: top; margin-top: 10px; margin-bottom: 10px; } .block.collection.portrait .react-item .front { height: 279px; } .block.collection .react-item .front { background-color: #212d33; position: relative; display: block; text-decoration: none; } .block.collection .react-item .front .front-image { animation: fadein 500ms; position: absolute; height: 100%; width: 100%; top: 0; left: 0; background-size: cover; } .block.collection .react-item .backdrop { transition: opacity 0.1s ease-in-out; opacity: 0; height: 100%; position: absolute; width: 100%; top: 0; left: 0; z-index: 5; text-align: center; background: rgba(15, 22, 26, 0.25); } .block.collection .react-item .backdrop:hover { opacity: 1; } .react-play-button.fill { margin: 0; width: 100%; height: 100%; background-size: 68px; } .react-play-button { display: flex; align-items: center; justify-content: center; background-color: transparent; border: 0; padding: 0; cursor: pointer; } .react-play-button .icon-content { width: 68px; height: 68px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background-image: url(data:image/svg+xml;base64,PD+PC9zdHlsZT4KCiAgICA8Zz4KICAgICAgICA8Y2lyY2xlIHI9IjQ4IiBjeD0iNTAiIGN5PSI1MCIgLz4KICAgICAgICA8cG9seWxpbmUgcG9pbnRzPSI0MSwyOCA2Myw1MCA0MSw3MiIgLz4KICAgIDwvZz4KPC9zdmc+); background-size: contain; background-position: center; background-repeat: no-repeat; } .block.collection.carousel .navigation { top: 49%; border: none; cursor: pointer; position: absolute; width: 66px; background: rgba(249, 249, 251, 0.7); width: 48px; height: 60px; display: block; font-size: 0; border-radius: 2px; z-index: 10; opacity: 1; pointer-events: auto; transition: opacity .3s ease-in-out; } .block.collection.carousel .navigation.disabled { opacity: 0; pointer-events: none; } .block.collection.carousel .navigation:hover { background-color: #FFF; } .block.collection.carousel .navigation:hover::after { opacity: 1; } .block.collection.carousel .navigation.prev { left: -25px; } .block.collection.carousel .navigation.next { right: -25px; } .block.collection.carousel .navigation::after { transition: opacity .5s ease; background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjIuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAxMy40IDI0IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAxMy40IDI0OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Cgkuc3Qwe2ZpbGw6IzIxMkQzMzt9Cjwvc3R5bGU+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0wLDEuNEwxMC42LDEyTDAsMjIuNkwxLjQsMjRsMTItMTJMMS40LDBMMCwxLjR6Ii8+Cjwvc3ZnPgo=) no-repeat; width: 16px; height: 24px; content: ''; position: absolute; top: 18px; left: 18px; opacity: 0.7; } .block.collection.carousel .navigation.prev::after { left: 13px; transform: rotate(180deg); }