@ohkit/draggable-box 0.0.1 → 0.0.2
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.
- package/dist/index.es.js +1 -1
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +1 -1
- package/dist/index.modern.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/types/index.d.ts +3 -11
- package/dist/types/utils.d.ts +19 -4
- package/package.json +2 -2
- package/src/index.tsx +80 -95
- package/src/utils.ts +54 -23
package/src/index.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
classNames as cx,
|
|
5
5
|
} from "@ohkit/prefix-classname";
|
|
6
6
|
import {addEventListener, addClass} from '@ohkit/dom-helper';
|
|
7
|
-
import {findFixedPositionParent, findAbsolutePositionParent, getScaleRatio} from './utils';
|
|
7
|
+
import {findFixedPositionParent, findAbsolutePositionParent, getScaleRatio, clamp} from './utils';
|
|
8
8
|
import {ValidPlacement} from './constants';
|
|
9
9
|
import {DraggableBoxProps, DraggableBoxState} from './type';
|
|
10
10
|
|
|
@@ -38,62 +38,65 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
getOtherXKey(xKey: 'left' | 'right') {
|
|
46
|
-
return xKey === 'left' ? 'right' : 'left';
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// TODO:
|
|
50
|
-
updatePosition(yKey: 'top' | 'bottom', xKey: 'left' | 'right') {
|
|
51
|
-
const oYKey = this.getOtherYKey(yKey);
|
|
52
|
-
const oXKey = this.getOtherXKey(xKey);
|
|
53
|
-
this.setState({
|
|
54
|
-
[oYKey]: this.dragPositionRang.height - (this.state[yKey] || 0),
|
|
55
|
-
[oXKey]: this.dragPositionRang.width - (this.state[xKey] || 0),
|
|
56
|
-
});
|
|
57
|
-
}
|
|
41
|
+
private prePositionMode: DraggableBoxProps['positionMode'];
|
|
42
|
+
private preDraggerRef: HTMLElement | null = null;
|
|
43
|
+
private container: HTMLElement | null = null;
|
|
58
44
|
/**
|
|
59
45
|
* 获取定位容器
|
|
60
46
|
* 根据 positionMode 返回对应的定位父元素
|
|
61
47
|
*/
|
|
62
|
-
private getContainer()
|
|
48
|
+
private getContainer(useCache = true) {
|
|
63
49
|
const { positionMode = 'fixed' } = this.props;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
50
|
+
if (!this.container || !useCache || this.prePositionMode !== positionMode || this.preDraggerRef !== this.draggerRef) {
|
|
51
|
+
this.prePositionMode = positionMode;
|
|
52
|
+
this.preDraggerRef = this.draggerRef;
|
|
53
|
+
this.container = positionMode === 'fixed'
|
|
54
|
+
? findFixedPositionParent(this.draggerRef)
|
|
55
|
+
: findAbsolutePositionParent(this.draggerRef);
|
|
56
|
+
}
|
|
57
|
+
return this.container;
|
|
67
58
|
}
|
|
68
59
|
|
|
69
60
|
/**
|
|
70
61
|
* 获取容器的尺寸和位置信息
|
|
71
62
|
*/
|
|
72
63
|
private getContainerRect() {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
const container = this.getContainer(false);
|
|
65
|
+
if (!container) {
|
|
66
|
+
return {
|
|
67
|
+
width: window.innerWidth,
|
|
68
|
+
height: window.innerHeight,
|
|
69
|
+
left: 0,
|
|
70
|
+
top: 0,
|
|
71
|
+
scrollLeft: 0,
|
|
72
|
+
scrollTop: 0,
|
|
73
|
+
scrollerScrollLeft: 0,
|
|
74
|
+
scrollerScrollTop: 0,
|
|
75
|
+
borderLeftWidth: 0,
|
|
76
|
+
borderTopWidth: 0
|
|
77
|
+
};
|
|
78
|
+
}
|
|
76
79
|
const containerRect = container.getBoundingClientRect();
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
scrollerScrollTop: isFixed && isRoot ? 0 : rootScrollingElement.scrollTop
|
|
88
|
-
};
|
|
89
|
-
}
|
|
80
|
+
|
|
81
|
+
// 获取容器的border宽度(仅 top, left 对坐标计算有影响)
|
|
82
|
+
const containerStyle = window.getComputedStyle(container);
|
|
83
|
+
const borderLeftWidth = parseFloat(containerStyle.borderLeftWidth) || 0;
|
|
84
|
+
const borderTopWidth = parseFloat(containerStyle.borderTopWidth) || 0;
|
|
85
|
+
const borderRightWidth = parseFloat(containerStyle.borderRightWidth) || 0;
|
|
86
|
+
const borderBottomWidth = parseFloat(containerStyle.borderBottomWidth) || 0;
|
|
87
|
+
const yScrollerWidth = container.offsetWidth - container.clientWidth - borderLeftWidth - borderRightWidth;
|
|
88
|
+
const xScrollerHeight = container.offsetHeight - container.clientHeight - borderTopWidth - borderBottomWidth;
|
|
89
|
+
// console.log('yScrollerWidth, xScrollerHeight', yScrollerWidth, xScrollerHeight);
|
|
90
90
|
|
|
91
|
-
get windowSize() {
|
|
92
|
-
const container = this.getContainer();
|
|
93
|
-
const { clientWidth, clientHeight } = container;
|
|
94
91
|
return {
|
|
95
|
-
|
|
96
|
-
|
|
92
|
+
width: containerRect.width / this.cachedScaleX - borderLeftWidth - borderRightWidth - yScrollerWidth,
|
|
93
|
+
height: containerRect.height / this.cachedScaleY - borderTopWidth - borderBottomWidth - xScrollerHeight,
|
|
94
|
+
left: containerRect.left / this.cachedScaleX,
|
|
95
|
+
top: containerRect.top / this.cachedScaleY,
|
|
96
|
+
scrollLeft: container.scrollLeft,
|
|
97
|
+
scrollTop: container.scrollTop,
|
|
98
|
+
borderLeftWidth: borderLeftWidth,
|
|
99
|
+
borderTopWidth: borderTopWidth,
|
|
97
100
|
};
|
|
98
101
|
}
|
|
99
102
|
|
|
@@ -113,19 +116,21 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
113
116
|
get dragPositionBoundaries() {
|
|
114
117
|
const { boundsX, boundsY, placement = 'bottom-right' } = this.props;
|
|
115
118
|
const dragSize = this.dragBoxSize;
|
|
116
|
-
const
|
|
119
|
+
const {width: containerWidth, height: containerHeight} = this.getContainerRect();
|
|
117
120
|
const [placementY, placementX] = placement.split('-') as ['top' | 'bottom', 'left' | 'right'];
|
|
118
121
|
|
|
122
|
+
const defaultBounds = {
|
|
123
|
+
minX: 0,
|
|
124
|
+
maxX: Math.max(containerWidth - dragSize.width, 0),
|
|
125
|
+
minY: 0,
|
|
126
|
+
maxY: Math.max(containerHeight- dragSize.height, 0),
|
|
127
|
+
};
|
|
119
128
|
// 初始化边界
|
|
120
|
-
let minX =
|
|
121
|
-
let maxX = windowSize.width - dragSize.width;
|
|
122
|
-
let minY = 0;
|
|
123
|
-
let maxY = windowSize.height - dragSize.height;
|
|
129
|
+
let {minX, maxX, minY, maxY} = defaultBounds
|
|
124
130
|
|
|
125
131
|
// 处理X轴边界
|
|
126
132
|
if (boundsX) {
|
|
127
133
|
const [minBound, maxBound] = boundsX;
|
|
128
|
-
|
|
129
134
|
if (placementX === 'left') {
|
|
130
135
|
// 左边位置:boundsX=[左边最小距离, 左边最大距离]
|
|
131
136
|
if (minBound !== undefined) minX = Math.max(minX, minBound);
|
|
@@ -134,19 +139,14 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
134
139
|
// 右边位置:boundsX=[右边最小距离, 右边最大距离]
|
|
135
140
|
// 直接使用边界值作为right的限制
|
|
136
141
|
if (minBound !== undefined && maxBound !== undefined) {
|
|
137
|
-
minX = Math.max(minX,
|
|
138
|
-
maxX = Math.min(maxX,
|
|
142
|
+
minX = Math.max(minX, containerWidth - maxBound - dragSize.width);
|
|
143
|
+
maxX = Math.min(maxX, containerWidth - minBound - dragSize.width);
|
|
139
144
|
} else if (minBound !== undefined) {
|
|
140
145
|
// 只有minBound:设置最大边界,最小边界保持默认
|
|
141
|
-
maxX = Math.min(maxX,
|
|
146
|
+
maxX = Math.min(maxX, containerWidth - minBound - dragSize.width);
|
|
142
147
|
} else if (maxBound !== undefined) {
|
|
143
148
|
// 只有maxBound:设置最小边界,最大边界保持默认
|
|
144
|
-
minX = Math.max(minX,
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// 确保最小边界不大于最大边界
|
|
148
|
-
if (minX > maxX) {
|
|
149
|
-
[minX, maxX] = [maxX, minX];
|
|
149
|
+
minX = Math.max(minX, containerWidth - maxBound - dragSize.width);
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
}
|
|
@@ -163,31 +163,25 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
163
163
|
// 底部位置:boundsY=[底边最小距离, 底边最大距离]
|
|
164
164
|
// 直接使用边界值作为bottom的限制
|
|
165
165
|
if (minBound !== undefined && maxBound !== undefined) {
|
|
166
|
-
minY = Math.max(minY,
|
|
167
|
-
maxY = Math.min(maxY,
|
|
166
|
+
minY = Math.max(minY, containerHeight - maxBound - dragSize.height);
|
|
167
|
+
maxY = Math.min(maxY, containerHeight - minBound - dragSize.height);
|
|
168
168
|
} else if (minBound !== undefined) {
|
|
169
169
|
// 只有minBound:设置最大边界,最小边界保持默认
|
|
170
|
-
maxY = Math.min(maxY,
|
|
170
|
+
maxY = Math.min(maxY, containerHeight - minBound - dragSize.height);
|
|
171
171
|
} else if (maxBound !== undefined) {
|
|
172
172
|
// 只有maxBound:设置最小边界,最大边界保持默认
|
|
173
|
-
minY = Math.max(minY,
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// 确保最小边界不大于最大边界
|
|
177
|
-
if (minY > maxY) {
|
|
178
|
-
[minY, maxY] = [maxY, minY];
|
|
173
|
+
minY = Math.max(minY, containerHeight - maxBound - dragSize.height);
|
|
179
174
|
}
|
|
180
175
|
}
|
|
181
176
|
}
|
|
177
|
+
// 确保各个边界值在默认范围内
|
|
178
|
+
minX = clamp(minX, defaultBounds.minX, defaultBounds.maxX);
|
|
179
|
+
maxX = clamp(maxX, minX, defaultBounds.maxX);
|
|
180
|
+
minY = clamp(minY, defaultBounds.minY, defaultBounds.maxY);
|
|
181
|
+
maxY = clamp(maxY, minY, defaultBounds.maxY);
|
|
182
182
|
|
|
183
183
|
return { minX, maxX, minY, maxY };
|
|
184
184
|
}
|
|
185
|
-
|
|
186
|
-
// 保持向后兼容
|
|
187
|
-
get dragPositionRang() {
|
|
188
|
-
const { maxX, maxY } = this.dragPositionBoundaries;
|
|
189
|
-
return { width: maxX, height: maxY };
|
|
190
|
-
}
|
|
191
185
|
|
|
192
186
|
get curPositionKey() {
|
|
193
187
|
let {placement} = this.props;
|
|
@@ -237,18 +231,17 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
237
231
|
|
|
238
232
|
reportStartPosition() {
|
|
239
233
|
if (this.draggerRef) {
|
|
240
|
-
const { top, left } = this.draggerRef.getBoundingClientRect();
|
|
241
|
-
const containerRect = this.getContainerRect();
|
|
242
|
-
// console.log(containerRect, 'containerRect');
|
|
243
|
-
|
|
244
234
|
// 获取缩放比例
|
|
245
|
-
const { scaleX, scaleY } = getScaleRatio(this.
|
|
235
|
+
const { scaleX, scaleY } = getScaleRatio(this.getContainer());
|
|
246
236
|
this.cachedScaleX = scaleX;
|
|
247
237
|
this.cachedScaleY = scaleY;
|
|
238
|
+
const { top, left } = this.draggerRef.getBoundingClientRect();
|
|
239
|
+
const containerRect = this.getContainerRect();
|
|
240
|
+
// console.log(containerRect, 'containerRect');
|
|
248
241
|
|
|
249
242
|
// 计算相对于容器的位置,并除以缩放比例得到未缩放的坐标
|
|
250
|
-
this.startTop =
|
|
251
|
-
this.startLeft =
|
|
243
|
+
this.startTop = top / scaleY - containerRect.top + containerRect.scrollTop - containerRect.borderTopWidth;
|
|
244
|
+
this.startLeft = left / scaleY - containerRect.left + containerRect.scrollLeft - containerRect.borderLeftWidth;
|
|
252
245
|
}
|
|
253
246
|
}
|
|
254
247
|
|
|
@@ -404,20 +397,12 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
404
397
|
this.dragAreaRef.style.height = '2px'; // 更细的虚线高度
|
|
405
398
|
this.dragAreaRef.style.left = `${minX}px`;
|
|
406
399
|
this.dragAreaRef.style.top = `${this.startTop + dragSize.height / 2}px`;
|
|
407
|
-
this.dragAreaRef.style.border = 'none';
|
|
408
|
-
this.dragAreaRef.style.backgroundColor = 'transparent'; // 透明背景
|
|
409
|
-
this.dragAreaRef.style.backgroundImage = 'linear-gradient(to right, var(--ohkit-color-primary, #1890ff) 50%, transparent 50%)';
|
|
410
|
-
this.dragAreaRef.style.backgroundSize = '4px 2px'; // 虚线模式
|
|
411
400
|
} else if (lockAxis === 'y') {
|
|
412
401
|
// 锁定X方向,显示为垂直虚线区域
|
|
413
402
|
this.dragAreaRef.style.width = '2px'; // 更细的虚线宽度
|
|
414
403
|
this.dragAreaRef.style.height = `${maxY - minY + dragSize.height}px`;
|
|
415
404
|
this.dragAreaRef.style.left = `${this.startLeft + dragSize.width / 2}px`;
|
|
416
405
|
this.dragAreaRef.style.top = `${minY}px`;
|
|
417
|
-
this.dragAreaRef.style.border = 'none';
|
|
418
|
-
this.dragAreaRef.style.backgroundColor = 'transparent'; // 透明背景
|
|
419
|
-
this.dragAreaRef.style.backgroundImage = 'linear-gradient(to bottom, var(--ohkit-color-primary, #1890ff) 50%, transparent 50%)';
|
|
420
|
-
this.dragAreaRef.style.backgroundSize = '2px 4px'; // 虚线模式
|
|
421
406
|
} else {
|
|
422
407
|
// 自由拖拽,显示完整区域
|
|
423
408
|
this.dragAreaRef.style.width = `${maxX - minX + dragSize.width}px`;
|
|
@@ -437,7 +422,7 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
437
422
|
calcPosition = () => {
|
|
438
423
|
const { lockAxis } = this.props;
|
|
439
424
|
const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;
|
|
440
|
-
const
|
|
425
|
+
const {height, width} = this.getContainerRect();
|
|
441
426
|
|
|
442
427
|
// 计算新的位置
|
|
443
428
|
let newTop = this.startTop;
|
|
@@ -451,13 +436,13 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
451
436
|
}
|
|
452
437
|
|
|
453
438
|
// 应用边界限制
|
|
454
|
-
const realTop =
|
|
455
|
-
const realLeft =
|
|
456
|
-
const realBottom =
|
|
457
|
-
const realRight =
|
|
439
|
+
const realTop = clamp(newTop, minY, maxY);
|
|
440
|
+
const realLeft = clamp(newLeft, minX, maxX);
|
|
441
|
+
const realBottom = height - realTop - this.dragBoxSize.height;
|
|
442
|
+
const realRight = width - realLeft - this.dragBoxSize.width;
|
|
458
443
|
if (realTop !== this.state.top || realLeft !== this.state.left || this.state.bottom !== realBottom || this.state.right !== realRight) {
|
|
459
|
-
// console.log(minY, maxY, this.startTop, this.dY, newTop, realTop, 'calcPosition y');
|
|
460
|
-
// console.log(minX, maxX, this.startLeft, this.dX, newLeft, realLeft, 'calcPosition x');
|
|
444
|
+
// console.log(minY, maxY, this.startTop, this.dY, newTop, realTop, 'minY, maxY, this.startTop, this.dY, newTop, realTop --- calcPosition y');
|
|
445
|
+
// console.log(minX, maxX, this.startLeft, this.dX, newLeft, realLeft, 'minX, maxX, this.startLeft, this.dX, newLeft, realLeft ---calcPosition x');
|
|
461
446
|
this.setState({
|
|
462
447
|
top: realTop,
|
|
463
448
|
left: realLeft,
|
package/src/utils.ts
CHANGED
|
@@ -1,42 +1,56 @@
|
|
|
1
1
|
import {findParent} from '@ohkit/dom-helper';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* 检查元素是否创建了新的定位上下文(包含块)
|
|
5
|
+
* @param element 要检查的元素
|
|
6
|
+
* @param includePosition 是否检查position属性(absolute/relative/fixed)
|
|
7
|
+
*/
|
|
8
|
+
export function isPositioningContextCreator(element: HTMLElement, includePosition: boolean): boolean {
|
|
9
|
+
const style = window.getComputedStyle(element);
|
|
10
|
+
const position = style.getPropertyValue('position');
|
|
11
|
+
const transform = style.getPropertyValue('transform');
|
|
12
|
+
const filter = style.getPropertyValue('filter');
|
|
13
|
+
const perspective = style.getPropertyValue('perspective');
|
|
14
|
+
const contain = style.getPropertyValue('contain');
|
|
15
|
+
const willChange = style.getPropertyValue('will-change');
|
|
16
|
+
|
|
17
|
+
return (includePosition && position !== 'static') ||
|
|
18
|
+
transform !== 'none' ||
|
|
19
|
+
filter !== 'none' ||
|
|
20
|
+
perspective !== 'none' ||
|
|
21
|
+
contain.includes('paint') ||
|
|
22
|
+
contain.includes('layout') ||
|
|
23
|
+
contain.includes('strict') ||
|
|
24
|
+
willChange.includes('transform') ||
|
|
25
|
+
willChange.includes('perspective') ||
|
|
26
|
+
willChange.includes('filter');
|
|
27
|
+
}
|
|
28
|
+
|
|
3
29
|
/**
|
|
4
30
|
* 查找影响 fixed 定位的父元素
|
|
5
|
-
* 当父元素有 transform/filter/perspective 等属性时,fixed 定位会相对于该父元素
|
|
31
|
+
* 当父元素有 transform/filter/perspective/contain/will-change 等属性时,fixed 定位会相对于该父元素
|
|
6
32
|
*/
|
|
7
|
-
export function findFixedPositionParent(dom?: HTMLElement | null)
|
|
33
|
+
export function findFixedPositionParent(dom?: HTMLElement | null) {
|
|
8
34
|
if (!dom) {
|
|
9
35
|
return document.documentElement;
|
|
10
36
|
}
|
|
11
37
|
const fixedPositionParent = findParent(dom, (parent) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const filter = style.getPropertyValue('filter');
|
|
15
|
-
const perspective = style.getPropertyValue('perspective');
|
|
16
|
-
|
|
17
|
-
// 检查是否有影响 fixed 定位的属性
|
|
18
|
-
if (transform !== 'none' || filter !== 'none' || perspective !== 'none') {
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
}, {excludeOwn: true}) || document.documentElement; // 没有找到,返回 window(通过 document.documentElement)
|
|
38
|
+
return isPositioningContextCreator(parent, false);
|
|
39
|
+
}, {excludeOwn: true}); // 没有找到,返回 window(通过 document.documentElement)
|
|
22
40
|
return fixedPositionParent;
|
|
23
41
|
}
|
|
24
42
|
|
|
25
43
|
/**
|
|
26
44
|
* 查找 absolute 定位的父元素
|
|
27
|
-
*
|
|
45
|
+
* 查找最近的包含块创建者,包含所有可能影响absolute定位的属性
|
|
28
46
|
*/
|
|
29
|
-
export function findAbsolutePositionParent(dom?: HTMLElement | null)
|
|
47
|
+
export function findAbsolutePositionParent(dom?: HTMLElement | null) {
|
|
30
48
|
if (!dom) {
|
|
31
49
|
return document.body;
|
|
32
50
|
}
|
|
33
51
|
return findParent(dom, (parent) => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (position !== 'static') {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
}, {excludeOwn: true}) || document.body;
|
|
52
|
+
return isPositioningContextCreator(parent, true);
|
|
53
|
+
}, {excludeOwn: true});
|
|
40
54
|
}
|
|
41
55
|
|
|
42
56
|
/**
|
|
@@ -49,9 +63,26 @@ export function getScaleRatio(dom?: HTMLElement | null): { scaleX: number; scale
|
|
|
49
63
|
}
|
|
50
64
|
// 通过比较 offsetWidth 和 getBoundingClientRect().width 来获取缩放比例
|
|
51
65
|
const rect = dom.getBoundingClientRect();
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
66
|
+
let scaleX = 1;
|
|
67
|
+
let scaleY = 1;
|
|
68
|
+
// 扩大{magnification}倍进行计算, 相当于保留小数点后4位
|
|
69
|
+
const magnification = 10000;
|
|
70
|
+
scaleX = dom.offsetWidth > 0 ? Math.round(rect.width / dom.offsetWidth * magnification) / magnification : 1;
|
|
71
|
+
scaleY = dom.offsetHeight > 0 ? Math.round(rect.height / dom.offsetHeight * magnification) / magnification : 1;
|
|
72
|
+
// console.log('rect.width dom.offsetWidth', rect.width, dom.offsetWidth);
|
|
73
|
+
// console.log('rect.height dom.offsetHeight', rect.height, dom.offsetHeight);
|
|
55
74
|
// console.log('scaleX', scaleX, 'scaleY', scaleY);
|
|
56
75
|
return { scaleX, scaleY };
|
|
57
76
|
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 限制数值在指定范围内
|
|
80
|
+
*
|
|
81
|
+
* @param value 要限制的数值
|
|
82
|
+
* @param min 最小值
|
|
83
|
+
* @param max 最大值
|
|
84
|
+
* @returns 限制后的数值,确保在 [min, max] 范围内
|
|
85
|
+
*/
|
|
86
|
+
export function clamp(value: number, min: number, max: number) {
|
|
87
|
+
return Math.min(Math.max(value, min), max);
|
|
88
|
+
}
|