通过监听主控元素的translate位移变化,将位移量按比例转换为目标元素的宽高值。这种方案保持主控元素的位置属性不变,仅通过视觉位移实现控制。
1#wrapper {
2 display: flex;
3 height: 300px;
4 border: 1px solid;
5}
6#handler {
7 width: 10px;
8 border: 1px solid;
9 background-color: aqua;
10 cursor: pointer;
11}
12[id^=panel] {
13 width: 200px;
14 height: 300px;
15 border: 1px solid;
16 background-color: bisque;
17}
1const wrapperEle = document.getElementById('wrapper');
2 const handleEle = document.getElementById('handler');
3 const panelLeftEle = document.getElementById('panel-left');
4 const panelRightEle = document.getElementById('panel-right');
5
6
7 let isDragging = false;
8 let offsetX, offsetY;
9
10 const containerWidth = wrapperEle.offsetWidth;
11 const dragBarWidth = handleEle.offsetWidth;
12
13 const leftWidth = (containerWidth / 2) - (dragBarWidth / 2);
14 const rightWidth = containerWidth - leftWidth - dragBarWidth;
15 // 初始化面板宽度
16 panelLeftEle.style.width = leftWidth;
17 panelRightEle.style.width = rightWidth;
18
19 // 获取当前translateX值
20 function getTranslateX(element) {
21 const style = window.getComputedStyle(element);
22 const matrix = new DOMMatrix(style.transform);
23 return matrix.m41;
24 }
25
26 handleEle.addEventListener('mousedown', (e) => {
27 startX = e.clientX;
28 startTranslateX = getTranslateX(handleEle);
29 isDragging = true;
30 });
31
32 document.addEventListener('mousemove', (e) => {
33 if (!isDragging) return;
34 const dx = e.clientX - startX;
35 const newTranslateX = startTranslateX + dx;
36
37 const containerWidth = wrapperEle.offsetWidth;
38 const dragBarWidth = handleEle.offsetWidth;
39
40 const leftWidth = (containerWidth / 2) + newTranslateX - (dragBarWidth / 2);
41 const rightWidth = containerWidth - leftWidth - dragBarWidth;
42
43 handleEle.style.transform = `translateX(${newTranslateX}px)`;
44 panelLeftEle.style.width = `${leftWidth}px`;
45 panelRightEle.style.width = `${rightWidth}px`;
46
47
48 });
49
50 document.addEventListener('mouseup', () => {
51 isDragging = false;
52 });
拖拽条的位置和预期位置不一致
产生问题的原因是面板宽度变化触发Flex容器重新计算项目位置,会与主动应用translate产生位移量叠加 ,导致移动速度翻倍,出现拖拽条位置和预期不一致的问题
这个问题的解决办法比较简单的是采用纯flex布局驱动,通过动态调整相邻面板的width或者flex-grow实现拖拽效果,无需手动改变拖拽条位置
1document.addEventListener('mousemove', (e) => {
2 if (!isDragging) return;
3 const dx = e.clientX - startX;
4 const newTranslateX = startTranslateX + dx;
5
6 const containerWidth = wrapperEle.offsetWidth;
7 const dragBarWidth = handleEle.offsetWidth;
8
9 const leftWidth = (containerWidth / 2) + newTranslateX - (dragBarWidth / 2);
10 const rightWidth = containerWidth - leftWidth - dragBarWidth;
11
12 // handleEle.style.transform = `translateX(${newTranslateX}px)`;
13 panelLeftEle.style.width = `${leftWidth}px`;
14 panelRightEle.style.width = `${rightWidth}px`;
15
16
17 });
在双面需求中,可以利用Flex容器的弹性分配特性,通过直接修改width/flex-grow值实现尺寸控制,主控元素位置会自动适应布局变化。