
<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.value = scrollbar.value;
document.addEventListener("mouseup", handleMouseUp);
document.addEventListener("mousemove", handleMouseMove);
});
});
function handleMouseWheel(e) {
box.scrollTop -= e.wheelDelta / 4;
bar.style.transform =
"translateY(" + (box.scrollTop + box.scrollTop / ratio.value) + "px)";
}
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;
}
}
function handleMouseMove(e) {
if (force.value) {
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;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>