import {
|
defineComponent,
|
h,
|
computed,
|
ref,
|
getCurrentInstance,
|
onUnmounted,
|
inject,
|
Ref,
|
} from 'vue';
|
import { on, off } from '@/utils/domUtils';
|
import { renderThumbStyle, BAR_MAP } from './util';
|
|
export default defineComponent({
|
name: 'Bar',
|
props: {
|
vertical: Boolean,
|
size: String,
|
move: Number,
|
},
|
|
setup(props) {
|
const instance = getCurrentInstance();
|
const thumb = ref();
|
const wrap = inject('scroll-bar-wrap', {} as Ref<Nullable<HTMLElement>>) as any;
|
const bar = computed(() => {
|
return BAR_MAP[props.vertical ? 'vertical' : 'horizontal'];
|
});
|
const barStore = ref<Recordable>({});
|
const cursorDown = ref();
|
|
const mouseMoveDocumentHandler = (e: any) => {
|
if (cursorDown.value === false) {
|
return;
|
}
|
const prevPage = barStore.value[bar.value.axis];
|
|
if (!prevPage) {
|
return;
|
}
|
|
const offset =
|
(instance?.vnode.el?.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) *
|
-1;
|
const thumbClickPosition = thumb.value[bar.value.offset] - prevPage;
|
const thumbPositionPercentage =
|
((offset - thumbClickPosition) * 100) / instance?.vnode.el?.[bar.value.offset];
|
wrap.value[bar.value.scroll] =
|
(thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
|
};
|
|
const startDrag = (e: any) => {
|
e.stopImmediatePropagation();
|
cursorDown.value = true;
|
on(document, 'mousemove', mouseMoveDocumentHandler);
|
on(document, 'mouseup', mouseUpDocumentHandler);
|
document.onselectstart = () => false;
|
};
|
|
const clickThumbHandler = (e: any) => {
|
// prevent click event of right button
|
if (e.ctrlKey || e.button === 2) {
|
return;
|
}
|
window.getSelection()?.removeAllRanges();
|
startDrag(e);
|
barStore.value[bar.value.axis] =
|
e.currentTarget[bar.value.offset] -
|
(e[bar.value.client] - e.currentTarget.getBoundingClientRect()[bar.value.direction]);
|
};
|
|
const clickTrackHandler = (e: any) => {
|
const offset = Math.abs(
|
e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client],
|
);
|
const thumbHalf = thumb.value[bar.value.offset] / 2;
|
const thumbPositionPercentage =
|
((offset - thumbHalf) * 100) / instance?.vnode.el?.[bar.value.offset];
|
|
wrap.value[bar.value.scroll] =
|
(thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
|
};
|
|
function mouseUpDocumentHandler() {
|
cursorDown.value = false;
|
barStore.value[bar.value.axis] = 0;
|
off(document, 'mousemove', mouseMoveDocumentHandler);
|
document.onselectstart = null;
|
}
|
|
onUnmounted(() => {
|
off(document, 'mouseup', mouseUpDocumentHandler);
|
});
|
|
return () =>
|
h(
|
'div',
|
{
|
class: ['scrollbar__bar', 'is-' + bar.value.key],
|
onMousedown: clickTrackHandler,
|
},
|
h('div', {
|
ref: thumb,
|
class: 'scrollbar__thumb',
|
onMousedown: clickThumbHandler,
|
style: renderThumbStyle({
|
size: props.size,
|
move: props.move,
|
bar: bar.value,
|
}),
|
}),
|
);
|
},
|
});
|