@douyinfe/semi-foundation 2.49.0 → 2.50.0-alpha.0

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,6 +1,8 @@
1
1
  import BaseFoundation, { DefaultAdapter } from "../base/foundation";
2
2
 
3
- export interface PreviewFooterAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S>{}
3
+ export interface PreviewFooterAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
4
+ setStartMouseOffset: (time: number) => void
5
+ }
4
6
 
5
7
  export default class PreviewFooterFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<PreviewFooterAdapter<P, S>, P, S> {
6
8
 
@@ -22,6 +24,7 @@ export default class PreviewFooterFoundation<P = Record<string, any>, S = Record
22
24
  } else {
23
25
  onZoomOut(Number((value / 100).toFixed(2)));
24
26
  }
27
+ this._adapter.setStartMouseOffset(value);
25
28
  };
26
29
 
27
30
  handleRatioClick = (): void => {
@@ -1,8 +1,16 @@
1
1
  import BaseFoundation, { DefaultAdapter } from "../base/foundation";
2
+ import { handlePrevent } from "../utils/a11y";
3
+ import { throttle, isUndefined } from "lodash";
2
4
 
3
5
  export interface PreviewImageAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
6
+ getOriginImageSize: () => { originImageWidth: number; originImageHeight: number };
7
+ setOriginImageSize: (size: { originImageWidth: number; originImageHeight: number }) => void;
4
8
  getContainer: () => HTMLDivElement;
5
9
  getImage: () => HTMLImageElement;
10
+ getMouseMove: () => boolean;
11
+ setStartMouseMove: (move: boolean) => void;
12
+ getMouseOffset: () => { x: number; y: number };
13
+ setStartMouseOffset: (offset: { x: number; y: number }) => void;
6
14
  setLoading: (loading: boolean) => void;
7
15
  setImageCursor: (canDrag: boolean) => void
8
16
  }
@@ -38,10 +46,6 @@ export default class PreviewImageFoundation<P = Record<string, any>, S = Record<
38
46
  super({ ...adapter });
39
47
  }
40
48
 
41
- startMouseOffset = { x: 0, y: 0 };
42
- originImageWidth = null;
43
- originImageHeight = null;
44
-
45
49
  _isImageVertical = (): boolean => this.getProp("rotation") % 180 !== 0;
46
50
 
47
51
  _getImageBounds = (): DOMRect => {
@@ -73,16 +77,21 @@ export default class PreviewImageFoundation<P = Record<string, any>, S = Record<
73
77
  }
74
78
 
75
79
  handleWindowResize = (): void => {
76
- if (this.originImageWidth && this.originImageHeight) {
77
- this.handleResizeImage();
80
+ const { ratio, setRatio } = this.getProps();
81
+ const { originImageWidth, originImageHeight } = this._adapter.getOriginImageSize();
82
+ if (originImageWidth && originImageHeight) {
83
+ if (ratio !== "adaptation") {
84
+ setRatio("adaptation");
85
+ } else {
86
+ this.handleResizeImage();
87
+ }
78
88
  }
79
89
  };
80
90
 
81
91
  handleLoad = (e: any): void => {
82
92
  if (e.target) {
83
- const { naturalWidth: w, naturalHeight: h } = e.target as any;
84
- this.originImageHeight = h;
85
- this.originImageWidth = w;
93
+ const { width: w, height: h } = e.target as any;
94
+ this._adapter.setOriginImageSize({ originImageWidth: w, originImageHeight: h });
86
95
  this.setState({
87
96
  loading: false,
88
97
  } as any);
@@ -102,50 +111,19 @@ export default class PreviewImageFoundation<P = Record<string, any>, S = Record<
102
111
 
103
112
  handleResizeImage = () => {
104
113
  const horizontal = !this._isImageVertical();
105
- const { currZoom } = this.getStates();
106
- const imgWidth = horizontal ? this.originImageWidth : this.originImageHeight;
107
- const imgHeight = horizontal ? this.originImageHeight : this.originImageWidth;
108
- const { onZoom, setRatio, ratio } = this.getProps();
114
+ const { originImageWidth, originImageHeight } = this._adapter.getOriginImageSize();
115
+ const imgWidth = horizontal ? originImageWidth : originImageHeight;
116
+ const imgHeight = horizontal ? originImageHeight : originImageWidth;
117
+ const { onZoom } = this.getProps();
109
118
  const containerDOM = this._adapter.getContainer();
110
119
  if (containerDOM) {
111
120
  const { width: containerWidth, height: containerHeight } = this._getContainerBounds();
112
121
  const reservedWidth = containerWidth - 80;
113
122
  const reservedHeight = containerHeight - 80;
114
- let _zoom = 1;
115
- if (imgWidth > reservedWidth || imgHeight > reservedHeight) {
116
- _zoom = Number(
117
- Math.min(reservedWidth / imgWidth, reservedHeight / imgHeight).toFixed(2)
118
- );
119
- }
120
- if (currZoom === _zoom) {
121
- this.calculatePreviewImage(_zoom, null);
122
- } else {
123
- onZoom(_zoom);
124
- }
125
- }
126
- }
127
-
128
- handleRatioChange = () => {
129
- if (this.originImageWidth && this.originImageHeight) {
130
- const { currZoom } = this.getStates();
131
- const { ratio, onZoom } = this.getProps();
132
- let _zoom: number;
133
- if (ratio === 'adaptation') {
134
- const horizontal = !this._isImageVertical();
135
- const imgWidth = horizontal ? this.originImageWidth : this.originImageHeight;
136
- const imgHeight = horizontal ? this.originImageHeight : this.originImageWidth;
137
- const { width: containerWidth, height: containerHeight } = this._getContainerBounds();
138
- const reservedWidth = containerWidth - 80;
139
- const reservedHeight = containerHeight - 80;
140
- _zoom = Number(
141
- Math.min(reservedWidth / imgWidth, reservedHeight / imgHeight).toFixed(2)
142
- );
143
- } else {
144
- _zoom = 1;
145
- }
146
- if (currZoom !== _zoom) {
147
- onZoom(_zoom);
148
- }
123
+ const _zoom = Number(
124
+ Math.min(reservedWidth / imgWidth, reservedHeight / imgHeight).toFixed(2)
125
+ );
126
+ onZoom(_zoom);
149
127
  }
150
128
  }
151
129
 
@@ -160,6 +138,33 @@ export default class PreviewImageFoundation<P = Record<string, any>, S = Record<
160
138
  }
161
139
  };
162
140
 
141
+ // e: WheelEvent<HTMLImageElement>
142
+ handleWheel = (e: any) => {
143
+ this.onWheel(e);
144
+ handlePrevent(e);
145
+ }
146
+
147
+ // e: WheelEvent<HTMLImageElement>
148
+ onWheel = throttle((e: any): void => {
149
+ const { onZoom, zoomStep, maxZoom, minZoom } = this.getProps();
150
+ const { currZoom } = this.getStates();
151
+ let _zoom: number;
152
+ if (e.deltaY < 0) {
153
+ /* zoom in */
154
+ if (currZoom + zoomStep <= maxZoom) {
155
+ _zoom = Number((currZoom + zoomStep).toFixed(2));
156
+ }
157
+ } else if (e.deltaY > 0) {
158
+ /* zoom out */
159
+ if (currZoom - zoomStep >= minZoom) {
160
+ _zoom = Number((currZoom - zoomStep).toFixed(2));
161
+ }
162
+ }
163
+ if (!isUndefined(_zoom)) {
164
+ onZoom(_zoom);
165
+ }
166
+ }, 50);
167
+
163
168
  calcCanDragDirection = (): DragDirection => {
164
169
  const { width, height } = this.getStates();
165
170
  const { rotation } = this.getProps();
@@ -176,13 +181,14 @@ export default class PreviewImageFoundation<P = Record<string, any>, S = Record<
176
181
  };
177
182
  };
178
183
 
179
- calculatePreviewImage = (newZoom: number, e: any): void => {
184
+ handleZoomChange = (newZoom: number, e: any): void => {
180
185
  const imageDOM = this._adapter.getImage();
186
+ const { originImageWidth, originImageHeight } = this._adapter.getOriginImageSize();
181
187
  const { canDragVertical, canDragHorizontal } = this.calcCanDragDirection();
182
188
  const canDrag = canDragVertical || canDragHorizontal;
183
189
  const { width: containerWidth, height: containerHeight } = this._getContainerBounds();
184
- const newWidth = Math.floor(this.originImageWidth * newZoom);
185
- const newHeight = Math.floor(this.originImageHeight * newZoom);
190
+ const newWidth = Math.floor(originImageWidth * newZoom);
191
+ const newHeight = Math.floor(originImageHeight * newZoom);
186
192
 
187
193
  // debugger;
188
194
  let _offset;
@@ -236,15 +242,15 @@ export default class PreviewImageFoundation<P = Record<string, any>, S = Record<
236
242
 
237
243
  handleMoveImage = (e: any): void => {
238
244
  const { offset, width, height } = this.getStates();
245
+ const startMouseMove = this._adapter.getMouseMove();
246
+ const startMouseOffset = this._adapter.getMouseOffset();
239
247
  const { canDragVertical, canDragHorizontal } = this.calcCanDragDirection();
240
- // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
241
- const mouseLeftPress = e.buttons === 1;
242
- if (mouseLeftPress && (canDragVertical || canDragHorizontal)) {
248
+ if (startMouseMove && (canDragVertical || canDragHorizontal)) {
243
249
  const { clientX, clientY } = e;
244
250
  const { left: containerLeft, top: containerTop } = this._getContainerBounds();
245
251
  const { left: extremeLeft, top: extremeTop } = this.calcExtremeBounds();
246
- let newX = canDragHorizontal ? clientX - containerLeft - this.startMouseOffset.x : offset.x;
247
- let newY = canDragVertical ? clientY - containerTop - this.startMouseOffset.y : offset.y;
252
+ let newX = canDragHorizontal ? clientX - containerLeft - startMouseOffset.x : offset.x;
253
+ let newY = canDragVertical ? clientY - containerTop - startMouseOffset.y : offset.y;
248
254
  if (canDragHorizontal) {
249
255
  newX = newX > 0 ? 0 : newX < extremeLeft ? extremeLeft : newX;
250
256
  }
@@ -264,7 +270,11 @@ export default class PreviewImageFoundation<P = Record<string, any>, S = Record<
264
270
  };
265
271
 
266
272
  handleImageMouseDown = (e: any): void => {
267
- this.startMouseOffset = this._getOffset(e);
273
+ this._adapter.setStartMouseOffset(this._getOffset(e));
274
+ this._adapter.setStartMouseMove(true);
268
275
  };
269
276
 
277
+ handleImageMouseUp = (): void => {
278
+ this._adapter.setStartMouseMove(false);
279
+ };
270
280
  }
@@ -1,8 +1,6 @@
1
- import { handlePrevent } from "../utils/a11y";
2
1
  import BaseFoundation, { DefaultAdapter } from "../base/foundation";
3
2
  import KeyCode from "../utils/keyCode";
4
3
  import { getPreloadImagArr, downloadImage, isTargetEmit } from "./utils";
5
- import { isUndefined, throttle } from "lodash";
6
4
 
7
5
  export type RatioType = "adaptation" | "realSize";
8
6
  export interface PreviewInnerAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
@@ -16,10 +14,15 @@ export interface PreviewInnerAdapter<P = Record<string, any>, S = Record<string,
16
14
  notifyDownload: (src: string, index: number) => void;
17
15
  registerKeyDownListener: () => void;
18
16
  unregisterKeyDownListener: () => void;
17
+ getMouseActiveTime: () => number;
18
+ getStopTiming: () => boolean;
19
+ setStopTiming: (value: boolean) => void;
20
+ getStartMouseDown: () => {x: number; y: number};
21
+ setStartMouseDown: (x: number, y: number) => void;
22
+ setMouseActiveTime: (time: number) => void;
19
23
  disabledBodyScroll: () => void;
20
24
  enabledBodyScroll: () => void;
21
- getSetDownloadFunc: () => (src: string) => string;
22
- isValidTarget: (e: any) => boolean
25
+ getSetDownloadFunc: () => (src: string) => string
23
26
  }
24
27
 
25
28
 
@@ -31,94 +34,50 @@ export default class PreviewInnerFoundation<P = Record<string, any>, S = Record<
31
34
  super({ ...adapter });
32
35
  }
33
36
 
34
- _timer = null;
35
- _startMouseDown = { x: 0, y: 0 };
36
-
37
37
  beforeShow() {
38
38
  this._adapter.registerKeyDownListener();
39
39
  this._adapter.disabledBodyScroll();
40
- this.updateTimer();
41
40
  }
42
41
 
43
42
  afterHide() {
44
43
  this._adapter.unregisterKeyDownListener();
45
44
  this._adapter.enabledBodyScroll();
46
- this.clearTimer();
47
45
  }
48
46
 
49
47
  handleViewVisibleChange = () => {
48
+ const nowTime = new Date().getTime();
49
+ const mouseActiveTime = this._adapter.getMouseActiveTime();
50
+ const stopTiming = this._adapter.getStopTiming();
51
+ const { viewerVisibleDelay } = this.getProps();
50
52
  const { viewerVisible } = this.getStates();
51
- if (viewerVisible) {
52
- this.setState({
53
+ if (nowTime - mouseActiveTime > viewerVisibleDelay && !stopTiming) {
54
+ viewerVisible && this.setState({
53
55
  viewerVisible: false,
54
56
  } as any);
55
- this.clearTimer();
56
- }
57
- }
58
-
59
- handleMouseMove = (e) => {
60
- this._persistEvent(e);
61
- this.mouseMoveHandler(e);
62
- }
63
-
64
- mouseMoveHandler = throttle((e: any) => {
65
- const { viewerVisible } = this.getStates();
66
- const isValidTarget = this._adapter.isValidTarget(e);
67
- if (isValidTarget) {
68
- if (!viewerVisible) {
69
- this.setState({
70
- viewerVisible: true,
71
- } as any);
72
- }
73
- this.updateTimer();
74
- } else {
75
- this.clearTimer();
76
57
  }
77
- }, 50);
78
-
79
- updateTimer = () => {
80
- const { viewerVisibleDelay } = this.getProps();
81
- this.clearTimer();
82
- this._timer = setTimeout(this.handleViewVisibleChange, viewerVisibleDelay);
83
58
  }
84
59
 
85
- clearTimer = () => {
86
- if (this._timer) {
87
- clearTimeout(this._timer);
88
- this._timer = null;
60
+ handleMouseMoveEvent = (e: any, event: string) => {
61
+ const isTarget = isTargetEmit(e, STOP_CLOSE_TARGET);
62
+ if (isTarget && event === "over") {
63
+ this._adapter.setStopTiming(true);
64
+ } else if (isTarget && event === "out") {
65
+ this._adapter.setStopTiming(false);
89
66
  }
90
67
  }
91
68
 
92
- handleWheel = (e: any) => {
93
- this.onWheel(e);
94
- handlePrevent(e);
69
+ handleMouseMove = (e: any) => {
70
+ this._adapter.setMouseActiveTime(new Date().getTime());
71
+ this.setState({
72
+ viewerVisible: true,
73
+ } as any);
95
74
  }
96
75
 
97
- onWheel = (e: any): void => {
98
- const { zoomStep, maxZoom, minZoom } = this.getProps();
99
- const { zoom: currZoom } = this.getStates();
100
- let _zoom: number;
101
- if (e.deltaY < 0) {
102
- /* zoom in */
103
- if (currZoom + zoomStep <= maxZoom) {
104
- _zoom = Number((currZoom + zoomStep).toFixed(2));
105
- }
106
- } else if (e.deltaY > 0) {
107
- /* zoom out */
108
- if (currZoom - zoomStep >= minZoom) {
109
- _zoom = Number((currZoom - zoomStep).toFixed(2));
110
- }
111
- }
112
- if (!isUndefined(_zoom)) {
113
- this.handleZoomImage(_zoom);
114
- }
115
- };
116
-
117
76
  handleMouseUp = (e: any) => {
118
77
  const { maskClosable } = this.getProps();
119
78
  let couldClose = !isTargetEmit(e, NOT_CLOSE_TARGETS);
120
79
  const { clientX, clientY } = e;
121
- const { x, y } = this._startMouseDown;
80
+ const { x, y } = this._adapter.getStartMouseDown();
122
81
  // 对鼠标移动做容错处理,当 x 和 y 方向在 mouseUp 的时候移动距离都小于等于 5px 时候就可以关闭预览
123
82
  // Error-tolerant processing of mouse movement, when the movement distance in the x and y directions is less than or equal to 5px in mouseUp, the preview can be closed
124
83
  // 不做容错处理的话,直接用 clientX !== x || y !== clientY 做判断,鼠标在用户点击时候无意识的轻微移动无法关闭预览,不符合用户预期
@@ -133,7 +92,7 @@ export default class PreviewInnerFoundation<P = Record<string, any>, S = Record<
133
92
 
134
93
  handleMouseDown = (e: any) => {
135
94
  const { clientX, clientY } = e;
136
- this._startMouseDown = { x: clientX, y: clientY } ;
95
+ this._adapter.setStartMouseDown(clientX, clientY);
137
96
  }
138
97
 
139
98
  handleKeyDown = (e: any) => {
@@ -201,12 +160,10 @@ export default class PreviewInnerFoundation<P = Record<string, any>, S = Record<
201
160
 
202
161
  handleZoomImage = (newZoom: number) => {
203
162
  const { zoom } = this.getStates();
204
- if (zoom !== newZoom) {
205
- this._adapter.notifyZoom(newZoom, newZoom > zoom);
206
- this.setState({
207
- zoom: newZoom,
208
- } as any);
209
- }
163
+ this._adapter.notifyZoom(newZoom, newZoom > zoom);
164
+ this.setState({
165
+ zoom: newZoom,
166
+ } as any);
210
167
  }
211
168
 
212
169
  // 当 visible 改变之后,预览组件完成首张图片加载后,启动预加载
@@ -1,5 +1,6 @@
1
1
  import BaseFoundation, { DefaultAdapter } from "../base/foundation";
2
2
  export interface PreviewFooterAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
3
+ setStartMouseOffset: (time: number) => void;
3
4
  }
4
5
  export default class PreviewFooterFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<PreviewFooterAdapter<P, S>, P, S> {
5
6
  changeSliderValue: (type: string) => void;
@@ -35,6 +35,7 @@ class PreviewFooterFoundation extends _foundation.default {
35
35
  } else {
36
36
  onZoomOut(Number((value / 100).toFixed(2)));
37
37
  }
38
+ this._adapter.setStartMouseOffset(value);
38
39
  };
39
40
  this.handleRatioClick = () => {
40
41
  const {
@@ -1,7 +1,26 @@
1
+ /// <reference types="lodash" />
1
2
  import BaseFoundation, { DefaultAdapter } from "../base/foundation";
2
3
  export interface PreviewImageAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
4
+ getOriginImageSize: () => {
5
+ originImageWidth: number;
6
+ originImageHeight: number;
7
+ };
8
+ setOriginImageSize: (size: {
9
+ originImageWidth: number;
10
+ originImageHeight: number;
11
+ }) => void;
3
12
  getContainer: () => HTMLDivElement;
4
13
  getImage: () => HTMLImageElement;
14
+ getMouseMove: () => boolean;
15
+ setStartMouseMove: (move: boolean) => void;
16
+ getMouseOffset: () => {
17
+ x: number;
18
+ y: number;
19
+ };
20
+ setStartMouseOffset: (offset: {
21
+ x: number;
22
+ y: number;
23
+ }) => void;
5
24
  setLoading: (loading: boolean) => void;
6
25
  setImageCursor: (canDrag: boolean) => void;
7
26
  }
@@ -19,12 +38,6 @@ export interface ImageOffset {
19
38
  }
20
39
  export default class PreviewImageFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<PreviewImageAdapter<P, S>, P, S> {
21
40
  constructor(adapter: PreviewImageAdapter<P, S>);
22
- startMouseOffset: {
23
- x: number;
24
- y: number;
25
- };
26
- originImageWidth: any;
27
- originImageHeight: any;
28
41
  _isImageVertical: () => boolean;
29
42
  _getImageBounds: () => DOMRect;
30
43
  _getContainerBounds: () => DOMRect;
@@ -34,11 +47,13 @@ export default class PreviewImageFoundation<P = Record<string, any>, S = Record<
34
47
  handleLoad: (e: any) => void;
35
48
  handleError: (e: any) => void;
36
49
  handleResizeImage: () => void;
37
- handleRatioChange: () => void;
38
50
  handleRightClickImage: (e: any) => boolean;
51
+ handleWheel: (e: any) => void;
52
+ onWheel: import("lodash").DebouncedFunc<(e: any) => void>;
39
53
  calcCanDragDirection: () => DragDirection;
40
- calculatePreviewImage: (newZoom: number, e: any) => void;
54
+ handleZoomChange: (newZoom: number, e: any) => void;
41
55
  calcExtremeBounds: () => ExtremeBounds;
42
56
  handleMoveImage: (e: any) => void;
43
57
  handleImageMouseDown: (e: any) => void;
58
+ handleImageMouseUp: () => void;
44
59
  }