两个面板


初步方案:基于translate偏移量的控制方式

  1. 实现思路

通过监听主控元素的translate位移变化,将位移量按比例转换为目标元素的宽高值。这种方案保持主控元素的位置属性不变,仅通过视觉位移实现控制。

  1. 可能的写法
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    });
  1. 出现的问题:

拖拽条的位置和预期位置不一致

产生问题的原因是面板宽度变化触发Flex容器重新计算项目位置,会与主动应用translate产生位移量叠加 ,导致移动速度翻倍,出现拖拽条位置和预期不一致的问题

最终方案:使用flex布局驱动

这个问题的解决办法比较简单的是采用纯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值实现尺寸控制,主控元素位置会自动适应布局变化。