仿uni-segmented-control添加左右滑动效果

        官网的选项卡没有左右滑动的效果,本身的样式也不太好看,所以封装了个简易的组件达到相同的效果,可自行修改css部分修改样式~

封装组件效果如下

custom-segmented-control.vue

<template>
  <view class="container">
    <view
      class="custom-segmented-control"
      @touchstart="onTouchStart"
      @touchend="onTouchEnd"
    >
      <view
        v-for="(value, index) in values"
        :key="index"
        :class="{ active: index === current }"
        class="title"
        @click="handleClick(index)"
      >
        {{ value }}
      </view>
      <view
        class="indicator"
        :style="{
          left: `${current * (100 / values.length) + 100 / values.length / 3}%`,
          width: `${100 / values.length / 3}%`,
        }"
      ></view>
    </view>
  </view>
</template>

<script>
export default {
  props: {
    current: {
      type: Number,
      default: 0,
    },
    values: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      touchStartX: 0,
    };
  },
  methods: {
    handleClick(index) {
      this.$emit("clickItem", { index });
    },
    onTouchStart(e) {
      this.touchStartX = e.changedTouches[0].clientX;
    },
    onTouchEnd(e) {
      const touchEndX = e.changedTouches[0].clientX;
      const deltaX = touchEndX - this.touchStartX;
      const threshold = 50;

      if (deltaX > threshold) {
        if (this.current > 0) {
          this.$emit("clickItem", { index: this.current - 1 });
        }
      } else if (deltaX < -threshold) {
        if (this.current < this.values.length - 1) {
          this.$emit("clickItem", { index: this.current + 1 });
        }
      }
    },
  },
};
</script>

<style scoped>
.container {
  height: 36px;
  overflow: hidden;
  cursor: pointer;
}

.custom-segmented-control {
  display: flex;
  /* 平均分配子元素空间 */
  justify-content: space-between;
  align-items: center;
  position: relative;
}

.custom-segmented-control > view {
  /* 平均分配宽度 */
  flex: 1;
  cursor: pointer;
  text-align: center;
}
.title {
  font-size: 14px;
  line-height: 20px;
  text-align: center;
}

.active {
  color: #333333;
  font-weight: bold;
  padding: 4px 0;
}

.indicator {
  position: absolute; /* 绝对定位 */
  bottom: -4px; /* 与内容底部对齐 */
  height: 4px; /* 下划线的高度 */
  background-color: #0574ff;
  border-radius: 4px; /* 设置圆角 */
  will-change: left; /* 告知浏览器 left 属性即将变化 */
  transition: left 0.1s ease;
}
</style>

外部引用

<template>
  <div id="app">
    <CustomSegmentedControl
      :current="currentStatus"
      :values="statusItems"
      @clickItem="onClickStatus"
    />
  </div>
</template>

<script>
import CustomSegmentedControl from "./components/CustomSegmentedControl.vue";

export default {
  components: {
    CustomSegmentedControl,
  },
  data() {
    return {
      currentStatus: 0,
      statusItems: ["草稿", "已下发", "生产中", "已完工", "已结案"],
    };
  },
  methods: {
    onClickStatus(e) {
      this.currentStatus = e.index;
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值