实现tabs圆角及反圆角效果(PLUS)

10,263 阅读2分钟

先看UI稿

image.png

这个效果跟上篇实现tabs圆角及反圆角效果的区别在于 中间过渡斜线

思考

刚开始想着拿两个圆角来拼,但发现中间接触过渡效果很差

image.png

需要丝滑的话,想到贝塞尔曲线/正弦曲线,但这样太麻烦,需要用canvas来画

image.png

图形计算器

image.png

贝塞尔曲线

最后想到用斜边加圆角来拼,先试试

image.png

开搞

添加前后伪元素

    .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); // 重点
    }

image.png

调整圆角弧度

    .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; // 新增
    }

image.png

未选中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);
    }

image.png

修改选中tab周围的阴影

image.png

image.png

    .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; // 重点
    }

最后修复选中颜色,未选中颜色即可

image.png

image.png

image.png

无论多少个tabs,这个都没问题

image.png

image.png

整体代码

      <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数量需要根据条件变化就不行
  • 还看不明白的话,有空再整理代码片段发出来