Created
June 10, 2018 15:15
-
-
Save zushenyan/f98c5bc4d791baa238abe394972ad405 to your computer and use it in GitHub Desktop.
This file contains 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
import React, { Component } from 'react'; | |
import $ from 'jquery'; | |
import _ from 'lodash'; | |
import 'normalize.css'; | |
import "slick-carousel/slick/slick.css"; | |
import "slick-carousel/slick/slick-theme.css"; | |
import './App.css'; | |
const translateArrayIndex = (arr, index) => { | |
const rest = index % arr.length; | |
return rest < 0 ? rest + arr.length : rest; | |
}; | |
const calcBoundry = (viewport, currentIndex, centerMode) => { | |
const shift = Math.floor(viewport.length / 2); | |
return { | |
leftMostIndex: centerMode ? currentIndex - shift : currentIndex, | |
rightMostIndex: centerMode ? currentIndex + shift : currentIndex + viewport.length, | |
}; | |
} | |
const applyKey = (data) => data.map((d, i) => ({ ...d, key: i })); | |
const applyViewportStlyes = ({ | |
enhancedData, | |
viewport, | |
currentIndex, | |
centerMode = false, | |
infinite = false, | |
}) => { | |
const { leftMostIndex, rightMostIndex } = calcBoundry(viewport, currentIndex, centerMode); | |
const result = _.range(leftMostIndex, rightMostIndex).reduce((acc, dataIndex, i) => { | |
if (!infinite) { | |
if (acc[dataIndex]) { | |
acc[dataIndex].viewProps = viewport[i] ; | |
} | |
} else { | |
const translatedDataIndex = translateArrayIndex(enhancedData, dataIndex); | |
acc[translatedDataIndex].viewProps = viewport[i]; | |
} | |
return acc; | |
}, _.cloneDeep(enhancedData)); | |
return result; | |
}; | |
const createEnhancedData = ({ | |
data, | |
viewport, | |
startIndex = 0, | |
centerMode = false, | |
infinite = false, | |
}) => { | |
let newData = infinite && data.length < viewport.length ? viewport.map((v, i) => data[translateArrayIndex(data, i)]) : data; | |
const dataWithKey = applyKey(newData); | |
return applyViewportStlyes({ | |
enhancedData: dataWithKey, | |
viewport, | |
currentIndex: startIndex, | |
centerMode, | |
infinite | |
}); | |
}; | |
const Template = ({ children }) => { | |
return ( | |
<div style={{ backgroundColor: 'lightgray' }}> | |
{children} | |
</div> | |
); | |
}; | |
const Carousel = ({ enhancedData }) => { | |
return ( | |
<div className="carousel"> | |
{ | |
enhancedData.map(({ | |
component: Component, | |
key, | |
viewProps: { | |
props: viewProps, | |
meta, | |
} = {} | |
}) => { | |
return viewProps ? ( | |
<div {...viewProps} key={key}> | |
<Component /> | |
</div> | |
) : null; | |
}) | |
} | |
</div> | |
) | |
} | |
class App extends Component { | |
constructor (props) { | |
super(props); | |
this.state = { | |
currentIndex: 0, | |
data: [ | |
{ | |
component: () => <Template>aaa</Template>, | |
}, | |
{ | |
component: () => <Template>bbb</Template>, | |
}, | |
{ | |
component: () => <Template>ccc</Template>, | |
}, | |
// { | |
// component: () => <Template>ddd</Template>, | |
// }, | |
// { | |
// component: () => <Template>eee</Template>, | |
// }, | |
], | |
viewport: [ | |
{ | |
props: { className: 'container sm', style: { left: '-250px', top: '100px', display: 'none' } }, | |
meta: {} | |
}, | |
{ | |
props: { className: 'container sm', style: { left: '-250px', top: '100px' } }, | |
meta: {} | |
}, | |
{ | |
props: { className: 'container sm', style: { left: '-50px', top: '100px' } }, | |
meta: {} | |
}, | |
{ | |
props: { className: 'container lg', style: { left: '250px', top: '50px' } }, | |
meta: {} | |
}, | |
{ | |
props: { className: 'container sm', style: { left: '650px', top: '100px' } }, | |
meta: {} | |
}, | |
{ | |
props: { className: 'container sm', style: { left: '850px', top: '100px' } }, | |
meta: {} | |
}, | |
{ | |
props: { className: 'container sm', style: { left: '850px', top: '100px', display: 'none' } }, | |
meta: {} | |
}, | |
], | |
enhancedData: [], | |
}; | |
this.state.enhancedData = createEnhancedData({ | |
data: this.state.data, | |
viewport: this.state.viewport, | |
startIndex: this.state.currentIndex, | |
centerMode: true, | |
infinite: true, | |
}); | |
} | |
hasNext = () => { | |
return true; | |
// const { data, currentIndex } = this.state; | |
// return !!data[currentIndex + 1]; | |
} | |
hasPrev = () => { | |
return true; | |
// const { data, currentIndex } = this.state; | |
// return !!data[currentIndex - 1]; | |
} | |
next = () => { | |
this.setState(({ | |
currentIndex, | |
enhancedData, | |
viewport, | |
}) => { | |
const newIndex = currentIndex + 1; | |
return { | |
currentIndex: newIndex, | |
enhancedData: applyViewportStlyes({ | |
enhancedData, | |
viewport, | |
currentIndex: newIndex, | |
centerMode: true, | |
infinite: true, | |
}), | |
}; | |
}); | |
} | |
prev = () => { | |
this.setState(({ | |
currentIndex, | |
enhancedData, | |
viewport | |
}) => { | |
const newIndex = currentIndex - 1; | |
return { | |
currentIndex: newIndex, | |
enhancedData: applyViewportStlyes({ | |
enhancedData, | |
viewport, | |
currentIndex: newIndex, | |
centerMode: true, | |
infinite: true, | |
}), | |
}; | |
}); | |
} | |
render() { | |
const { enhancedData } = this.state; | |
return ( | |
<div> | |
<div> | |
<Carousel | |
enhancedData={enhancedData} | |
/> | |
</div> | |
<button onClick={this.prev} disabled={!this.hasPrev()}>prev</button> | |
<button onClick={this.next} disabled={!this.hasNext()}>next</button> | |
</div> | |
); | |
} | |
} | |
export default App; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment