Werheng Zhang
2024-03-27 05030ee9843d49f864576cd39b6e7f78a880527c
提交 | 用户 | age
7db0c5 1 import {
V 2   defineComponent,
3   h,
4   computed,
5   ref,
6   getCurrentInstance,
7   onUnmounted,
8   inject,
9   Ref,
10 } from 'vue';
bab28a 11 import { on, off } from '@/utils/domUtils';
7db0c5 12 import { renderThumbStyle, BAR_MAP } from './util';
V 13
14 export default defineComponent({
15   name: 'Bar',
16   props: {
17     vertical: Boolean,
18     size: String,
19     move: Number,
20   },
21
22   setup(props) {
23     const instance = getCurrentInstance();
3576d0 24     const thumb = ref();
7db0c5 25     const wrap = inject('scroll-bar-wrap', {} as Ref<Nullable<HTMLElement>>) as any;
V 26     const bar = computed(() => {
27       return BAR_MAP[props.vertical ? 'vertical' : 'horizontal'];
28     });
a98835 29     const barStore = ref<Recordable>({});
3576d0 30     const cursorDown = ref();
05030e 31
WZ 32     const mouseMoveDocumentHandler = (e: any) => {
33       if (cursorDown.value === false) {
34         return;
35       }
36       const prevPage = barStore.value[bar.value.axis];
37
38       if (!prevPage) {
39         return;
40       }
41
42       const offset =
43         (instance?.vnode.el?.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) *
44         -1;
45       const thumbClickPosition = thumb.value[bar.value.offset] - prevPage;
46       const thumbPositionPercentage =
47         ((offset - thumbClickPosition) * 100) / instance?.vnode.el?.[bar.value.offset];
48       wrap.value[bar.value.scroll] =
49         (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
50     };
51
52     const startDrag = (e: any) => {
53       e.stopImmediatePropagation();
54       cursorDown.value = true;
55       on(document, 'mousemove', mouseMoveDocumentHandler);
56       on(document, 'mouseup', mouseUpDocumentHandler);
57       document.onselectstart = () => false;
58     };
59
7db0c5 60     const clickThumbHandler = (e: any) => {
V 61       // prevent click event of right button
62       if (e.ctrlKey || e.button === 2) {
63         return;
64       }
a96cb2 65       window.getSelection()?.removeAllRanges();
7db0c5 66       startDrag(e);
V 67       barStore.value[bar.value.axis] =
68         e.currentTarget[bar.value.offset] -
69         (e[bar.value.client] - e.currentTarget.getBoundingClientRect()[bar.value.direction]);
70     };
71
72     const clickTrackHandler = (e: any) => {
73       const offset = Math.abs(
56a966 74         e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client],
7db0c5 75       );
V 76       const thumbHalf = thumb.value[bar.value.offset] / 2;
77       const thumbPositionPercentage =
78         ((offset - thumbHalf) * 100) / instance?.vnode.el?.[bar.value.offset];
79
80       wrap.value[bar.value.scroll] =
81         (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
82     };
83
84     function mouseUpDocumentHandler() {
85       cursorDown.value = false;
86       barStore.value[bar.value.axis] = 0;
87       off(document, 'mousemove', mouseMoveDocumentHandler);
88       document.onselectstart = null;
89     }
90
91     onUnmounted(() => {
92       off(document, 'mouseup', mouseUpDocumentHandler);
93     });
94
95     return () =>
96       h(
97         'div',
98         {
99           class: ['scrollbar__bar', 'is-' + bar.value.key],
100           onMousedown: clickTrackHandler,
101         },
102         h('div', {
103           ref: thumb,
104           class: 'scrollbar__thumb',
105           onMousedown: clickThumbHandler,
106           style: renderThumbStyle({
107             size: props.size,
108             move: props.move,
109             bar: bar.value,
110           }),
56a966 111         }),
7db0c5 112       );
V 113   },
114 });