通过监听主控元素的移动事件(鼠标拖拽或触摸移动),实时计算位移量,然后将这个位移量按比例映射到目标元素的宽高属性上,形成联动效果。
1<div id="panel">panel</div>
2<div id="handler">handler ele</div>
1// 主控元素事件监听
2const handleEle = document.getElementById('handler');
3 const panelEle = document.getElementById('panel');
4 let isDragging = false;
5 let offsetX, offsetY;
6
7 let mouseBegin = {
8 x: undefined,
9 y: undefined
10 }
11 let eleBegin = {
12 x: undefined,
13 y: undefined
14 }
15 let panelSize = {
16 width: undefined,
17 height: undefined
18 }
19 let panelMinSize = {
20 width: 100,
21 height: 100
22 }
23
24
25 handleEle.addEventListener('mousedown', (e) => {
26 isDragging = true;
27 const rect = handleEle.getBoundingClientRect();
28 mouseBegin.x = e.x;
29 mouseBegin.y = e.y;
30 const style = window.getComputedStyle(handleEle);
31 const matrix = new DOMMatrix(style.transform);
32 eleBegin = { x: matrix.m41, y: matrix.m42 };
33
34 const panelElePos = panelEle.getBoundingClientRect();
35 const { width, height } = panelElePos;
36 panelSize = { width, height }
37
38 });
39
40 document.addEventListener('mousemove', (e) => {
41 if (!isDragging) return;
42 offsetX = e.x - mouseBegin.x;
43 offsetY = e.y - mouseBegin.y;
44 handleEle.style.transform = `translate(${eleBegin.x + offsetX}px, ${eleBegin.y + offsetY}px)`;
45
46 console.log(offsetX, panelSize.width + offsetX);
47 panelEle.style.width = Math.max(panelMinSize.width, panelSize.width + offsetX)+ 'px';
48 panelEle.style.height = Math.max(panelMinSize.height, panelSize.height + offsetY )+ 'px';
49 });
50
51 document.addEventListener('mouseup', () => {
52 isDragging = false;
53 });
1<div id="panel">panel</div>
2<div id="handler">handler ele</div>
1<script>
2
3 const handleEle = document.getElementById('handler');
4 const panelEle = document.getElementById('panel');
5 let isDragging = false;
6 let offsetX, offsetY;
7
8 let mouseBegin = {
9 x: undefined,
10 y: undefined
11 }
12 let eleBegin = {
13 x: undefined,
14 y: undefined
15 }
16 let panelSize = {
17 width: undefined,
18 height: undefined
19 }
20 let panelMinSize = {
21 width: 100,
22 height: 200
23 }
24
25 handleEle.addEventListener('mousedown', (e) => {
26 isDragging = true;
27 const rect = handleEle.getBoundingClientRect();
28 mouseBegin.x = e.x;
29 mouseBegin.y = e.y;
30 const style = window.getComputedStyle(handleEle);
31 const matrix = new DOMMatrix(style.transform);
32 eleBegin = { x: matrix.m41, y: matrix.m42 };
33
34 const panelElePos = panelEle.getBoundingClientRect();
35 const { width, height } = panelElePos;
36 panelSize = { width, height }
37
38 });
39
40 document.addEventListener('mousemove', (e) => {
41 if (!isDragging) return;
42 offsetX = e.x - mouseBegin.x;
43 offsetY = e.y - mouseBegin.y;
44
45 // 需要实时更新拖拽条的位置,这样在满足条件后,可以给拖拽条的偏移量设置固定值
46 const style = window.getComputedStyle(handleEle);
47 const matrix = new DOMMatrix(style.transform);
48 eleBegin = { x: matrix.m41, y: matrix.m42 };
49
50 let translateX;
51 let translateY;
52
53 if (panelSize.width + offsetX <= panelMinSize.width && offsetX < 0) {
54 translateX = eleBegin.x
55 } else if (panelSize.height + offsetY <= panelMinSize.height && offsetY < 0) {
56 translateY = eleBegin.y;
57 } else {
58 translateX = eleBegin.x + offsetX;
59 translateY = eleBegin.y + offsetY;
60 }
61
62 handleEle.style.transform = `translate(${translateX}px, ${translateY}px)`;
63
64 mouseBegin = {x: e.x, y: e.y };
65
66 // 元素的最大最小宽度限制
67 const w = Math.max(panelSize.width + offsetX, panelMinSize.width);
68 const h = Math.max(panelSize.height + offsetY, panelMinSize.height);
69 panelEle.style.width = w + 'px';
70 panelEle.style.height = h+ 'px';
71 panelSize = { width: w, height: h}
72 });
73
74 document.addEventListener('mouseup', () => {
75 isDragging = false;
76 });
77
78 </script>
在实现到达最大最小值拖拽条不能移动的需求时,不能只记录mousedown时拖拽条的位置,要记录实时位置,这样在到达限制后,可以给translateX或者translateY设置为固定值。