A Pen by Selva Ganesh B on CodePen.
Created
May 3, 2017 11:51
-
-
Save selvagsz/d30e40afd1526a977c0e8403b4b1543a to your computer and use it in GitHub Desktop.
react-carousel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="react-root"> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Carousel extends React.Component { | |
state = { | |
translateX: 0, | |
}; | |
childDimensions = {}; | |
stashChildDimensions = ({ index, width, height }) => { | |
this.childDimensions[index] = { | |
width, | |
height, | |
}; | |
}; | |
setCarouselDimension(selectedIndex) { | |
let { width, height } = this.childDimensions[selectedIndex]; | |
this.setState({ | |
width, | |
height, | |
}); | |
} | |
renderChildren() { | |
let selectedIndex = this.props.selectedIndex; | |
return React.Children.map(this.props.children, (child, index) => { | |
if (child.type === CarouselItem) { | |
return React.cloneElement(child, { | |
index, | |
isActive: selectedIndex === index, | |
onMount: this.stashChildDimensions, | |
}); | |
} | |
return child; | |
}); | |
} | |
componentDidMount() { | |
this.setCarouselDimension(this.props.selectedIndex); | |
} | |
componentWillReceiveProps({ selectedIndex }) { | |
this.setCarouselDimension(selectedIndex); | |
} | |
render() { | |
let { selectedIndex } = this.props; | |
let { width, height } = this.state | |
return ( | |
<div | |
className="Carousel" | |
style={{ | |
width: `${width}px`, | |
height: `${height}px`, | |
}} | |
> | |
<CarouselBody | |
selectedIndex={selectedIndex} | |
childDimensions={this.childDimensions} | |
> | |
{this.renderChildren()} | |
</CarouselBody> | |
</div> | |
); | |
} | |
} | |
class CarouselBody extends React.Component { | |
state = { | |
translateX: 0 | |
}; | |
componentDidMount() { | |
let { childDimensions } = this.props; | |
let carouselBodyDimensions = Object.keys(childDimensions).reduce( | |
(prev, curr) => { | |
prev.width = prev.width + childDimensions[curr].width; | |
prev.height = prev.height + childDimensions[curr].height; | |
return prev; | |
}, | |
{ width: 0, height: 0 } | |
); | |
this.setState({ | |
...carouselBodyDimensions | |
}); | |
} | |
componentWillReceiveProps({ selectedIndex }) { | |
if (selectedIndex > this.props.selectedIndex) { | |
this.translateLeft(selectedIndex); | |
} else if (selectedIndex < this.props.selectedIndex) { | |
this.translateRight(selectedIndex); | |
} | |
} | |
translateLeft(selectedIndex) { | |
this.setState({ | |
translateX: this.state.translateX - | |
this.props.childDimensions[selectedIndex - 1].width | |
}); | |
} | |
translateRight(selectedIndex) { | |
this.setState({ | |
translateX: this.state.translateX + | |
this.props.childDimensions[selectedIndex].width | |
}); | |
} | |
render() { | |
let { children } = this.props; | |
let { width, translateX } = this.state; | |
return ( | |
<div | |
className="Carousel__Body" | |
style={{ | |
width: `${width}px`, | |
transform: `translate3d(${translateX}px, 0, 0)` | |
}} | |
> | |
{children} | |
</div> | |
); | |
} | |
} | |
class CarouselItem extends React.Component { | |
componentDidMount() { | |
let { index, onMount } = this.props; | |
onMount({ | |
index, | |
width: this.carouselItem.offsetWidth, | |
height: this.carouselItem.offsetHeight | |
}); | |
} | |
render() { | |
let { isActive, children, className } = this.props; | |
return ( | |
<div | |
className={`Carousel__Item ${className} ${isActive ? 'Carousel__Item--active' : ''}`} | |
ref={element => (this.carouselItem = element)} | |
> | |
{children} | |
</div> | |
); | |
} | |
} | |
class App extends React.Component { | |
state = { | |
selectedIndex: 0 | |
}; | |
gotoPrev = () => { | |
this.setState({ | |
selectedIndex: this.state.selectedIndex-1 | |
}) | |
}; | |
gotoNext = () => { | |
this.setState({ | |
selectedIndex: this.state.selectedIndex + 1 | |
}) | |
}; | |
render() { | |
return ( | |
<div> | |
<Carousel selectedIndex={this.state.selectedIndex}> | |
<CarouselItem className="bg-color-1"> | |
<h1>Item 1</h1> | |
</CarouselItem> | |
<CarouselItem className="bg-color-2"> | |
<h1>Item 2</h1> | |
</CarouselItem> | |
<CarouselItem className="bg-color-3"> | |
<h1>Itezm 3</h1> | |
</CarouselItem> | |
<CarouselItem className="bg-color-4"> | |
<h1>Itzzzzzzzzem 4</h1> | |
<h1>Itzzzzzzzzem 4</h1> | |
<h1>Itzzzzzzzzem 4</h1> | |
<h1>Itzzzzzzzem 4</h1> | |
</CarouselItem> | |
</Carousel> | |
<div> | |
<button onClick={this.gotoPrev}>Prev</button> | |
<button onClick={this.gotoNext}>Next</button> | |
</div> | |
</div> | |
) | |
} | |
} | |
ReactDOM.render(<App />, document.getElementById('react-root')); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.min.js"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.Carousel { | |
overflow: hidden; | |
display: inline-block; | |
transition: width 0.3s, height 0.35s; | |
} | |
.Carousel__Body { | |
transition: transform 0.3s; | |
} | |
.Carousel__Body::before, .Carousel__Body::after { | |
content: ''; | |
display: table; | |
clear: both; | |
} | |
.Carousel__Item { | |
float: left; | |
padding: 40px; | |
background-color: #00ffbb; | |
} | |
@mixin random-color($selector) { | |
#{$selector}: unquote("rgba(#{random(256) - 25}, #{random(256) - 1}, #{random(256) - 5}, #{random(100)/50})"); | |
} | |
@for $i from 1 to 4 { | |
.bg-color-#{$i} { | |
@include random-color('background-color'); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment