在开发移动端官网时,设计师想要实现标签沿轨道运动的效果(如下),点击标签时沿轨道运动,点击的标签到位置1,其他依次排列,并伴随轮播,每个位置的标签样式不同。
设计思路如下:
一、标签动还是轨道动?
- 标签动:不同类名设置宽高、定位属性,点击时改变标签赋值的类名;要分清标签的顺序和位置的顺序
此时标签位置顺序为[0,1,2,3,4,5]
当标签运动时 此时标签位置顺序为[5,0,1,2,3,4](标签0在位置5)
即:我们需要拿到当前点击标签的顺序值,这个标签到位置1,其他的依次排列 如,点击标签4,则标签顺序变为[2,3,4,5,0,1],点击标签5,顺序变为[1,2,3,4,5,0]
代码以vue+scss为例 HTML:
<ul class="label_ul">
<li class="label_li" :class="`label${indexList[index]}`" :data-order="indexList[index]" ref="labelLi" @click="handleLabelChange($event, index)" v-for="(item, index) in labelList" :key="index" >
<div>{{ item.name }}</div>
</li>
</ul>
在data中存储当前的位置信息,indexList存储位置数组,初始为[0,1,2,3,4,5],之后点击动作即改变位置数组
CSS:
.label_ul {
.label_li {
position: absolute;
transition: all 300ms ease-in-out 0s;
}
.label0 {
width: 108px;
height: 56px;
top: 128px;
left: calc(50% - 53px);
z-index: 5;
font-size: 18px;
box-shadow: 0px 2px 0px 0px #2d63fb inset;
}
.label1{···}
.label2{···}
}
js:
method:{
handleLabelChange(e, index) {
this.order = e.currentTarget.dataset.order;//获取当前标签位置
this.currentIndex = index;//获取点击当前标签的index
},
},
watch:{
currentIndex(n){
if (n == 0) {
this.indexList = [0, 1, 2, 3, 4, 5];
} else if (n == 1) {
this.indexList = [5, 0, 1, 2, 3, 4];
} else if (n == 2) {
this.indexList = [4, 5, 0, 1, 2, 3];
} else if (n == 3) {
this.indexList = [3, 4, 5, 0, 1, 2];
} else if (n == 4) {
this.indexList = [2, 3, 4, 5, 0, 1];
} else if (n == 5) {
this.indexList = [1, 2, 3, 4, 5, 0];
}//此处标签个数比较固定,直接判断,可归纳为indexList[n]=0;
}
}
优化1:如果点击2/4,会直接到达位置0,期望效果,先到位置1/5,再到0
解决办法:当判断为位置2时,移到位置1,即将indexList末位删除移到首位; 当判断为位置4时,移到位置5,即将indexList首位删除移到末位;
watch:{
currentIndex(n){
if (this.order == 2) {
let num = this.indexList.pop();
this.indexList.unshift(num);
} else if (this.order == 4) {
let num = this.indexList.shift();
this.indexList.push(num);
}
if (n == 0) {
this.indexList = [0, 1, 2, 3, 4, 5];
} else if (n == 1) {
this.indexList = [5, 0, 1, 2, 3, 4];
} else if (n == 2) {
this.indexList = [4, 5, 0, 1, 2, 3];
} else if (n == 3) {
this.indexList = [3, 4, 5, 0, 1, 2];
} else if (n == 4) {
this.indexList = [2, 3, 4, 5, 0, 1];
} else if (n == 5) {
this.indexList = [1, 2, 3, 4, 5, 0];
}//此处标签个数比较固定,直接判断,可归纳为indexList[n]=0;
}
}
优化2:为了防止连续点击位置错乱,可加一个防抖函数;
- 轨道动:一个标签与轨道为整体,标签沿轨道运动实际为轨道的旋转
1、布局轨道与标签
<div class="track">
<div class="label">
</div>
</div>
2、将轨道旋转、压缩、变为椭圆
.track{
width: 315px;
height:315px;
transform: scaleY(0.5) rotateZ(180deg);
border-radius: 50%;
}
.label{
width: 108px;
height: 56px;
position: absolute;
top: -28px;
left: calc(50% - 54px);
box-shadow: 0px 2px 0px 0px #2d63fb inset;
transform: rotateZ(-180deg) scaleY(2);//先旋转,角度和轨道相反,后变为二倍
}
轨道transform中先scaleY(),后旋转,标签中为了不受影响要和轨道的相反
transform是有顺序的,因为CSS3D完全是由CSS2D演化而来的,并没有3D空间,所以就会按照顺序进行渲染,transform会造成整个坐标轴的转换,因此顺序十分重要。 可参考CSS3D原理
3、此时标签的旋转则为轨道整体的运动,只需要改变旋转角度即可
此时轨道和标签都要设置动画,但是顺序相反
4、重叠多个标签轨道,轨道border隐藏即可
二、与轮播联动
再点击标签的事件中,获取当前点击的标签索引值,再利用轮播事件滑动到相应模块,此处轮播使用的swiper,利用slideToLoop()滑动至当前页面。
swiper设置:
swiperOption: {
initialSlide :0,
loop: true,
centeredSlides: true,
slidesPerView: "auto",
spaceBetween: 12,
speed:750,
observer: true,
observeParents: true,
},
热知识:如果想实现swiper中间大两边小,滑块之间有空隙,可使用如下方法
.swiper-slide {
transform: scale(0.8);
}
.swiper-slide-active,.swiper-slide-duplicate-active{
transform: scale(1);
}
今天的文章标签沿轨道运动效果设计思路分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/19757.html