由于工作需要,写了一个人物卡片轮播的组件,卡片内容包括照片,姓名及介绍。要求人物个数大于等于五张,设置每次只显示五张卡片,点击后方的卡片时该卡片会跳到最中间显示。不点击时自动轮播。效果如上。
其实总的逻辑非常简单,大体的思路就是改变class属性。设置需要显示的五个卡片的class为 info-1,...,info-5。不显示的卡片则为 info-none。
通过点击更换显示卡片索引,根据显示卡片索引给它以及它左右两个卡片添加class属性 info-#{index},并将其他卡片设为 info-none 即可。
我之前最困惑的地方在于如何做出翻转的特效,差点就要手撕一个3d坐标转换的方法了。。还好得知 css3 有一个很溜的属性 transform,包含了一些现成的动画方法,例如 translate, scale,rotate,功能非常强大,建议查阅文档,动手尝试一番。本组件主要用到的是 translate3d 以及 scale3d。具体见代码。
基本功能都差不多实现了,只需要再利用 setInterval 和 clearInterval 设置定时操作,来实现自动轮播即可。注意,每次鼠标点击选择后,需要清空时间,重新计时。
代码的话,我是用的 vue 框架,逻辑部分的用的是 coffeescript,需要看JS的话就,emmmmm,去 coffeescript官网 可以自动转为JS (其实都差不多辣,逃
<template>
<div class="card-block">
<ul class="card-list">
<li class="card-info" v-for="card in cardInfo" :value="$index">
<img :src="card.img"/>
<h5>{{ card.title }}</h5>
<p>{{ card.content }}</p>
</li>
</ul>
</div>
</template>
<script lang="coffee">
module.exports =
props:
# 理论上卡片数量需要大于等于五张
cardInfo:
type: Array
default: []
# 是否自动轮播
autoDisplay:
type: Boolean
default: true
data: ->
# 卡片总数
cardTotal: 5
# 显示卡片数
displayCardNum: 5
# 当前卡片下标
currentCard: 2
# 用于设置自动轮播时间
autoChangeTimer: -1
methods:
# 初始化
InitCardDisplay: ->
for i in [0 .. 4]
$('.card-list').find("li[value$='#{i}']").addClass "info-#{i+1}"
for i in [5 .. @cardTotal - 1]
$('.card-list').find("li[value$='#{i}']").addClass "info-none"
@setAutoChange()
# 当 currentCard 更换时调用
changeCard: ->
for i in [0 .. @cardTotal - 1]
for j in [1 .. 5]
$('.card-list').find("li[value$='#{i}']").removeClass "info-#{j}"
$('.card-list').find("li[value$='#{i}']").addClass "info-none"
leftCardId = @currentCard - 2
rightCardId = @currentCard + 2
index = 1
for i in [leftCardId .. rightCardId]
i = (i + @cardTotal) % @cardTotal
$('.card-list').find("li[value$='#{i}']").removeClass "info-none"
$('.card-list').find("li[value$='#{i}']").addClass "info-#{index}"
index += 1
@setAutoChange()
# 设置自动轮播
setAutoChange: ->
if !@autoDisplay
return
@clearAutoChange()
@autoChangeTimer = setInterval =>
@currentCard = (@currentCard + 1) % @cardTotal
@changeCard()
, 3000
# 清除自动轮播
clearAutoChange: ->
clearInterval @autoChangeTimer
@autoChangeTimer = -1
ready: ->
@cardTotal = @cardInfo.length
@InitCardDisplay()
@setAutoChange()
vm = @
$('.card-list').on 'click', 'li', ->
vm.currentCard = $(this).val()
vm.clearAutoChange()
vm.changeCard()
</script>
<style lang="less">
.card-block {
width: 400px;
position: relative;
margin: 10px auto;
.card-list {
padding: 0px;
position: relative;
z-index: 100;
height: 375px;
width: 100%;
margin: 20px auto;
.card-info {
-webkit-transition: all 0.6s;
transition: all 0.6s;
background-color: white;
position: absolute;
border: 1px solid #C4C0BB;
list-style-type: none;
text-align: center;
width: 300px;
height: 375px;
padding: 20px 25px;
img {
border-radius: 50%;
border: 1px solid #C4C0BB;
height: 100px;
width: 100px;
}
h5 {
margin: 15px 0;
}
p {
font-size: 10px;
}
}
.info-1 {
left: 0;
z-index: 100;
filter: blur(2px);
-webkit-transform: translate3d(-104%, 12%, 0) scale3d(0.5, 0.5, 1);
transform: translate3d(-104%, 12%, 0) scale3d(0.5, 0.5, 1)
}
.info-2 {
left: 100px;
z-index: 110;
filter: blur(1px);
-webkit-transform: translate3d(-81%, 9%, 0) scale3d(0.7, 0.7, 1);
transform: translate3d(-81%, 9%, 0) scale3d(0.7, 0.7, 1);
}
.info-3 {
left: 200px;
z-index: 120;
-webkit-transform: translate3d(-50%, 0, 0);
transform: translate3d(-50%, 0, 0);
}
.info-4 {
left: 300px;
z-index: 110;
filter: blur(1px);
-webkit-transform: translate3d(-20%, 9%, 0) scale3d(0.7, 0.7, 1);
transform: translate3d(-20%, 9%, 0) scale3d(0.7, 0.7, 1);
}
.info-5 {
left: 400px;
z-index: 100;
filter: blur(2px);
-webkit-transform: translate3d(4%, 12%, 0) scale3d(0.5, 0.5, 1);
transform: translate3d(4%, 12%, 0) scale3d(0.5, 0.5, 1)
}
.info-none {
display: none;
}
}
}
</style>