0%

Drop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
* 为了确保兼容性,建议使用 requestAnimationFrame 的 polyfill 版本 raf
*/
const MOVE_ANIM_INTER = 1000
const raf = window.requestAnimationFrame;

/**
* 封装拖拽函数
* @param $ele 需要拖拽的元素
* @param adsorb { x = 20, y = 80 } 上下左右吸附的边距
*/
export default function draggable($ele, adsorb = { x: 20, y: 80 }) {
if (!$ele) {
throw new Error("必须是可拖拽元素");
}
// 开始时候的位置
let startX = 0;
let startY = 0;

// 移动过程中的 left 和 top,其实通过这俩参数,就能确定元素位置
let left = 0;
let top = 0;

// 屏幕的宽高
const cw = document.documentElement.clientWidth;
const ch = document.documentElement.clientHeight;

// 获取到元素自身的宽高
const { width, height } = $ele.getBoundingClientRect();

/**
* 开始拖拽的事件
*/
$ele.addEventListener(
"touchstart",
function (event) {
startX = event.targetTouches[0].pageX;
startY = event.targetTouches[0].pageY;

top = $ele.offsetTop;
left = $ele.offsetLeft;

event.preventDefault();
},
false
);

/**
* 拖拽过程中的事件
*/
$ele.addEventListener(
"touchmove",
function (event) {
// 偏移距离
const offsetX = event.targetTouches[0].pageX - startX;
const offsetY = event.targetTouches[0].pageY - startY;

$ele.style.top = `${top + offsetY}px`;
$ele.style.left = `${left + offsetX}px`;
$ele.style.right = "auto";
$ele.style.bottom = "auto";

event.preventDefault();
},
false
);

function touchDone(event) {
const dx = event.changedTouches[0].pageX - startX;
const dy = event.changedTouches[0].pageY - startY;

const ty = top + dy;
const tx = left + dx;

$ele.style.top = `${ty}px`;
$ele.style.left = `${tx}px`;
$ele.style.right = "auto";
$ele.style.bottom = "auto";

const adsorb_safe_x = cw - width - adsorb.x;
const adsorb_safe_y = ch - height - adsorb.y;

raf(() => {
console.log('raf')
let nx;
let ny = ty;

if (tx + width / 2 < cw / 2) {
nx = adsorb.x;
} else {
nx = adsorb_safe_x;
}

if (ty < adsorb.y) {
ny = adsorb.y;
} else if (ty > adsorb_safe_y) {
ny = adsorb_safe_y;
}

$ele.style.webkitTransition = `left ${MOVE_ANIM_INTER}ms ease-in-out, top ${MOVE_ANIM_INTER}ms ease-in-out`;
$ele.style.transition = `left ${MOVE_ANIM_INTER}ms ease-in-out, top ${MOVE_ANIM_INTER}ms ease-in-out`;

const onAnimationDone = () => {
$ele.style.webkitTransition = $ele.style.transition = "none";
$ele.removeEventListener("webkitTransitionEnd", onAnimationDone, false);
$ele.removeEventListener("transitionend", onAnimationDone, false);
};

$ele.addEventListener("webkitTransitionEnd", onAnimationDone, false);
$ele.addEventListener("transitionend", onAnimationDone, false);
$ele.style.top = `${ny}px`;
$ele.style.left = `${nx}px`;
});
}

$ele.addEventListener("touchend", touchDone, true);
$ele.addEventListener("touchcancel", touchDone, true);
}