js实现拖拽缩放
实现拖拽缩放的基本思路
拖拽缩放功能通常需要监听鼠标事件,计算元素位置和尺寸变化。以下是实现的核心步骤:

监听鼠标事件
为可拖拽缩放的元素添加mousedown事件监听器,记录初始位置和尺寸。在mousemove事件中计算位移并更新元素样式,mouseup事件结束拖拽。

const element = document.getElementById('resizable');
let isDragging = false;
let startX, startY, startWidth, startHeight;
element.addEventListener('mousedown', (e) => {
isDragging = true;
startX = e.clientX;
startY = e.clientY;
startWidth = parseInt(document.defaultView.getComputedStyle(element).width, 10);
startHeight = parseInt(document.defaultView.getComputedStyle(element).height, 10);
e.preventDefault();
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const width = startWidth + e.clientX - startX;
const height = startHeight + e.clientY - startY;
element.style.width = `${width}px`;
element.style.height = `${height}px`;
});
document.addEventListener('mouseup', () => {
isDragging = false;
});
添加拖拽手柄
通常在元素角落添加一个小方块作为拖拽手柄,限制只能从特定方向缩放:
const handle = document.createElement('div');
handle.style.width = '10px';
handle.style.height = '10px';
handle.style.backgroundColor = 'red';
handle.style.position = 'absolute';
handle.style.right = '0';
handle.style.bottom = '0';
handle.style.cursor = 'se-resize';
element.appendChild(handle);
handle.addEventListener('mousedown', (e) => {
isDragging = true;
startX = e.clientX;
startY = e.clientY;
startWidth = parseInt(document.defaultView.getComputedStyle(element).width, 10);
startHeight = parseInt(document.defaultView.getComputedStyle(element).height, 10);
e.stopPropagation();
});
限制最小尺寸
防止元素被缩放到不可见或太小:
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
let width = startWidth + e.clientX - startX;
let height = startHeight + e.clientY - startY;
width = Math.max(width, 50); // 最小宽度50px
height = Math.max(height, 50); // 最小高度50px
element.style.width = `${width}px`;
element.style.height = `${height}px`;
});
完整示例代码
<!DOCTYPE html>
<html>
<head>
<style>
#resizable {
width: 200px;
height: 200px;
background: lightblue;
position: relative;
}
.handle {
width: 10px;
height: 10px;
background: red;
position: absolute;
right: 0;
bottom: 0;
cursor: se-resize;
}
</style>
</head>
<body>
<div id="resizable">
<div class="handle"></div>
</div>
<script>
const element = document.getElementById('resizable');
const handle = element.querySelector('.handle');
let isDragging = false;
let startX, startY, startWidth, startHeight;
handle.addEventListener('mousedown', (e) => {
isDragging = true;
startX = e.clientX;
startY = e.clientY;
startWidth = parseInt(document.defaultView.getComputedStyle(element).width, 10);
startHeight = parseInt(document.defaultView.getComputedStyle(element).height, 10);
e.stopPropagation();
e.preventDefault();
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
let width = startWidth + e.clientX - startX;
let height = startHeight + e.clientY - startY;
width = Math.max(width, 50);
height = Math.max(height, 50);
element.style.width = `${width}px`;
element.style.height = `${height}px`;
});
document.addEventListener('mouseup', () => {
isDragging = false;
});
</script>
</body>
</html>
进阶优化方向
- 添加边界限制:防止元素超出父容器范围
- 保持宽高比:按住Shift键时保持原始比例缩放
- 触摸屏支持:添加
touchstart、touchmove和touchend事件 - 性能优化:使用
transform代替直接修改宽高减少重排 - 多方向手柄:添加顶部、左侧等不同方向的缩放手柄
以上代码实现了基本的右下角拖拽缩放功能,可根据需求进一步扩展和完善。






