需求描述
产品说小程序首页的合作品牌列表有16张(固定16张),但是一次性只展示8张,另外8张随机翻转展示,如下:
实现需求
这个好实现,基本思路:写八个容器,每个容器放两张图片(一张正面一张反面),然后写一个能让它们翻转的css3动画,定义一个active变量,通过这个变量的值来判断哪个容器执行翻转动画(加上相应的class),然后定义一个定时器,利用Math.random()来随机改变active的值,就实现了,核心代码如下:
js部分:
componentDidMount () {
this._getBanner()
// this.getChamp('all')
// this.getChamp('month')
this._getbrandList()
this.setState({
times: setInterval(() => {
let num = (Math.random() * 10).toFixed(0)
if (num > 7) {
num -= 3
}
this.setState({
active: num
})
}, 8000)
})
}
View部分:
<View className={styles.title}>合作品牌</View>
<View className={styles.coopBrand}>
<View className={styles.flipContainer}>
<View className={this.state.active === 0 ? styles.transform : ''}>
<View className={styles.front}>
<Image className={styles.brandPic} src={this.state.brandList[0] && this._transformUrl(this.state.brandList[0].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
<View className={styles.back}>
<Image className={styles.brandPic} src={this.state.brandList[8] && this._transformUrl(this.state.brandList[8].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
</View>
</View>
<View className={styles.flipContainer}>
<View className={this.state.active === 1 ? styles.transform : ''}>
<View className={styles.front}>
<Image className={styles.brandPic} src={this.state.brandList[1] && this._transformUrl(this.state.brandList[1].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
<View className={styles.back}>
<Image className={styles.brandPic} src={this.state.brandList[9] && this._transformUrl(this.state.brandList[9].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
</View>
</View>
<View className={styles.flipContainer}>
<View className={this.state.active === 2 ? styles.transform : ''}>
<View className={styles.front}>
<Image className={styles.brandPic} src={this.state.brandList[2] && this._transformUrl(this.state.brandList[2].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
<View className={styles.back}>
<Image className={styles.brandPic} src={this.state.brandList[10] && this._transformUrl(this.state.brandList[10].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
</View>
</View>
<View className={styles.flipContainer}>
<View className={this.state.active === 3 ? styles.transform : ''}>
<View className={styles.front}>
<Image className={styles.brandPic} src={this.state.brandList[3] && this._transformUrl(this.state.brandList[3].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
<View className={styles.back}>
<Image className={styles.brandPic} src={this.state.brandList[11] && this._transformUrl(this.state.brandList[11].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
</View>
</View>
<View className={styles.flipContainer}>
<View className={this.state.active === 4 ? styles.transform : ''}>
<View className={styles.front}>
<Image className={styles.brandPic} src={this.state.brandList[4] && this._transformUrl(this.state.brandList[4].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
<View className={styles.back}>
<Image className={styles.brandPic} src={this.state.brandList[12] && this._transformUrl(this.state.brandList[12].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
</View>
</View>
<View className={styles.flipContainer}>
<View className={this.state.active === 5 ? styles.transform : ''}>
<View className={styles.front}>
<Image className={styles.brandPic} src={this.state.brandList[5] && this._transformUrl(this.state.brandList[5].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
<View className={styles.back}>
<Image className={styles.brandPic} src={this.state.brandList[13] && this._transformUrl(this.state.brandList[13].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
</View>
</View>
<View className={styles.flipContainer}>
<View className={this.state.active === 6 ? styles.transform : ''}>
<View className={styles.front}>
<Image className={styles.brandPic} src={this.state.brandList[6] && this._transformUrl(this.state.brandList[6].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
<View className={styles.back}>
<Image className={styles.brandPic} src={this.state.brandList[14] && this._transformUrl(this.state.brandList[14].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
</View>
</View>
<View className={styles.flipContainer}>
<View className={this.state.active === 7 ? styles.transform : ''}>
<View className={styles.front}>
<Image className={styles.brandPic} src={this.state.brandList[7] && this._transformUrl(this.state.brandList[7].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
<View className={styles.back}>
<Image className={styles.brandPic} src={this.state.brandList[15] && this._transformUrl(this.state.brandList[15].fdBrandPic) + '?x-oss-process=image/resize,w_104/format,png'} mode='aspectFit' />
</View>
</View>
</View>
</View>
CSS部分:
.brandPic {
width: 100%;
height: 100%;
}
.flipContainer {
display: inline-block;
margin: 25px 40px 10px 40px;
perspective: 1000;
}
.transform{
transform-style: preserve-3d;
position: relative;
animation: myfirst 8s infinite;
}
@keyframes myfirst {
0% {transform: rotateY(0deg);}
25% {transform: rotateY(90deg);}
50% {transform: rotateY(180deg);}
75% {transform: rotateY(270deg);}
100% {transform: rotateY(360deg);}
}
.flipContainer, .front, .back {
width: 95px;
height: 95px;
}
.front, .back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
.back {
transform: rotateY(180deg);
}
遇到问题
结果发现并不是每一次图片都会翻转,那就打印一下active的值看一下它是否改变了吧!
times: setInterval(() => {
let num = (Math.random() * 10).toFixed(0)
if (num > 7) {
num -= 3
}
console.log(num)
this.setState({
active: num
})
}, 8000)
但是神奇的一幕出现了,active的值是改变了的,但有些是紫色有些是白色(紫色是number白色是string),显然是有问题的,在view里使用的是===,即类型不相等时就无法判断为true,从而导致无法加上class,那为啥呢?换个位置打印一下吧:
times: setInterval(() => {
let num = (Math.random() * 10).toFixed(0)
console.log(num)
if (num > 7) {
num -= 3
}
this.setState({
active: num
})
}, 8000)
果然在使用toFixed(0)处理后就变成了字符串,只是当num > 7时执行下一步if判断的时候把num转成了数字,查了一下文档,果然toFixed()方法返回的是一个字符串,这是一个坑,这个方法是做四舍五入处理的,当然是处理数字的,正常逻辑下返回的也应该是数字吧,结果却不是,这个问题需要记录一下,分享给大家,防止大家踩同样的坑。
解决问题
可以在toFixed()处理完后把num使用Number()方法转一下,或者在view中把 === 改成 == ,前者比后者多一行代码,差别不大。
文章已转移到个人公众号,有帮到你的话,用发财的小手关注一下我的公众号呗~