@koi-br/ocr-web-sdk 1.0.56 → 1.0.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { g as getAugmentedNamespace, a as getDefaultExportFromCjs } from "./index-tUex1DtC.mjs";
1
+ import { g as getAugmentedNamespace, a as getDefaultExportFromCjs } from "./index--nfCgExV.mjs";
2
2
  function _mergeNamespaces(U, W) {
3
3
  for (var Z = 0; Z < W.length; Z++) {
4
4
  const s0 = W[Z];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koi-br/ocr-web-sdk",
3
- "version": "1.0.56",
3
+ "version": "1.0.57",
4
4
  "description": "一个支持多种Office文件格式预览的Vue3组件SDK,包括PDF、Word、Excel、图片、OFD、TIF等格式",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
@@ -105,6 +105,7 @@
105
105
  <div
106
106
  ref="containerRef"
107
107
  class="image-container"
108
+ :class="{ 'hide-horizontal-scroll': shouldHideHorizontalScroll }"
108
109
  @mousedown="startPan"
109
110
  @mousemove="pan"
110
111
  @mouseup="handleMouseUp"
@@ -134,7 +135,7 @@
134
135
  class="image-wrapper"
135
136
  :style="{
136
137
  transform: `translate(${position.x}px, ${position.y}px) rotate(${rotation}deg) scale(${scale})`,
137
- transformOrigin: transformOrigin,
138
+ transformOrigin: 'top center',
138
139
  }"
139
140
  >
140
141
  <img
@@ -488,7 +489,14 @@ const lastPosition = ref({ x: 0, y: 0 });
488
489
  const initialAutoFitScale = ref<number | null>(null); // 记录初始自适应缩放比例
489
490
  const isCalculatingAutoFit = ref(false); // 标记是否正在计算自适应宽度(显示 loading)
490
491
  const isImageReady = ref(false); // 标记图片是否已准备好显示(自适应宽度计算完成)
491
- const transformOrigin = ref('top center'); // 缩放中心点,动态调整以实现智能缩放
492
+
493
+ // 自适应宽度“贴合宽度”时隐藏横向滚动条(避免 transform 带来的 1px 溢出触发横向滚动条)
494
+ // 仅在 scale <= initialAutoFitScale 的阶段生效,不影响用户放大后的横向滚动/拖拽查看逻辑
495
+ const shouldHideHorizontalScroll = computed(() => {
496
+ if (!props.autoFitWidth) return false;
497
+ if (initialAutoFitScale.value === null) return false;
498
+ return scale.value <= initialAutoFitScale.value + 0.001;
499
+ });
492
500
 
493
501
  // 监听图片URL变化,当有新图片时立即隐藏(等待自适应宽度计算)
494
502
  watch(
@@ -651,7 +659,19 @@ const getPageBlocksData = (pageNo: number) => {
651
659
 
652
660
  // 计算指定页面缩放后的尺寸(考虑旋转)
653
661
  const getPageScaledSize = (pageNo: number) => {
654
- const pageSize = imageSizes.get(pageNo);
662
+ // 某些情况下(尤其是多页最后一页)图片尺寸可能还没写入 imageSizes
663
+ // 此时如果返回 0,会导致 page 容器走 "auto" 高度(未缩放高度),从而出现底部留白。
664
+ // 在自适应宽度模式下,兜底使用第一页尺寸作为基准,保证容器高度按 scale 计算。
665
+ let pageSize = imageSizes.get(pageNo);
666
+ if (
667
+ (!pageSize || pageSize.width === 0 || pageSize.height === 0) &&
668
+ props.autoFitWidth
669
+ ) {
670
+ const firstPageSize = imageSizes.get(1);
671
+ if (firstPageSize && firstPageSize.width > 0 && firstPageSize.height > 0) {
672
+ pageSize = firstPageSize;
673
+ }
674
+ }
655
675
  if (!pageSize || pageSize.width === 0 || pageSize.height === 0) {
656
676
  return { width: 0, height: 0 };
657
677
  }
@@ -697,36 +717,30 @@ const zoom = (delta, isWheel = false) => {
697
717
  const oldScale = scale.value;
698
718
  const newScale = scale.value + delta * step;
699
719
 
700
- // 计算新的缩放比例
701
- let finalScale = newScale;
720
+ // 更新缩放比例
702
721
  if (newScale <= props.minScale) {
703
- finalScale = props.minScale;
722
+ scale.value = props.minScale;
704
723
  } else if (newScale >= props.maxScale) {
705
- finalScale = props.maxScale;
724
+ scale.value = props.maxScale;
725
+ } else {
726
+ scale.value = newScale;
706
727
  }
707
728
 
708
- // 更新缩放比例
709
- scale.value = finalScale;
710
-
711
- // 缩放后调整位置和缩放中心点
729
+ // 缩放后调整位置,确保图片不会超出容器
712
730
  // 使用 nextTick 确保 DOM 已更新
713
731
  nextTick(() => {
714
- if (containerRef.value) {
715
- if (finalScale > oldScale) {
716
- // 放大时,确保图片左侧不会超出容器
717
- adjustPositionAfterZoom();
718
- } else if (finalScale < oldScale) {
719
- // 缩小时,智能调整缩放中心点和位置
720
- adjustPositionAfterZoomOut();
721
- }
722
- }
732
+ adjustPositionAfterZoom(oldScale, scale.value);
723
733
  });
724
734
  };
725
735
 
726
736
  /**
727
- * 放大后调整位置,确保图片左侧不会超出容器
737
+ * 缩放后调整位置
738
+ * 根据缩放前后的比例,智能调整图片位置,确保:
739
+ * 1. 图片不会超出容器顶部和左侧
740
+ * 2. 在自适应宽度范围内时,保持居中显示
741
+ * 3. 超过自适应宽度时,保持左侧对齐,向右向下扩展/向左向上收缩
728
742
  */
729
- const adjustPositionAfterZoom = () => {
743
+ const adjustPositionAfterZoom = (oldScale: number, newScale: number) => {
730
744
  if (!containerRef.value) return;
731
745
 
732
746
  const container = containerRef.value;
@@ -740,91 +754,43 @@ const adjustPositionAfterZoom = () => {
740
754
  // 计算缩放后的图片宽度(考虑旋转)
741
755
  const normalizedRotation = ((rotation.value % 360) + 360) % 360;
742
756
  const isRotated = normalizedRotation === 90 || normalizedRotation === 270;
743
- const scaledWidth = isRotated
744
- ? currentPageSize.height * scale.value
745
- : currentPageSize.width * scale.value;
757
+ const imageBaseWidth = isRotated ? currentPageSize.height : currentPageSize.width;
758
+ const newScaledWidth = imageBaseWidth * newScale;
759
+ const oldScaledWidth = imageBaseWidth * oldScale;
746
760
 
747
- // 如果图片宽度小于等于容器宽度,不需要调整
748
- if (scaledWidth <= containerWidth) {
749
- return;
750
- }
761
+ // 判断是否超过自适应宽度
762
+ const isOverAutoFitWidth = props.autoFitWidth && initialAutoFitScale.value !== null
763
+ ? newScale > initialAutoFitScale.value
764
+ : newScaledWidth > containerWidth;
751
765
 
752
- // 由于 transformOrigin 是 'top center',缩放时图片从顶部中心扩展
753
- // 图片在容器中默认居中(因为 image-wrapper-container 设置了 align-items: center)
754
- // 图片左侧距离容器左侧的距离 = (容器宽度 - 图片宽度) / 2 + position.x
755
- const imageLeftOffset = (containerWidth - scaledWidth) / 2 + position.value.x;
756
-
757
- // 如果图片左侧超出容器左侧(imageLeftOffset < 0),需要调整
758
- if (imageLeftOffset < 0) {
759
- // 调整 position.x,使图片左侧对齐容器左侧
760
- // 目标:imageLeftOffset = 0
761
- // 即:(containerWidth - scaledWidth) / 2 + position.x = 0
762
- // 所以:position.x = -(containerWidth - scaledWidth) / 2
763
- position.value = {
764
- ...position.value,
765
- x: -(containerWidth - scaledWidth) / 2,
766
- };
766
+ if (isOverAutoFitWidth) {
767
+ // 超过自适应宽度:强制左侧对齐,向右扩展/向左收缩
768
+ // 直接计算并设置左侧对齐的位置,确保不会有左侧空白
769
+
770
+ // 由于图片在容器中默认居中(align-items: center)
771
+ // 图片左侧位置 = (容器宽度 - 图片宽度) / 2 + position.x
772
+ // 要使左侧对齐容器左侧(左侧位置 = 0):
773
+ // 0 = (containerWidth - newScaledWidth) / 2 + position.x
774
+ // position.x = -(containerWidth - newScaledWidth) / 2
767
775
 
768
- // 确保容器的滚动位置为 0,使图片左侧可见
769
- // 使用 requestAnimationFrame 确保在浏览器渲染后执行
770
- requestAnimationFrame(() => {
771
- if (containerRef.value) {
772
- containerRef.value.scrollLeft = 0;
773
- }
774
- });
775
- }
776
- };
777
-
778
- /**
779
- * 缩小后调整位置,确保图片左侧不会超出容器
780
- * 不改变缩放中心点,只调整位置
781
- */
782
- const adjustPositionAfterZoomOut = () => {
783
- if (!containerRef.value) return;
784
-
785
- const container = containerRef.value;
786
- const containerRect = container.getBoundingClientRect();
787
- const containerWidth = containerRect.width;
788
-
789
- // 获取当前页的图片尺寸
790
- const currentPageSize = imageSizes.get(currentPage.value);
791
- if (!currentPageSize || currentPageSize.width === 0) return;
792
-
793
- // 计算缩放后的图片宽度(考虑旋转)
794
- const normalizedRotation = ((rotation.value % 360) + 360) % 360;
795
- const isRotated = normalizedRotation === 90 || normalizedRotation === 270;
796
- const scaledWidth = isRotated
797
- ? currentPageSize.height * scale.value
798
- : currentPageSize.width * scale.value;
799
-
800
- // 如果图片宽度小于等于容器宽度,不需要调整
801
- if (scaledWidth <= containerWidth) {
802
- return;
803
- }
804
-
805
- // 由于 transformOrigin 是 'top center',缩放时图片从顶部中心扩展
806
- // 图片在容器中默认居中(因为 image-wrapper-container 设置了 align-items: center)
807
- // 图片左侧距离容器左侧的距离 = (容器宽度 - 图片宽度) / 2 + position.x
808
- const imageLeftOffset = (containerWidth - scaledWidth) / 2 + position.value.x;
809
-
810
- // 如果图片左侧超出容器左侧(imageLeftOffset < 0),需要调整
811
- if (imageLeftOffset < 0) {
812
- // 调整 position.x,使图片左侧对齐容器左侧
813
- // 目标:imageLeftOffset = 0
814
- // 即:(containerWidth - scaledWidth) / 2 + position.x = 0
815
- // 所以:position.x = -(containerWidth - scaledWidth) / 2
816
776
  position.value = {
817
- ...position.value,
818
- x: -(containerWidth - scaledWidth) / 2,
777
+ x: -(containerWidth - newScaledWidth) / 2,
778
+ y: Math.max(0, position.value.y), // 确保顶部不超出
819
779
  };
820
780
 
821
- // 确保容器的滚动位置为 0,使图片左侧可见
822
- // 使用 requestAnimationFrame 确保在浏览器渲染后执行
781
+ // 确保容器滚动位置正确,使图片左上角可见
823
782
  requestAnimationFrame(() => {
824
783
  if (containerRef.value) {
825
784
  containerRef.value.scrollLeft = 0;
785
+ if (position.value.y === 0) {
786
+ containerRef.value.scrollTop = 0;
787
+ }
826
788
  }
827
789
  });
790
+ } else {
791
+ // 在自适应宽度范围内:保持居中显示,不调整位置
792
+ // position 保持为 { x: 0, y: 0 },图片会自动居中
793
+ // 这里不需要做任何调整,让原有的居中逻辑生效即可
828
794
  }
829
795
  };
830
796
 
@@ -1130,7 +1096,6 @@ const reset = () => {
1130
1096
  }
1131
1097
 
1132
1098
  position.value = { x: 0, y: 0 };
1133
- transformOrigin.value = 'top center'; // 重置缩放中心点为默认值
1134
1099
 
1135
1100
  // 重置文本选择状态和批注状态
1136
1101
  showAnnotationPopup.value = false;
@@ -1180,10 +1145,9 @@ const calculateAutoFitScale = () => {
1180
1145
  return 1;
1181
1146
  }
1182
1147
 
1183
- const containerRect = containerRef.value.getBoundingClientRect();
1184
- // 使用容器的完整宽度,但预留足够空间避免因浏览器渲染误差导致横向滚动条
1185
- // 预留 4px 以确保不会因为任何渲染误差导致滚动条
1186
- const containerWidth = containerRect.width - 4;
1148
+ // 使用容器可用内容宽度(clientWidth 不包含滚动条),避免因为纵向滚动条/小数像素导致横向滚动条
1149
+ // 再额外预留 1px,防止浏览器渲染/缩放的舍入误差触发横向滚动条
1150
+ const containerWidth = containerRef.value.clientWidth - 1;
1187
1151
 
1188
1152
  if (containerWidth <= 0) {
1189
1153
  console.log(
@@ -1207,7 +1171,7 @@ const calculateAutoFitScale = () => {
1207
1171
  return 1;
1208
1172
  }
1209
1173
 
1210
- // 计算缩放比例,使图片宽度完全适应容器宽度
1174
+ // 计算缩放比例,使图片宽度适应容器宽度(带 1px 安全余量)
1211
1175
  const calculatedScale = containerWidth / imageWidth;
1212
1176
  const finalScale = Math.max(
1213
1177
  props.minScale,
@@ -3098,6 +3062,12 @@ defineExpose({
3098
3062
  overflow: auto;
3099
3063
  }
3100
3064
 
3065
+ // 自适应宽度贴合阶段:隐藏横向滚动条(保留纵向滚动)
3066
+ .image-container.hide-horizontal-scroll {
3067
+ overflow-x: hidden;
3068
+ overflow-y: auto;
3069
+ }
3070
+
3101
3071
  // 自适应宽度计算 Loading
3102
3072
  .auto-fit-loading {
3103
3073
  position: absolute;