1
0
Эх сурвалжийг харах

fix: determine if scrollbar has been totally scrolled (#5934)

* 修复在系统屏幕缩放比例不为100%的情况下,滚动组件对是否已滚动到边界的判断可能不正确的问题
wyc001122 3 долоо хоног өмнө
parent
commit
333998b518

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

@@ -39,6 +39,14 @@ const isAtRight = ref(false);
 const isAtBottom = ref(false);
 const isAtLeft = ref(true);
 
+/**
+ * We have to check if the scroll amount is close enough to some threshold in order to
+ * more accurately calculate arrivedState. This is because scrollTop/scrollLeft are non-rounded
+ * numbers, while scrollHeight/scrollWidth and clientHeight/clientWidth are rounded.
+ * https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#determine_if_an_element_has_been_totally_scrolled
+ */
+const ARRIVED_STATE_THRESHOLD_PIXELS = 1;
+
 const showShadowTop = computed(() => props.shadow && props.shadowTop);
 const showShadowBottom = computed(() => props.shadow && props.shadowBottom);
 const showShadowLeft = computed(() => props.shadow && props.shadowLeft);
@@ -60,14 +68,18 @@ function handleScroll(event: Event) {
   const target = event.target as HTMLElement;
   const scrollTop = target?.scrollTop ?? 0;
   const scrollLeft = target?.scrollLeft ?? 0;
-  const offsetHeight = target?.offsetHeight ?? 0;
-  const offsetWidth = target?.offsetWidth ?? 0;
+  const clientHeight = target?.clientHeight ?? 0;
+  const clientWidth = target?.clientWidth ?? 0;
   const scrollHeight = target?.scrollHeight ?? 0;
   const scrollWidth = target?.scrollWidth ?? 0;
   isAtTop.value = scrollTop <= 0;
   isAtLeft.value = scrollLeft <= 0;
-  isAtBottom.value = scrollTop + offsetHeight >= scrollHeight;
-  isAtRight.value = scrollLeft + offsetWidth >= scrollWidth;
+  isAtBottom.value =
+    Math.abs(scrollTop) + clientHeight >=
+    scrollHeight - ARRIVED_STATE_THRESHOLD_PIXELS;
+  isAtRight.value =
+    Math.abs(scrollLeft) + clientWidth >=
+    scrollWidth - ARRIVED_STATE_THRESHOLD_PIXELS;
 
   emit('scrollAt', {
     bottom: isAtBottom.value,