<div class="flap-card" v-for="(item, index) in flapCardList" :key="index" :style="{zIndex: item.zIndex}">
<div class="flap-card-circle">
<div class="flap-card-semi-circle flap-card-semi-circle-left" :style="semiCircleStyle(item, 'left')"
ref="left"></div>
<div class="flap-card-semi-circle flap-card-semi-circle-right" :style="semiCircleStyle(item, 'right')"
ref="right"></div>
</div>
</div>
data() {
return {
front: 0,
back: 1,
}
},
methods: {
// flapCardList是存储着图片信息的对象数组,通过v-for循环和semiCircleStyle方法设置5组图片的背景。
semiCircleStyle(item, dir) {
return {
backgroundColor: `rgb(${item.r}, ${item.g}, ${item.b})`,
backgroundSize: item.backgroundSize,
backgroundImage: dir === 'left' ? item.imgLeft : item.imgRight
}
},
rotate(index, type) {
//卡牌翻转,"front"选择右边卡片,否则选择左边卡片;然后改变dom元素的样式
const item = this.flapCardList[index]
let dom
if (type === 'front') {
dom = this.$refs.right[index]
} else {
dom = this.$refs.left[index]
}
dom.style.transform = `rotateY(${item.rotateDegree}deg)`
dom.style.backgroundColor = `rgb(${item.r}, ${item._g}, ${item.b})`
},
flapCardRotate() {
//首先是翻转函数,每次翻转分正反两面。当动画至90°时,改变背面的z-index值,每一帧动画完毕执行rotate函数以改变样式。
const frontFlapCard = this.flapCardList[this.front]
const backFlapCard = this.flapCardList[this.back]
frontFlapCard.rotateDegree += 10
frontFlapCard._g -= 5
backFlapCard.rotateDegree -= 10
if (backFlapCard.rotateDegree < 90) {
backFlapCard._g += 5
}
if (frontFlapCard.rotateDegree === 90 && backFlapCard.rotateDegree === 90) {
backFlapCard.zIndex += 2
}
this.rotate(this.front, 'front')
this.rotate(this.back, 'back')
if (frontFlapCard.rotateDegree === 180 && backFlapCard.rotateDegree === 0) {
this.next()
}
},
prepare() {
const backFlapCard = this.flapCardList[this.back]
backFlapCard.rotateDegree = 180
backFlapCard._g = backFlapCard.g - 5 * 9
this.rotate(this.back, 'back')
},
next() {
const frontFlapCard = this.flapCardList[this.front]
const backFlapCard = this.flapCardList[this.back]
frontFlapCard.rotateDegree = 0
backFlapCard.rotateDegree = 0
frontFlapCard._g = frontFlapCard.g
backFlapCard._g = backFlapCard.g
this.rotate(this.front, 'front')
this.rotate(this.back, 'back')
this.front++
this.back++
const len = this.flapCardList.length
if (this.front >= len) {
this.front = 0
}
if (this.back >= len) {
this.back = 0
}
// 动态设置zIndex
// 100 -> 96
// 99 -> 100
// 98 -> 99
// 97 -> 98
// 96 -> 97
// (0 - 1 + 5) % 5 = 4
// (1 - 1 + 5) % 5 = 0
this.flapCardList.forEach((item, index) => {
item.zIndex = 100 - ((index - this.front + len) % len)
})
this.prepare()
},
startFlapCardAnimation() {
this.prepare()
this.task = setInterval(() => {
this.flapCardRotate()
}, this.intervalTime)
},
stopAnimation() {
//动画停止时,清除所有setTimeout;否则再次进入动画出现错误。
if (this.task) {
clearInterval(this.task)
}
if (this.timeout) {
clearTimeout(this.timeout)
}
if (this.timeout2) {
clearTimeout(this.timeout2)
}
this.reset()
},
runAnimation() {
//点击推荐,则动画开始(vuex中定义了flapCardVisible,watch监听其变化,为TRUE则动画开始)
this.runFlapCardAnimation = true
this.timeout = setTimeout(() => {
this.startFlapCardAnimation()
this.startPointAnimation()
}, 300)
this.timeout2 = setTimeout(() => {
this.stopAnimation()
//2500ms过渡动画结束,推荐图书显示
this.runBookCardAnimation = true
}, 2500)
},
watch: {
flapCardVisible(v) {
if (v) {
this.runAnimation()
}
}
},
}
|