@ohkit/draggable-box 0.0.2 → 0.0.3

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/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, clamp} from './utils';
7
+ import {findFixedPositionParent, findAbsolutePositionParent, getScaleRatio, clamp, supportsTouchEvents} from './utils';
8
8
  import {ValidPlacement} from './constants';
9
9
  import {DraggableBoxProps, DraggableBoxState} from './type';
10
10
 
@@ -20,6 +20,7 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
20
20
  disabled: false,
21
21
  lockAxis: 'none',
22
22
  showDragArea: false,
23
+ showDragAreaOverMoveDistanse: 5,
23
24
  positionMode: 'fixed',
24
25
  };
25
26
 
@@ -226,6 +227,7 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
226
227
  __bodyClassDisposer?: () => void;
227
228
  __upDisposer?: () => void;
228
229
  __resizeDisposer?: () => void;
230
+ __preventScrollDisposer?: () => void;
229
231
 
230
232
  dragAreaRef: HTMLDivElement | null = null;
231
233
 
@@ -245,15 +247,19 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
245
247
  }
246
248
  }
247
249
 
248
- enableDrag = () => {
250
+ enableDrag = (isTouch = false) => {
249
251
  this.reportStartPosition();
250
252
  this.__moveDisposer?.();
251
- this.__moveDisposer = addEventListener(document, 'mousemove', (evt) => {
253
+ this.__moveDisposer = addEventListener(isTouch && this.draggerRef ? this.draggerRef : document, isTouch ? 'touchmove' : 'mousemove', (evt) => {
254
+ evt.stopPropagation();
255
+ if (isTouch) {
256
+ evt.preventDefault();
257
+ }
252
258
  // INFO: 移动过程中禁止click事件
253
259
  if (!this.__clickDisposer) {
254
260
  const moveDistanse = Math.sqrt(Math.pow(this.dX, 2) + Math.pow(this.dY, 2));
255
- // INFO: 移动超过5px?? 确保用户有真实的移动意愿,而不是手抖~~
256
- if (moveDistanse > 5) {
261
+ // INFO: 移动超过px?? 确保用户有真实的移动意愿,而不是手抖~~
262
+ if (moveDistanse > (this.props.showDragAreaOverMoveDistanse || 5)) {
257
263
  this.__clickDisposer = addEventListener(
258
264
  document,
259
265
  'click',
@@ -270,17 +276,17 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
270
276
  }
271
277
  }
272
278
  }
273
- this.dragging(evt);
274
- }, true);
279
+ this.dragging(evt as TouchEvent | MouseEvent);
280
+ }, {
281
+ passive: !isTouch
282
+ });
275
283
 
276
284
  this.__upDisposer?.();
277
285
  this.__upDisposer = addEventListener(
278
286
  document,
279
287
  'mouseup',
280
- (evt) => {
288
+ () => {
281
289
  this.endDrag();
282
- evt.stopPropagation();
283
- evt.preventDefault();
284
290
  },
285
291
  true
286
292
  );
@@ -294,11 +300,11 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
294
300
  this.axisX = evt.nativeEvent.pageX;
295
301
  this.axisY = evt.nativeEvent.pageY;
296
302
  if (!this.props.disabled) {
297
- this.enableDrag();
303
+ this.enableDrag();
298
304
  }
299
305
  };
300
306
 
301
- dragging = (evt: MouseEvent) => {
307
+ dragging = (evt: MouseEvent | TouchEvent) => {
302
308
  this.isDragging = true;
303
309
  const { lockAxis } = this.props;
304
310
  const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;
@@ -307,9 +313,21 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
307
313
  const scaleX = this.cachedScaleX;
308
314
  const scaleY = this.cachedScaleY;
309
315
 
316
+ // 获取坐标
317
+ let pageX: number, pageY: number;
318
+ if (evt instanceof TouchEvent) {
319
+ const touch = evt.touches[0];
320
+ if (!touch) return;
321
+ pageX = touch.pageX;
322
+ pageY = touch.pageY;
323
+ } else {
324
+ pageX = evt.pageX;
325
+ pageY = evt.pageY;
326
+ }
327
+
310
328
  // 计算原始偏移量(需要除以缩放比例)
311
- this.dX = (evt.pageX - (this.axisX || 0)) / scaleX;
312
- this.dY = (evt.pageY - (this.axisY || 0)) / scaleY;
329
+ this.dX = (pageX - (this.axisX || 0)) / scaleX;
330
+ this.dY = (pageY - (this.axisY || 0)) / scaleY;
313
331
 
314
332
  // 应用方向锁定并计算变换值
315
333
  let translateX = this.dX;
@@ -346,7 +364,16 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
346
364
  if (this.draggerRef) {
347
365
  this.draggerRef.style.transform = `translate(${translateX}px, ${translateY}px)`;
348
366
  }
349
- evt.stopPropagation();
367
+ };
368
+
369
+ startTouchDrag = (evt: React.TouchEvent<HTMLDivElement>) => {
370
+ const touch = evt.touches[0];
371
+ if (!touch) return;
372
+ this.axisX = touch.pageX;
373
+ this.axisY = touch.pageY;
374
+ if (!this.props.disabled) {
375
+ this.enableDrag(true);
376
+ }
350
377
  };
351
378
 
352
379
  endDrag = () => {
@@ -362,8 +389,10 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
362
389
  }
363
390
  }
364
391
 
365
- this.__moveDisposer?.();
366
- this.__moveDisposer = undefined;
392
+ if (this.__moveDisposer) {
393
+ this.__moveDisposer();
394
+ this.__moveDisposer = undefined;
395
+ }
367
396
  if (this.__clickDisposer) {
368
397
  requestAnimationFrame(() => {
369
398
  if (this.__clickDisposer) {
@@ -372,10 +401,14 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
372
401
  }
373
402
  });
374
403
  }
375
- this.__upDisposer?.();
376
- this.__upDisposer = undefined;
377
- this.__bodyClassDisposer?.();
378
- this.__bodyClassDisposer = undefined;
404
+ if (this.__upDisposer) {
405
+ this.__upDisposer();
406
+ this.__upDisposer = undefined;
407
+ }
408
+ if (this.__bodyClassDisposer) {
409
+ this.__bodyClassDisposer();
410
+ this.__bodyClassDisposer = undefined;
411
+ }
379
412
 
380
413
  this.isDragging = false;
381
414
  };
@@ -464,6 +497,13 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
464
497
  this.__resizeDisposer = addEventListener(window, 'resize', () => {
465
498
  this.calcPosition();
466
499
  });
500
+
501
+ // 触屏设备时,阻止拖拽时滚动页面
502
+ if (supportsTouchEvents() && this.draggerRef) {
503
+ this.__preventScrollDisposer = addEventListener(this.draggerRef, 'touchmove', (evt) => {
504
+ evt.preventDefault();
505
+ });
506
+ }
467
507
  }
468
508
 
469
509
  componentWillUnmount() {
@@ -472,11 +512,12 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
472
512
  this.__moveDisposer?.();
473
513
  this.__clickDisposer?.();
474
514
  this.__upDisposer?.();
515
+ this.__preventScrollDisposer?.();
475
516
  }
476
517
 
477
518
  render() {
478
519
  const { className, zIndex, children, showDragArea, positionMode = 'fixed' } = this.props;
479
- const { startDrag, endDrag } = this;
520
+ const { startDrag, startTouchDrag, endDrag } = this;
480
521
  const stl = {
481
522
  zIndex,
482
523
  ...this.position,
@@ -508,8 +549,10 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
508
549
  ref={(r) => {
509
550
  this.draggerRef = r;
510
551
  }}
511
- onMouseDown={startDrag}
512
- onMouseUp={endDrag}
552
+ onMouseDownCapture={startDrag}
553
+ onMouseUpCapture={endDrag}
554
+ onTouchStartCapture={startTouchDrag}
555
+ onTouchEndCapture={endDrag}
513
556
  >
514
557
  {children}
515
558
  </div>
package/src/type.ts CHANGED
@@ -51,6 +51,11 @@ export interface DraggableBoxProps {
51
51
  * @default false
52
52
  */
53
53
  showDragArea?: boolean;
54
+ /**
55
+ * 拖拽过程中,超出多少px时才显示拖拽区域可视化
56
+ * @default 5
57
+ */
58
+ showDragAreaOverMoveDistanse?: number;
54
59
  /**
55
60
  * 定位模式
56
61
  * 'fixed' - 使用 fixed 定位(默认),动态查找影响 fixed 定位的父元素
package/src/utils.ts CHANGED
@@ -86,3 +86,13 @@ export function getScaleRatio(dom?: HTMLElement | null): { scaleX: number; scale
86
86
  export function clamp(value: number, min: number, max: number) {
87
87
  return Math.min(Math.max(value, min), max);
88
88
  }
89
+
90
+
91
+ /**
92
+ * 检测当前环境是否支持触摸事件
93
+ *
94
+ * @returns 如果环境支持触摸事件返回 true,否则返回 false
95
+ */
96
+ export function supportsTouchEvents() {
97
+ return typeof window !== 'undefined' && ('ontouchstart' in window || navigator.maxTouchPoints > 0);
98
+ };