Vue3 滚动盒子组件,scroll,overflow-y:scroll

在这里插入图片描述

<template>
  <div
    class="ui-scroll scrollbox"
    ref="box"
    @mousewheel.stop.prevent="handleMouseWheel"
    @mouseenter="handleMouseEnter"
    @mouseleave="handleMouseLeave"
    :style="$store.state.app.device == 'mobile' ? 'overflow:hidden scroll' : ''"
  >
    <transition name="fade">
      <div
        :class="['scrollbar', { force: force }]"
        ref="bar"
        v-show="show"
        :style="{ height: barHeight + 'px', width: '5px' }"
        @mousedown="handleMouseDown"
      ></div>
    </transition>
    <slot></slot>
  </div>
</template>

<script setup>
import { nextTick, onMounted, defineEmits } from "vue";
const { proxy } = getCurrentInstance();

const props = defineProps({
  scrollbar: {
    type: Boolean,
    default: false,
  },
});

let btn = ref(undefined);
let box = ref(undefined); // 自定义滚动条盒子
let bar = ref(undefined); // 滚动条
let barHeight = ref(100); // 滚动条高度
let ratio = ref(1); // 滚动条偏移率
let force = ref(false); // 滚动条是否被鼠标光标按住
let hover = ref(false); // 鼠标光标是否悬停在盒子上
let show = ref(false); // 是否显示滚动条
const { scrollbar } = toRefs(props);

onMounted(() => {
  nextTick(() => {
    box = proxy.$refs["box"];
    bar = proxy.$refs["bar"];
    // show = proxy.$refs["scrollbar"];
    show.value = scrollbar.value;
    // 滚动条全局可拖动
    document.addEventListener("mouseup", handleMouseUp);
    document.addEventListener("mousemove", handleMouseMove);
  });
});

/**
 * 鼠标滚轮事件
 * @param {object} e 事件
 */
function handleMouseWheel(e) {
  box.scrollTop -= e.wheelDelta / 4;
  bar.style.transform =
    "translateY(" + (box.scrollTop + box.scrollTop / ratio.value) + "px)";
}
/**
 * 鼠标按下
 * @param {object} e 事件
 */
function handleMouseDown(e) {
  if (e.target === bar) {
    box.prevY = e.pageY;
    force.value = true;
  }
}
/**
 * 鼠标按键释放
 */
function handleMouseUp() {
  force.value = false;
  box.prevY = null;
  if (!hover.value) {
    show.value = false;
  }
}
/**
 * 鼠标移动
 * @param {object} e 事件
 */
function handleMouseMove(e) {
  if (force.value) {
    // 阻止默认选中事件(IE下无效)
    e.preventDefault();
    box.scrollTop += (e.pageY - box.prevY) * ratio.value;
    bar.style.transform =
      "translateY(" + (box.scrollTop + box.scrollTop / ratio.value) + "px)";
    box.prevY = e.pageY;
  }
}
/**
 * 鼠标光标进入盒子范围
 */
function handleMouseEnter() {
  hover.value = true;
  if (box.scrollHeight > box.offsetHeight) {
    // 修正进度条高度和位置(建议通过事件触发)
    barHeight.value = box.offsetHeight ** 2 / box.scrollHeight;
    ratio.value =
      (box.scrollHeight - box.offsetHeight) / (box.offsetHeight - barHeight.value);
    bar.style.transform =
      "translateY(" + (box.scrollTop + box.scrollTop / ratio.value) + "px)";
    // 显示滚动条
    nextTick(() => (show.value = true));
  }
}
/**
 * 鼠标光标离开盒子范围
 */
function handleMouseLeave() {
  hover.value = false;
  if (!force.value) {
    show.value = false;
  }
}
</script>


<style>
.ui-scroll.scrollbox {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
}

.ui-scroll.scrollbox .scrollbar {
  width: var(--scrollbar-width);
  height: 100%;
  background-color: var(--gray);
  position: absolute;
  right: 0;
  border-radius: var(--scrollbar-width) / 2;
  transition: transform 0s !important;
  border-radius: 8px;
  opacity: 0.6;
  z-index: 100;
}

.ui-scroll.scrollbox .scrollbar:hover {
  background-color: gray;
}

.ui-scroll.scrollbox .scrollbar.force {
  background-color: gray;
}

/* // Vue进入离开动画 */
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s;
}

.fade-enter,
.fade-leave-to {
  opacity: 0;
}
</style>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue Seamless Scroll 是一个 Vue.js 插件,用于实现无限滚动和表头固定的无缝滚动效果。当使用这个插件时,你可以让滚动条保持在内容区域下方,而表头始终保持在顶部,即使内容区域随着用户的滚动而无限加载。 要实现表头固定不滚动的功能,你需要按照以下步骤配置: 1. 安装和引入插件: 使用 npm 或者 yarn 安装 `vue-seamless-scroll`: ``` npm install vue-seamless-scroll // 或者 yarn add vue-seamless-scroll ``` 在你的 Vue 项目中导入并使用该插件: ```js import { SeamlessScroll } from 'vue-seamless-scroll' export default { components: { SeamlessScroll } } ``` 2. 在需要应用无缝滚动的元素上使用组件: ```html <template> <div class="scroll-container"> <table> <thead>...</thead> <seamless-scroll :data="yourData" :options="{ ... }"> <tbody> <!-- 这里是你动态加载的数据 --> </tbody> </seamless-scroll> </table> </div> </template> ``` 3. 配置选项(可选): - `:offsetTop` 设置表头固定距离顶部的距离。 - `:contentWrapperClass` 可以为内容区域添加自定义 CSS 类,以便更好地控制样式。 4. 控制表头固定: 默认情况下,表头会随着内容滚动。如果你想要固定表头,可以在 CSS 中设置表头元素(thead)的 `position` 为 `fixed`,并且调整其 `top`、`left` 和 `right` 属性使其与视口对齐。同时,记得给滚动区域设置 `overflow-y: auto` 以限制垂直滚动。 ```css thead { position: fixed; top: 0; /* 表头距离顶部的距离 */ left: 0; right: 0; overflow-x: hidden; } .scroll-container { overflow-y: auto; /* 仅允许垂直滚动 */ } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值