react card slider实现滑动卡片教程示例

2022-09-03 11:11:43

目录效果实现card-slider.tsxcard-item.tsxApp.tsx效果实现通过zIndex控制层级,opacity控制透明度,transform控制卡片缩放程度,marginLeft...

目录
效果
实现
card-slider.tsx
card-item.tsx
App.tsx

效果

react card slider实现滑动卡片教程示例

实现

通过zIndex控制层级,opacity控制透明度,transform%20控制卡片缩放程度,marginLeft控制位置,剩下的就是计算的事了

card-slider.tsx

import%20React%20from%20'react' export%20type%20CardProps%20=%20{ %20%20opacity:%20number %20%20scale:%20number %20%20loop?:%20boolean %20%20width:%20number %20%20disablePrev?:%20boolean %20%20disableNext?:%20boolean %20%20boxWidth:%20number %20%20index?:%20number %20%20list:%20any[] %20%20renderItem(data:%20any):%20React.ReactNode %20%20onChange?:%20(index:%20number,%20data:%20any)%20=>%20void %20%20stpythonyle?:%20React.cssProperties } type%20CardState%20=%20{ %20%20activeIndex:%20number %20%20moving:%20boolean } export%20default%20class%20CardSlider%20extends%20React.Component<CardProps,%20CardState>%20{ %20%20static%20defaultProps:%20Partial<CardProps>%20=%20{ %20%20%20%20opacity:%200.9, %20%20%20%20scale:%200.9, %20%20%20%20loop:%20false, %20%20%20%20disablePrev:%20false, %20%20%20%20disableNext:%20false %20%20} %20%20constructor(props:%20CardProps)%20{ %20%20%20%20super(props) %20%20%20%20this.state%20=%20{ %20%20%20%20%20%20activeIndex:%20props.index%20||%200, %20%20%20%20%20%20moving:%20false %20%20%20%20} %20%20} %20%20componentWillReceiveProps(nextProps:%20any)%20{ %20%20%20%20if%20(this.props.index%20!==%20nextProps.index)%20{ %20%20%20%20%20%20this.setState({ %20%20%20%20%20%20%20%20activeIndex:%20nextProps.index %20%20%20%20%20%20}) %20%20%20%20} %20%20} %20%20//%20卡片总数量 %20%20get%20totalCount()%20{ %20%20%20%20return%20this.props.list.length %20%20} %20%20//%20间隔宽度 %20%20get%20gridwidth()%20{ %20%20%20%20const%20isEven%20=%20this.totalCount%20%%202%20===%200 %20%20%20%20const%20{%20width,%20boxWidth%20}%20=%20this.props %20%20%20%20return%20(boxWidth%20-%20width)%20/%20(isEven%20?%20this.totalCount%20:%20this.totalCount%20-%201) %20%20} %20%20//%20禁用prev %20%20get%20disablePrev()%20{ %20%20%20%20const%20{%20loop,%20disablePrev%20}%20=%20this.props %20%20%20%20const%20{%20activeIndex%20}%20=%20this.state %20%20%20%20if%20(disablePrev)%20return%20true %20%20%20%20return%20!loop%20&&%20activeIndex%20===%200 %20%20} %20%20//%20禁用prev %20%20get%20disableNext()%20{ %20%20%20%20const%20{%20loop,%20disableNext%20}%20=%20this.props %20%20%20%20const%20{%20activeIndex%20}%20=%20this.state %20%20%20%20if%20(disableNext)%20return%20true %20%20%20%20return%20!loop%20&&%20activeIndex%20===%20this.totalCount%20-%201 %20%20} %20%20/** %20%20%20*%20offset:%20是左或者右的第几个 %20%20%20*%20direction:%201:右侧:-1:左侧 %20%20%20*/ %20%20getDirection(index:%20number)%20{ %20%20%20%20const%20{%20activeIndex%20}%20=%20this.state http://www.cppcns.com%20%20%20%20let%20direction%20=%201 %20%20%20%20if%20( %20%20%20%20%20%20index%20-%20activeIndex%20>%20this.totalCount%20/%202%20|| %20%20%20%20%20%20(index%20-%20activeIndex%20<%200%20&&%20index%20-%20activeIndex%20>%20-this.totalCount%20/%202) %20%20%20%20)%20{ %20%20%20%20%20%20direction%20=%20-1 %20%20%20%20} %20%20%20%20let%20offset%20=%20Math.abs(index%20-%20activeIndex) %20%20%20%20if%20(offset%20>%20this.totalCount%20/%202)%20{ %20%20%20%20%20%20offset%20=%20activeIndex%20+%20this.totalCount%20-%20index %20%20%20%20} %20%20%20%20if%20(index%20-%20activeIndex%20<%20-this.totalCount%20/%202)%20{ %20%20%20%20%20%20offset%20=%20this.totalCount%20+%20index%20-%20activeIndex %20%20%20%20} %20%20%20%20return%20{ %20%20%20%20%20%20direction, %20%20%20%20%20%20offset %20%20%20%20} %20%20} %20%20render()%20{ %20%20%20%20const%20{%20list,%20renderItem,%20opacity,%20scale,%20width,%20boxWidth,%20style%20=%20{}%20}%20=%20this.props %20%20%20%20return%20( %20%20%20%20%20%20<div%20style={{%20...styles.wrapper,%20...style%20}}> %20%20%20%20%20%20%20%20<div%20style={{%20...styles.content,%20width:%20boxWidth%20}}> %20%20%20%20%20%20%20%20%20%20{list.map((data,%20index)%20=>%20{ %20%20%20%20%20%20%20%20%20%20%20%20const%20{%20direction,%20offset%20}%20=%20this.getDirection(index) %20%20%20%20%20%20%20%20%20%20%20%20const%20realScale%20=%20Math.pow(scale,%20offset) %20%20%20%20%20%20%20%20%20%20%20%20return%20renderItem({ %20%20%20%20%20%20%20%20%20%20%20%20%20%20key:%20index, %20%20%20%20%20%20%20%20%20%20%20%20%20%20...data, %20%20%20%20%20%20%20%20%20%20%20%20%20%20style:%20{ %20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20position:%20'absolute', %20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20left:%20'50%', %20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20marginLeft:%20this.gridWidth%20*%20direction%20*%20offset%20+%20direction%20*%20((width%20/%202)%20*%20(1%20-%20realScale)), %20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20zIndex:%20this.totalCount%20-%20offset, %20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20opacity:%20Math.pow(opacity,%20offset), %20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform:%20`translateX(-50%)%20translateZ(0)%20scale(${realScale})`, %20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transition:%20'all%20300ms' %20%20%20%20%20%20%20%20%20%20%20%20%20%20} %20%20%20%20%20%20%20%20%20%20%20%20}) %20%20%20%20%20%20%20%20%20%20})} %20%20%20%20%20%20%20%20</div> %20%20%20%20%20%20%20%20{!this.disablePrev%20&&%20( %20%20%20%20%20%20%20%20%20%20<a%20href="Javascript:;"%20rel="external%20nofollow"%20%20rel="external%20nofollow"%20%20style={{%20...styles.btn,%20left:%2035%20}}%20onClick={this.handlePrev}> %20%20%20%20%20%20%20%20%20%20%20%20{'<'} %20%20%20%20%20%20%20%20%20%20</a> %20%20%20%20%20%20%20%20)} %20%20%20%20%20%20%20%20{!this.disableNext%20&&%20( %20%20%20%20%20%20%20%20%20%20<a%20href="javascript:;"%20rel="external%20nofollow"%20%20rel="external%20nofollow"%20%20style={{%20...styles.btn,%20right:%2035%20}}%20onClick={this.handleNext}> %20%20%20%20%20%20%20%20%20%20%20%20{'>'} %20%20%20%20%20%20%20%20%20%20</a> %20%20%20%20%20%20%20%20)} %20%20%20%20%20%20</div> %20%20%20%20) %20%20} %20%20handlePrev%20=%20()%20=>%20{ %20%20%20%20let%20{%20activeIndex%20}%20=%20this.state %20%20%20%20if%20(this.disablePrev)%20return %20%20%20%20activeIndex%20=%20--activeIndex%20<%200%20?%20this.totalCount%20-%201%20:%20activeIndex %20%20%20%20this.setState({%20activeIndex%20}) %20%20%20%20this.handleChange(activeIndex) %20%20} %20%20handleNext%20=%20()%20=>%20{ %20%20%20%20let%20{%20activeIndex%20}%20=%20this.state %20%20%20%20if%20(this.disableNext)%20return %20%20%20%20activeIndex%20=%20++activeIndex%20>=%20this.totalCount%20?%200%20:%20activeIndex %20%20%20%20this.setState({%20activeIndex%20}) %20%20%20%20this.handleChange(activeIndex) %20%20} %20%20handleChange%20=%20(index:%20number)%20=>%20{ %20%20%20%20const%20{%20list,%20onChange%20}%20=%20this.props %20%20%20%20onChange%20&&%20onChange(index,%20list[index]) %20%20} } const%20styles:%20{%20[name:%20string]:%20React.CSSProperties%20}%20=%20{ %20%20wrapper:%20{ %20%20%20%20position:%20'relative', %20%20%20%20display:%20'Flex', %20%20%20%20justifyContent:%20'center', %20%20%20%20width:%20'100%' %20%20}, %20%20content:%20{ %20%20%20%20height:%20210, %20%20%20%20position:%20'relative' %20%20}, %20%20btn:%20{ %20%20%20%20position:%20'absolute', %20%20%20%20top:%20'50%', %20%20%20%20transform:%20'translateY(-50%)', %20%20%20%20width:%2036, %20%20%20%20height:%2036, %20%20%20%20zIndex:%2099, %20%20%20%20display:%20'flex', %20%20%20%20justifyContent:%20'center', %20%20%20%20alignItems:%20'center', %20%20%20%20fontSize:%2024 %20%20} }

card-item.tsx

import%20React%20from%20'react' const%20CardItem%20=%20({%20style,%20url%20})%20=>%20{ %20%20return%20( %20%20%20%20<div %20%20%20%20%20%20style={{ %20%20%20%20%20%20%20%20width:%20375, %20%20%20%20%20%20%20%20height:%20208, %20%20%20%20%20%20%20%20background:%20'#000', %20%20%20%20%20%20%20%20color:%20'#fff', %20%20%20%20%20%20%20%20borderRadius:%205, %20%20%20%20%20%20%20%20textAlign:%20'center', %20%20%20%20%20%20%20%20...style %20%20%20%20%20%20}} %20%20%20%20> %20%20%20%20%20%20<img%20src={url}%20width="100%"%20height="100%"%20/> %20%20%20%20</div> %20%20) } export%20default%20CardItem

App.tsx

import%20CardSlider%20from%20'./card-slider' import%20CardItem%20from%20'./card-item' import%20'./App.scss' const%20list%20=%20[ %20%20{ %20%20%20%20name:%20'1', %20%20%20%20url:%20'https://m15.360buyimg.com/mobilecms/jfs/t1/218369/27/14203/132191/6226a702E5a0b9236/a11294e884bc7635.jpg!cr_1053x420_4_0!q70.jpg' }, { name: '2', url: 'https://m15.360buyimg.com/mobilecms/jfs/t1/158791/25/27003/106834/620c4bc2Efb15fc57/7c89841a597ce41b.jpg!cr_1053x420_4_0!q70.jpg' }, { name: '3', url: 'https://m15.360buyimg.com/mobilecms/jfs/t1/117358/2/22877/138901/6228342eE68ae2c88/f8a9aDB2642c1313.jpg!cr_1053x420_4_0!q70.jpg' }, { name: '4', url: 'https://m15.360buyimg.com/mobilecms/jfs/t1/121592/2/24818/138081/622ccc8fEdf840f95/cd229433d699c70c.jpg!cr_1053x420_4_0!q70.jpg' }, { name: '5', url: 'https://imgcps.jd.com/ling-cubic/danpin/lab/amZzL3QxLzE2Mjc4Mi8zNi85MTM4LzQ0NjQ1MS82MDQwN2Q4MUVkMDlmMWM5OC9jZWVmOWU0OWVkNzlkNjZkLnBuZw/6Zi_6L-q6L6-5pav6LeR5q2l6Z6L/5qmh6IO25aSW5bqV/60586f6fa1b18f3314204f2d/cr_1125x449_0_166/s/q70.jpg' }, { name: '6', url: 'https://imgcps.jd.com/img-cubic/creative_server_cid/v2/2000755/10041170380456/FocusActivity/CkNqZnMvdDEvMjExMDQ2LzIyLzExMTc3Lzc0NTA0LzYxYTU4MzAwRWU1YjQ0OTcxL2Q5YjE5NzlmOGJkMjAzNzIuanBnEgs4NDIteGNfMF81MjABOPOOekIWChLkuprnkZ_lo6vot5HmraXpnosQAEIQCgzpkpzmg6DnmbvlnLoQAUIQCgznq4vljbPmiqLotK0QAkIKCgbkvJjpgIkQBw/cr_1053x420_4_0/s/q70.jpg' }, { name: '7', url: 'https://m15.360buyimg.com/mobilecms/jfs/t1/117358/2/22877/138901/6228342eE68ae2c88/f8a9adb2642c1313.jpg!cr_1053x420_4_0!q70.jpg' } ] export default function App() { return ( http://www.cppcns.com<div style={{ paddingTop: '20%'}}> <CardSlider list={list} renderItem={CardItem} width={375} boxWidth={500} opacity={0.75} scale={0.9} disableNext={false} disablePrev={false} onChange={(index: number, data: any) => { console.log(index, data) }} /> </div> ) }

以上就是react card slider实现滑动卡片教程的详细内容,更多关于react card slider卡片滑动的资料请关注我们其它相关文章!