Skip to content

Commit 333998b

Browse files
authored
fix: determine if scrollbar has been totally scrolled (vbenjs#5934)
* 修复在系统屏幕缩放比例不为100%的情况下,滚动组件对是否已滚动到边界的判断可能不正确的问题
1 parent 3fb4fba commit 333998b

File tree

1 file changed

+16
-4
lines changed
  • packages/@core/ui-kit/shadcn-ui/src/components/scrollbar

1 file changed

+16
-4
lines changed

packages/@core/ui-kit/shadcn-ui/src/components/scrollbar/scrollbar.vue

+16-4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ const isAtRight = ref(false);
3939
const isAtBottom = ref(false);
4040
const isAtLeft = ref(true);
4141
42+
/**
43+
* We have to check if the scroll amount is close enough to some threshold in order to
44+
* more accurately calculate arrivedState. This is because scrollTop/scrollLeft are non-rounded
45+
* numbers, while scrollHeight/scrollWidth and clientHeight/clientWidth are rounded.
46+
* https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#determine_if_an_element_has_been_totally_scrolled
47+
*/
48+
const ARRIVED_STATE_THRESHOLD_PIXELS = 1;
49+
4250
const showShadowTop = computed(() => props.shadow && props.shadowTop);
4351
const showShadowBottom = computed(() => props.shadow && props.shadowBottom);
4452
const showShadowLeft = computed(() => props.shadow && props.shadowLeft);
@@ -60,14 +68,18 @@ function handleScroll(event: Event) {
6068
const target = event.target as HTMLElement;
6169
const scrollTop = target?.scrollTop ?? 0;
6270
const scrollLeft = target?.scrollLeft ?? 0;
63-
const offsetHeight = target?.offsetHeight ?? 0;
64-
const offsetWidth = target?.offsetWidth ?? 0;
71+
const clientHeight = target?.clientHeight ?? 0;
72+
const clientWidth = target?.clientWidth ?? 0;
6573
const scrollHeight = target?.scrollHeight ?? 0;
6674
const scrollWidth = target?.scrollWidth ?? 0;
6775
isAtTop.value = scrollTop <= 0;
6876
isAtLeft.value = scrollLeft <= 0;
69-
isAtBottom.value = scrollTop + offsetHeight >= scrollHeight;
70-
isAtRight.value = scrollLeft + offsetWidth >= scrollWidth;
77+
isAtBottom.value =
78+
Math.abs(scrollTop) + clientHeight >=
79+
scrollHeight - ARRIVED_STATE_THRESHOLD_PIXELS;
80+
isAtRight.value =
81+
Math.abs(scrollLeft) + clientWidth >=
82+
scrollWidth - ARRIVED_STATE_THRESHOLD_PIXELS;
7183
7284
emit('scrollAt', {
7385
bottom: isAtBottom.value,

0 commit comments

Comments
 (0)