先看UI稿
这个效果跟上篇实现tabs圆角及反圆角效果的区别在于 中间过渡斜线
思考
刚开始想着拿两个圆角来拼,但发现中间接触过渡效果很差
需要丝滑的话,想到贝塞尔曲线/正弦曲线,但这样太麻烦,需要用canvas来画
最后想到用斜边加圆角来拼,先试试
开搞
添加前后伪元素
.tab-selected::before {
content: '';
position: absolute;
left: -6px;
bottom: 0;
width: 12px;
height: $tab-height;
background-color: red;
transform: skewX(-15deg); // 重点
}
.tab-selected::after {
content: '';
position: absolute;
right: -6px;
bottom: 0;
width: 12px;
height: $tab-height;
background-color: red;
transform: skewX(15deg); // 重点
}
调整圆角弧度
.tab-selected::before {
content: '';
position: absolute;
left: -6px;
bottom: 0;
width: 12px;
height: $tab-height;
background-color: red;
transform: skewX(-15deg);
border-top-left-radius: 12px; // 新增
}
.tab-selected::after {
content: '';
position: absolute;
right: -6px;
bottom: 0;
width: 12px;
height: $tab-height;
background-color: red;
transform: skewX(15deg);
border-top-right-radius: 12px; // 新增
}
未选中tab添加反圆角效果
.not-selected::before {
content: '';
position: absolute;
left: 6px;
bottom: 0;
width: 12px;
height: $tab-height;
border-bottom-left-radius: 12px;
background-color: yellow;
transform: skewX(15deg);
}
.not-selected::after {
content: '';
position: absolute;
right: 6px;
bottom: 0;
width: 12px;
height: $tab-height;
border-bottom-right-radius: 12px;
background-color: yellow;
transform: skewX(-15deg);
}
修改选中tab周围的阴影
.tab-selected {
opacity: 1;
background: #ffffff;
border-radius: 12px 12px 0 0;
box-shadow: 24px 40px 0 $active-color, -24px 40px 0 0 $active-color; // 重点
}
最后修复选中颜色,未选中颜色即可
无论多少个tabs,这个都没问题
整体代码
<div class="tab-list">
<div
v-for="tab in tabList"
:key="tab.id"
class="tab-item"
:class="activeTab === tab.id ? 'tab-selected' : 'not-selected'"
@click="onTab(tab.id)"
>
<image :src="tab.icon" class="tab-icon" />
<div>{{ tab.label }}</div>
</div>
</div>
// scss
$tab-height: 52px;
$active-color: #ffffff;
$default-color: #e2e8f8;
.tab-list {
display: flex;
position: relative;
z-index: 2;
border-radius: 12px 12px 0 0;
background-color: $default-color;
overflow: hidden; // 重点
.tab-item {
flex: 1;
height: $tab-height;
display: flex;
justify-content: center;
align-items: center;
font-size: 15px;
// opacity: 0.65; // 暂时删除,不选中样式需要重新编写
color: $primary-color;
font-weight: 600;
position: relative;
}
.tab-icon {
width: 17px;
height: 17px;
margin-right: 4px;
margin-top: 1px;
}
.tab-selected {
opacity: 1;
background: #ffffff;
border-radius: 12px 12px 0 0;
box-shadow: 24px 40px 0 $active-color, -24px 40px 0 0 $active-color; // 重点
}
.tab-selected::before {
content: '';
position: absolute;
left: -6px;
bottom: 0;
width: 12px;
height: $tab-height;
border-top-left-radius: 12px;
background-color: $active-color;
transform: skewX(-15deg); // 重点
}
.tab-selected::after {
content: '';
position: absolute;
right: -6px;
bottom: 0;
width: 12px;
height: $tab-height;
border-top-right-radius: 12px;
background-color: $active-color;
transform: skewX(15deg); // 重点
}
.not-selected::before {
content: '';
position: absolute;
left: 6px;
bottom: 0;
width: 12px;
height: $tab-height;
background: $default-color;
border-bottom-left-radius: 12px;
transform: skewX(15deg); // 重点
}
.not-selected::after {
content: '';
position: absolute;
right: 6px;
bottom: 0;
width: 12px;
height: $tab-height;
background: $default-color;
border-bottom-right-radius: 12px;
transform: skewX(-15deg); // 重点
}
}
总结
- 主要使用skewX变换处理,再结合上期发的实现tabs圆角及反圆角效果
- 注意,上期发的.tab-item使用opacity要去掉
- 其实,最简单的方法就是UI切图(多少个tab就切多少张背景图),但是tabs数量需要根据条件变化就不行
- 还看不明白的话,有空再整理代码片段发出来