vue3 实现点击可左右滑动

这是一个使用Vue和TypeScript编写的组件,实现了进度条滚动效果。组件包含左右箭头,通过点击箭头实现进度条的前后滚动。当进度条达到边界时,会自动禁用相应箭头。每个进度项的宽度固定,并且根据屏幕宽度动态计算可展示的最大数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

具体代码如下

<template>
  <div>
    <div
      class="ProgressBoxTool"
      v-if="state.progressList && state.progressList.length"
    >
      <div class="processBox">
        <div
          :class="state.currentClickNumber > 0 ? 'arrow' : 'arrow arrowOpacity'"
          @click="fnPrev()"
        >
          <img :src="arrowL" alt="" />
        </div>
        <div class="fixedBox" ref="fixedBox">
          <div
            class="centerScroll"
            :style="`width:${
              state.signleWidth * state.progressList.length
            }px;transform:translate(${
              state.scrollResultWidth
            }px,0);transition:1s;`"
          >
            <div
              class="signleTab"
              v-for="(itemP, indexP) in state.progressList"
              :key="indexP + 'progress'"
            >
              <div class="leftIcon">
                <img class="pregressIcon" :src="icon" alt="" />
              </div>
              <!-- 最后一个不展示箭头 -->
              <img
                v-if="state.progressList.length > indexP + 1"
                :src="iconArrow"
                alt=""
                class="arrowSquare"
              />
            </div>
          </div>
        </div>

        <div
          :class="state.noScrollRight ? 'arrow' : 'arrow arrowOpacity'"
          @click="fnNext()"
        >
          <img :src="arrowR" alt="" />
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { reactive, ref, onMounted } from "vue";
import arrowL from "../../assets/images/arrow.png";
import arrowR from "../../assets/images/arrow.png";
import icon from "../../assets/images/icon.png";
import iconArrow from "../../assets/images/arrow.png";
const state = reactive({
  progressList: [
    { type: "1" },
    { type: "2" },
    { type: "1" },
    { type: "2" },
    { type: "1" },
    { type: "2" },
    { type: "1" },
    { type: "2" },
    { type: "1" },
    { type: "2" }
  ],
  currentProgressId: "",
  scrollResultWidth: 0, //transform滚动的距离
  signleWidth: 215, //单个流程的宽度
  activeName: 0,
  currentClickNumber: 0,
  noScrollRight: true
});
const fixedBox = ref();
const initgoRightArrow = () => {
  const currentScrollWidth = fixedBox.value.clientWidth;
  const canNumber = Math.floor(currentScrollWidth / state.signleWidth); //可以放下的个数
  //如果最后一个流程图标已经展示出来,则停止滚动
  if (state.currentClickNumber + canNumber >= state.progressList.length) {
    state.noScrollRight = false;
    return;
  }
};
onMounted(() => {
  initgoRightArrow();
});
const fnPrev = () => {
  //如果右点击的次数大于0,才可以左滚
  if (state.currentClickNumber > 0) {
    state.currentClickNumber -= 1;
    state.noScrollRight = true;
    fnScrollWidth("reduce");
  } else {
    return false;
  }
};
const fnNext = () => {
  const currentScrollWidth = fixedBox.value.clientWidth;
  const canNumber = Math.floor(currentScrollWidth / state.signleWidth); //可以放下的个数
  //如果最后一个流程图标已经展示出来,则停止滚动
  if (state.currentClickNumber + canNumber >= state.progressList.length) {
    return;
  }
  //说明放不下有滚动条
  if (state.progressList.length > canNumber) {
    state.currentClickNumber += 1;
    if (state.currentClickNumber + canNumber >= state.progressList.length) {
      state.noScrollRight = false;
    }
    fnScrollWidth("add");
  }
};
const fnScrollWidth = type => {
  let result = 0;
  if (type === "reduce") {
    result = 215;
  } else if (type === "add") {
    result = -215;
  } else {
    result = 0;
  }
  state.scrollResultWidth += result;
};
</script>

<style lang="scss" scoped>
//中间的时间发展部分
.processBox {
  display: flex;
  align-items: center;
  justify-content: space-between;
  .arrow {
    width: 60px;
    cursor: pointer;
  }
  .arrowOpacity {
    cursor: default;
    opacity: 0.4;
  }
  .fixedBox {
    flex: 1;
    overflow: hidden;
  }
  .centerScroll {
    // flex: 1;
    box-sizing: border-box;
    padding: 20px 0;
    white-space: nowrap;
    // width: calc(100% - 120px);
    // overflow-x: auto;
    .signleTab {
      width: 215px;
      position: relative;
      display: inline-block;
      .leftIcon {
        width: 150px;
        text-align: center;
        cursor: pointer;
        & > .pregressIcon {
          width: 60px;
          height: 60px;
        }
      }
      & > .arrowSquare {
        position: absolute;
        top: 25px;
        right: 0;
      }
    }
  }
}
</style>

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值