求助:优化JavaScript实现的文本框拖拽调整宽度功能
问题
需要实现两个并排textarea的拖拽调整宽度功能,参考双栏编辑器的拖拽效果,但现有代码存在拖拽不流畅、无法拖至全宽的问题,原代码如下:
<!DOCTYPE html> <html> <head> <title>Log Converter</title> <script src="https://cdn.tailwindcss.com"></script> <style> #input, #output { height: 80vh; } * { box-sizing: border-box; } .bar { height: 90%; width: 2px; background-color: #ddd; cursor: w-resize; } </style> </head> <body class="bg-gray-100"> <div class="container mx-auto mt-10 p-4"> <div class="flex gap-2"> <div class="w-full left"> <div class="editor"> <textarea id="input" class="w-full h-48 p-4 bg-white rounded" placeholder="Enter logs here..."></textarea> </div> <button class="btn bg-green-500 text-white px-4 py-2 mt-4" onclick="convertLogs()">Convert</button> </div> <div><div class="bar w-1" title="Click & Drug"></div></div> <div class="w-full right"> <textarea id="output" class="w-full h-48 p-4 bg-white rounded" readonly></textarea> </div> </div> </div> <script> const left = document.querySelector(".left"), bar = document.querySelector(".bar"); const drag = (e) => { left.style.width = (e.pageX + (bar.offsetWidth * 148)) + "px"; } bar.addEventListener("mousedown", () => { document.addEventListener("mousemove", drag); }) window.addEventListener("click", () => { document.removeEventListener("mousemove", drag); }) </script> </body> </html>
解决方案
修改以下核心点即可解决问题:
- 替换拖拽宽度计算逻辑:基于父容器的相对位置计算宽度,避免绝对坐标导致的偏移
- 优化事件绑定:在
mouseup事件中移除拖拽监听,而非click事件,防止拖拽中途意外停止 - 添加边界限制:确保左右栏不会被拖到最小宽度以下或超出父容器范围
- 调整拖拽栏布局:让拖拽栏高度匹配编辑器区域,提升交互体验
完整修正代码:
<!DOCTYPE html> <html> <head> <title>Log Converter</title> <script src="https://cdn.tailwindcss.com"></script> <style> #input, #output { height: 80vh; } * { box-sizing: border-box; } .bar-container { display: flex; align-items: stretch; } .bar { width: 4px; background-color: #ddd; cursor: col-resize; margin: 0 4px; transition: background-color 0.2s; } .bar:hover { background-color: #999; } .left, .right { flex-shrink: 0; flex-grow: 1; min-width: 100px; /* 最小宽度限制,可调整 */ } </style> </head> <body class="bg-gray-100"> <div class="container mx-auto mt-10 p-4"> <div class="flex gap-2 h-[80vh]"> <div class="left w-1/2"> <div class="editor h-full flex flex-col"> <textarea id="input" class="flex-1 w-full p-4 bg-white rounded" placeholder="Enter logs here..."></textarea> <button class="btn bg-green-500 text-white px-4 py-2 mt-4" onclick="convertLogs()">Convert</button> </div> </div> <div class="bar-container"> <div class="bar" title="拖拽调整宽度"></div> </div> <div class="right w-1/2"> <textarea id="output" class="w-full h-full p-4 bg-white rounded" readonly></textarea> </div> </div> </div> <script> const left = document.querySelector(".left"), right = document.querySelector(".right"), bar = document.querySelector(".bar"), parent = bar.parentElement.parentElement; // 获取父容器 let isDragging = false; const startDrag = () => { isDragging = true; document.body.style.cursor = "col-resize"; }; const stopDrag = () => { isDragging = false; document.body.style.cursor = ""; }; const drag = (e) => { if (!isDragging) return; // 计算父容器的左侧偏移 const parentLeft = parent.getBoundingClientRect().left; // 计算左侧栏的宽度(鼠标位置 - 父容器左侧) let leftWidth = e.clientX - parentLeft; // 父容器总宽度 const parentWidth = parent.offsetWidth; // 右侧栏最小宽度 const minRightWidth = 100; // 边界限制:左侧栏不能太小,也不能让右侧栏小于最小宽度 leftWidth = Math.max(100, Math.min(leftWidth, parentWidth - minRightWidth - bar.offsetWidth)); left.style.width = `${leftWidth}px`; right.style.width = `${parentWidth - leftWidth - bar.offsetWidth - 8}px`; // 减去gap的2*4px }; bar.addEventListener("mousedown", startDrag); document.addEventListener("mousemove", drag); document.addEventListener("mouseup", stopDrag); </script> </body> </html>
关键修改说明
- 使用
clientX替代pageX,结合父容器的getBoundingClientRect()计算相对宽度,避免页面滚动导致的偏移 - 通过
isDragging状态变量控制拖拽逻辑,避免无效触发 - 添加
min-width和最大宽度限制,防止栏被拖到不可用的范围 - 调整拖拽栏的样式,增加hover效果提升交互反馈
- 让左右栏使用
flex布局,配合固定最小宽度,确保拖拽时布局稳定
内容的提问来源于stack exchange,提问作者Meshkat Hassan Riad
相关产品推荐
相关产品推荐

