提交 | 用户 | 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 |
}); |