
本文介绍如何改造传统宽度驱动型拖拽分隔条,使其通过控制 left 偏移量来移动左右面板(尤其是左侧图片),保持元素尺寸不变,仅改变其在容器中的水平位置,从而实现“滑出屏幕”的对比浏览效果。
本文介绍如何改造传统宽度驱动型拖拽分隔条,使其通过控制 `left` 偏移量来移动左右面板(尤其是左侧图片),保持元素尺寸不变,仅改变其在容器中的水平位置,从而实现“滑出屏幕”的对比浏览效果。
在典型的双栏拖拽对比组件(如 CodePen 中常见的 dragbar 示例)中,逻辑通常基于动态调整左侧面板的 width 来实现分隔效果。但本需求恰恰相反:左侧文章截图需保持 100% 宽高自适应、不缩放不变形,仅随拖拽条水平位移而整体平移——即用 position: absolute + left 控制位置,而非 width 拉伸/压缩。
✅ 核心改造思路
-
布局重构:将
.panel-one(左图)设为position: absolute,脱离文档流,使其left值可自由控制; -
拖拽逻辑重写:不再修改
style.width,而是计算鼠标 X 坐标并赋值给left.style.left; -
同步定位:同时更新
.dragbar和右侧面板(若需对齐)的left,确保视觉连贯; -
容器约束:
.drag-container需设为position: relative,作为绝对定位元素的参考父容器。
✅ 修改后的完整 JS 逻辑(推荐)
const left = document.getElementById('drag-left');
const right = document.getElementById('drag-right');
const dragbar = document.getElementById('dragbar');
// 确保容器为相对定位(关键!)
const container = document.querySelector('.drag-container');
if (container && !container.style.position) {
container.style.position = 'relative';
}
const drag = (e) => {
// 清除文本选中(防拖拽干扰)
document.selection ? document.selection.empty() : window.getSelection().removeAllRanges();
// 计算相对于容器左边缘的偏移(推荐使用 getBoundingClientRect 更健壮)
const rect = container.getBoundingClientRect();
const newPosition = e.clientX - rect.left - dragbar.offsetWidth / 2;
// 直接设置 left 值(单位 px)
left.style.left = `${newPosition}px`;
dragbar.style.left = `${newPosition}px`;
// 右侧面板可选择固定定位,或也设 left 实现联动(此处按需保留原布局)
};
// 绑定事件
dragbar.addEventListener('mousedown', () => {
document.addEventListener('mousemove', drag);
// 防止默认行为(如图片拖拽)
dragbar.style.userSelect = 'none';
});
document.addEventListener('mouseup', () => {
document.removeEventListener('mousemove', drag);
dragbar.style.userSelect = '';
});
✅ 必要的 CSS 调整
.drag-container {
display: flex;
min-height: 100vh;
position: relative; /* 关键:作为绝对定位的 containing block */
}
.panel-one {
position: absolute;
top: 0;
width: 100%; /* 图片自身用 width: 100%; height: 100% 即可撑满 */
height: 100%;
/* 移除原有 width: 48% 等固定宽度 */
}
.panel-two {
/* 右侧内容保持 flex 自适应,无需 absolute */
flex: 1;
padding: 0 20px;
}
.dragbar {
position: absolute;
top: 0;
bottom: 0;
width: 8px; /* 细条更符合拖拽感 */
background-color: rgb(25, 0, 75);
cursor: ew-resize;
z-index: 10;
user-select: none;
}
⚠️ 注意事项与优化建议
-
边界限制:当前代码允许拖拽超出可视区。如需限制范围(例如左图最多左移
-100%,最多右移0px),可在drag函数中添加:const maxLeft = 0; const minLeft = -left.offsetWidth; // 或固定像素值,如 -800 left.style.left = `${Math.max(minLeft, Math.min(maxLeft, newPosition))}px`; -
响应式兼容:
e.clientX在缩放/滚动页面时可能偏移,生产环境建议用e.clientX - container.getBoundingClientRect().left(已含在示例中); -
移动端支持:需额外监听
touchstart/touchmove事件,并用e.touches[0].clientX替代e.clientX; -
性能优化:高频
mousemove可加节流(如requestAnimationFrame包裹),避免卡顿。
通过以上改造,左侧图片将真正“随拖拽条滑动”,而非被挤压变形——完美满足设计稿中“平移对比”的交互诉求。










