我的目的是生成一个堆叠卡片的翻页组件,使用translate3d产生堆叠效果,但是在浏览器中堆叠部分总会被hidden。
后来我发现浏览器一开始没有加载CSS动画。但是当我鼠标在目标元素上进行移动后,才会加载出来CSS动画,然后堆叠被hidden部分就显示了。
js添加动画是在加载的时候。我在JS逻辑代码外部添加了判断,在代码块里添加了控制台打印。加载的时候打印了数据,但是移动的时候并没有打印出内容。添加动画确实是在一开始就有的,但是鼠标移动到目标元素上并没有执行css,这我就很奇妙啦
slidecard.vue:
- 主要是一个可拖拽的翻页组件,模仿其他人做的。
<ul
class="stack column"
ref="mySlideStack"
@touchstart.stop.prevent="stop"
@touchmove.stop.prevent="stop"
@touchend.stop.prevent="stop"
@touchcancel.stop.prevent="stop"
@mousedown.stop.prevent="stop"
@mouseup.stop.prevent="stop"
@mousemove.stop.prevent="stop"
@mouseout.stop.prevent="stop">
<li
class="stack-item"
v-for="(item, index) in pages"
:key="index"
:style="transform(index)"
@touchstart.capture.prevent="touchstart"
@touchmove.capture.prevent="touchmove"
@touchend.capture.prevent="touchend"
@touchcancel.capture.prevent="touchend"
@mousedown.capture.prevent="touchstart"
@mouseup.capture.prevent="touchend"
@mousemove.capture.prevent="touchmove"
@mouseout.capture.prevent="touchend"
@webkit-transition-end="onTransitionEnd"
@transitionend="onTransitionEnd">
<img :src="item">
</li>
</ul>
css代码(使用scss)
- 使用perspective和translate3d实现堆叠效果
.stack {
position: relative;
perspective: 1000px; //子元素视距
touch-action: none;
perspective-origin: 50% 150%; //子元素透视位置
transform: translate3d(0px, 0px, 0px);
}
.stack-item {
position: absolute;
height: 100%;
width: 100%;
border-radius: 4px;
text-align: center;
overflow: hidden;
user-select: none;
opacity: 0;
// 控制着用户能否选中文本
img {
width: 100%;
height: 100%;
// display: block;
pointer-events: none;
}
}
js代码(大部分都是拖拽的其实不必太关注)
- translate3d的值都是根据拖拽距离计算的,如何计算并不是重点不需要纠结。
// 计算出style
transform (index) {
let tempdata = this.tempdata
let currentPage = tempdata.currentPage
let length = this.pages.length
// 设置上一张
let lastPage = currentPage === 0 ? length - 1 : currentPage - 1
let style = {}
let visible = tempdata.visible // 可见层数
let transform = tempdata.prefixes.transform
let transition = tempdata.prefixes.transition
if (index === currentPage) { // 首页样式
style[transform] = `translate3d(${tempdata.poswidth}px, ${tempdata.posheight}px, 0px) rotate(${tempdata.rotate}deg)`
style['opacity'] = tempdata.opacity
style['zIndex'] = 10
if (tempdata.animation) {
style[transition + 'TimingFunction'] = 'ease'
style[transition + 'Duration'] = tempdata.animation ? '300ms' : '0ms'
}
} else if (this.findStack(index, currentPage)) { // 显示中图片
let perIndex = index - currentPage > 0 ? index - currentPage : index - currentPage + length // 和前面间隔层数
style['opacity'] = '1'
// 根据划出比例
style[transform] = `translate3d(0, 0, ${-1 * 60 * (perIndex - this.offsetRatio) / this.px2rem}rem)`
style['zIndex'] = visible - perIndex
if (!tempdata.tracking) {
// 兼容前缀
style[transition + 'TimingFunction'] = 'ease'
style[transition + 'Duration'] = '300ms'
}
} else if (index === lastPage) { // 设置翻过去的页的动画效果
style[transform] = `translate3d(${tempdata.lastPosWidth}px, ${tempdata.lastPosHeight}px, 0px) rotate(${tempdata.lastRotate}deg)`
style['opacity'] = tempdata.lastOpacity
style['zIndex'] = tempdata.lastZindex
style[transition + 'TimingFunction'] = 'ease'
style[transition + 'Duration'] = '300ms'
} else {
style['zIndex'] = '-1'
style[transform] = `translate3d(0, 0, ${-1 * visible * 60 / this.px2rem}rem)`
}
return style
},
// 鼠标移动或者触摸事件,判断只有拖拽的时候才执行代码块,所以鼠标单纯移动过并不会生效
touchmove (e) {
// 记录滑动位置
if (this.tempdata.tracking && !this.tempdata.animation) {
if (e.type === 'touchmove') { // 判断电脑和手机
this.basicdata.end.x = e.targetTouches[0].clientX
this.basicdata.end.y = e.targetTouches[0].clientY
} else {
this.basicdata.end.x = e.clientX
this.basicdata.end.y = e.clientY
}
// 计算滑动值
this.tempdata.poswidth = this.basicdata.end.x - this.basicdata.start.x
this.tempdata.posheight = this.basicdata.end.y - this.basicdata.start.y
// 计算翻转角度
let rotateDirection = this.rotateDirection()
let angleRatio = this.angleRatio()
this.tempdata.rotate = rotateDirection * this.offsetWidthRatio * 15 * angleRatio
}
}
实际上调用slidecard.vue的时候
- slide-wrapper去除overflow:hidden的时候,堆叠也会显示????
<div id="slide-wrapper" class="column">
<slide-card class="slide"></slide-card>
</div>
#slide-wrapper {
width: 100%;
height: 450px;
overflow: hidden;
justify-content: center;
background-color: #565f77;
}
.slide {
width: 320px;
height: 320px;
}
这就要看你js怎么写的了,也许你写的是鼠标移动到目标元素上,才会加载出来动画。