目录效果实现card-slider.tsxcard-item.tsxApp.tsx效果实现通过zIndex控制层级,opacity控制透明度,transform控制卡片缩放程度,marginLeft...
目录
效果实现
card-slider.tsx
card-item.tsx
App.tsx
效果
实现
通过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卡片滑动的资料请关注我们其它相关文章!










