bar.ts
3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import type { Ref } from 'vue'
import {
computed,
defineComponent,
getCurrentInstance,
h,
inject,
onUnmounted,
ref,
} from 'vue'
import { BAR_MAP, renderThumbStyle } from './util'
import { off, on } from '@/utils/domUtils'
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 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 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
}
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,
}),
}),
)
},
})