我们在项目实践中,偶尔会为了增加页面内容的显示效果,使用卷轴展开的形式展示页面内容,以此来增加良好的交互和趣味性,卷轴的展开方式有两种,一种是向左或者向右单向展开,另一种是从中间向两边双向展开。
单向展开的卷轴实现起来相对比较容易,笔者不做讲解,这里笔者主要说明双向卷轴的实现。
先上效果图,感兴趣的继续,没兴趣的过。
思路:
1.显示未展开状态下的显示样式。
2.显示完全展开状态下的显示样式。
3.解决展开中状态下卷轴布始终居中问题和未展开部分隐藏问题。
1和2都非常简单,重点是3,咱们先解决未展开部分隐藏问题,这里笔者需要有个空间容器的概念,以ABC来举例:
A是房子,B是窗户,C是一张比窗户大的画布,那么我们想象站在房子外看窗户,肯定只能看到部分画布,这时,假设窗户可以逐渐变大,最终的效果我们就可以全部的画布。这里窗户就是卷轴的可见区域,窗户周围的画布我们看不到overflow:hidden,因此我们的元素层级为A包含B,B包含C。B处于A的中间位置,这个容易控制,居中设置就可以,C比B大,而且还要显示中间,所以C要相对于B进行定位,top:0;left:0;再来一个transform:translateX()将C向左移动就可以将C置于中间显示位置。
因为C是相对于B的定位,所以当B的大小变化时,C的移动就需要动态变化,不断更改移动的位置,以此来保证C位于B的显示中间。这里笔者使用了定时间,不断更改B的宽度大小和C的移动距离。
结构代码如下:
<template>
<div class="c-reel">
<div class="view" ref="view" :style="{width: viewWidth}">
<div class="content" ref="reel" :style="scrollStyle">
<slot></slot>
</div>
<img class="jz left-jz" src="../assets/questions/jz1.png" alt="左卷轴" :style="{left: jzLeft}" />
<img class="jz right-jz" src="../assets/questions/jz2.png" alt="右卷轴" :style="{right: jzRight}" />
</div>
</div>
</template>
设置C居中的代码如下:
/**
* 处理内部展开卷轴的移动位置
* 展开卷轴的宽度-可见区域的宽度,再除以2得到的值就是内部卷轴应该向左移动的位置
* 随着可见区域的扩大,向左移动位置应该动态改变,保证卷轴处于中间位置
*/
handleTransform() {
let viewWidth = this.$refs.view.clientWidth; // 可见区域的宽度
let scrollWidth = this.$refs.reel.clientWidth; // 获取展开卷轴的宽度
let translateX = (scrollWidth - viewWidth) / 2;
this.scrollStyle = {
transform: "translateX(-" + translateX + "px)"
};
}
样式代码如下:
<style lang="less" scoped>
.c-reel {
position: absolute;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -65%);
width: 100%;
height: 6rem;
.view {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 0.88rem;
height: 100%;
overflow: hidden;
.content {
width: 100vw;
height: 100%;
background: url("../assets/questions/jz.png") no-repeat center;
background-size: 100% 100%;
overflow: hidden;
position: relative;
}
}
.jz {
position: absolute;
top: 0;
width: 0.44rem;
height: 100%;
&.left-jz {
left: 0;
}
&.right-jz {
right: 0;
}
}
}
</style>
欢迎关注博主:小圣贤君,有问题可以留言哦~