下面是“JS通过八个点拖动改变div大小的实现方法”的完整攻略。
1. 需求分析
我们需要实现一个可以通过拖动八个点来改变一个 div 元素的大小的功能。最好的做法是使用原生 JavaScript 实现,而不是使用第三方类库,这样我们可以更好地理解背后的实现原理。
2. HTML 结构
首先,我们需要准备一个 div 元素,用于展示效果。具体的实现方法是通过在 div 元素上创建八个 span 元素,用于拖动改变 div 元素的大小。
<div class="box">
<span class="point top-left"></span>
<span class="point top"></span>
<span class="point top-right"></span>
<span class="point right"></span>
<span class="point bottom-right"></span>
<span class="point bottom"></span>
<span class="point bottom-left"></span>
<span class="point left"></span>
</div>
3. CSS 样式
接下来,我们需要为这些元素添加 CSS 样式。具体实现方式是为 box 和 point 添加相关样式,使其具有接下来我们需要的拖动效果。
.box {
width: 200px;
height: 200px;
background-color: #f0f0f0;
position: relative;
}
.point {
width: 10px;
height: 10px;
background-color: #333;
position: absolute;
}
.top-left {
top: -5px;
left: -5px;
cursor: nw-resize;
}
.top {
top: -5px;
left: 50%;
margin-left: -5px;
cursor: n-resize;
}
.top-right {
top: -5px;
right: -5px;
cursor: ne-resize;
}
.right {
top: 50%;
right: -5px;
margin-top: -5px;
cursor: e-resize;
}
.bottom-right {
bottom: -5px;
right: -5px;
cursor: se-resize;
}
.bottom {
bottom: -5px;
left: 50%;
margin-left: -5px;
cursor: s-resize;
}
.bottom-left {
bottom: -5px;
left: -5px;
cursor: sw-resize;
}
.left {
top: 50%;
left: -5px;
margin-top: -5px;
cursor: w-resize;
}
其中,box 元素使用了 position: relative;,使得 point 元素可以根据 box 元素进行定位。point 元素使用了 position: absolute;,为了脱离文档流,并且可以根据 box 元素进行定位。
在 point 元素中,我们对运用了不同的鼠标样式和定位方式,以实现不同方向的拖动效果。
4. JavaScript 代码实现
最后,我们需要编写 JavaScript 代码,为拖动点添加对应的事件监听器,以实现拖动大小的功能。
4.1 获取元素
首先,我们需要获取 box 和 point 元素,以便在后续的操作中使用。
var box = document.querySelector('.box');
var points = document.querySelectorAll('.point');
4.2 实现拖动
接下来,我们需要为每个拖动点添加事件监听器,以实现拖动效果。具体实现方式是监听鼠标的 mousedown、mousemove、mouseup 事件。
points.forEach(function(point) {
point.addEventListener('mousedown', handleMouseDown);
});
function handleMouseDown(e) {
var point = e.target;
var startX = e.pageX;
var startY = e.pageY;
var startWidth = parseInt(getComputedStyle(box).width);
var startHeight = parseInt(getComputedStyle(box).height);
var startTop = parseInt(getComputedStyle(box).top);
var startLeft = parseInt(getComputedStyle(box).left);
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
function handleMouseMove(e) {
var deltaX = e.pageX - startX;
var deltaY = e.pageY - startY;
switch (point.className) {
case 'point top-left':
box.style.width = startWidth - deltaX + 'px';
box.style.height = startHeight - deltaY + 'px';
box.style.top = startTop + deltaY + 'px';
box.style.left = startLeft + deltaX + 'px';
break;
case 'point top':
box.style.height = startHeight - deltaY + 'px';
box.style.top = startTop + deltaY + 'px';
break;
case 'point top-right':
box.style.width = startWidth + deltaX + 'px';
box.style.height = startHeight - deltaY + 'px';
box.style.top = startTop + deltaY + 'px';
break;
case 'point right':
box.style.width = startWidth + deltaX + 'px';
break;
case 'point bottom-right':
box.style.width = startWidth + deltaX + 'px';
box.style.height = startHeight + deltaY + 'px';
break;
case 'point bottom':
box.style.height = startHeight + deltaY + 'px';
break;
case 'point bottom-left':
box.style.width = startWidth - deltaX + 'px';
box.style.height = startHeight + deltaY + 'px';
box.style.left = startLeft + deltaX + 'px';
break;
case 'point left':
box.style.width = startWidth - deltaX + 'px';
box.style.left = startLeft + deltaX + 'px';
break;
default:
break;
}
e.stopPropagation();
e.preventDefault();
}
function handleMouseUp(e) {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
}
e.stopPropagation();
e.preventDefault();
}
在上述代码中,我们首先为每个 point 元素添加了 mousedown 事件监听器,当鼠标按下时会触发 handleMouseDown 函数。在 handleMouseDown 函数中,我们获取了相关信息,如起始坐标、元素宽高以及位置,以备后续使用。我们还添加了 mousemove 和 mouseup 事件监听器,以在鼠标移动时改变box元素的大小和位置,并在鼠标松开时移除监听器。
在 handleMouseMove 函数中,我们根据不同拖动点的位置,添加不同的改变逻辑,此处使用了一系列 switch 来判断分支。在 handleMouseUp 函数中,我们移除了所有的事件监听器。
4.3 完整代码
最终的代码实现如下:
<div class="box">
<span class="point top-left"></span>
<span class="point top"></span>
<span class="point top-right"></span>
<span class="point right"></span>
<span class="point bottom-right"></span>
<span class="point bottom"></span>
<span class="point bottom-left"></span>
<span class="point left"></span>
</div>
<style>
.box {
width: 200px;
height: 200px;
background-color: #f0f0f0;
position: relative;
}
.point {
width: 10px;
height: 10px;
background-color: #333;
position: absolute;
}
.top-left {
top: -5px;
left: -5px;
cursor: nw-resize;
}
.top {
top: -5px;
left: 50%;
margin-left: -5px;
cursor: n-resize;
}
.top-right {
top: -5px;
right: -5px;
cursor: ne-resize;
}
.right {
top: 50%;
right: -5px;
margin-top: -5px;
cursor: e-resize;
}
.bottom-right {
bottom: -5px;
right: -5px;
cursor: se-resize;
}
.bottom {
bottom: -5px;
left: 50%;
margin-left: -5px;
cursor: s-resize;
}
.bottom-left {
bottom: -5px;
left: -5px;
cursor: sw-resize;
}
.left {
top: 50%;
left: -5px;
margin-top: -5px;
cursor: w-resize;
}
</style>
<script>
var box = document.querySelector('.box');
var points = document.querySelectorAll('.point');
points.forEach(function(point) {
point.addEventListener('mousedown', handleMouseDown);
});
function handleMouseDown(e) {
var point = e.target;
var startX = e.pageX;
var startY = e.pageY;
var startWidth = parseInt(getComputedStyle(box).width);
var startHeight = parseInt(getComputedStyle(box).height);
var startTop = parseInt(getComputedStyle(box).top);
var startLeft = parseInt(getComputedStyle(box).left);
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
function handleMouseMove(e) {
var deltaX = e.pageX - startX;
var deltaY = e.pageY - startY;
switch (point.className) {
case 'point top-left':
box.style.width = startWidth - deltaX + 'px';
box.style.height = startHeight - deltaY + 'px';
box.style.top = startTop + deltaY + 'px';
box.style.left = startLeft + deltaX + 'px';
break;
case 'point top':
box.style.height = startHeight - deltaY + 'px';
box.style.top = startTop + deltaY + 'px';
break;
case 'point top-right':
box.style.width = startWidth + deltaX + 'px';
box.style.height = startHeight - deltaY + 'px';
box.style.top = startTop + deltaY + 'px';
break;
case 'point right':
box.style.width = startWidth + deltaX + 'px';
break;
case 'point bottom-right':
box.style.width = startWidth + deltaX + 'px';
box.style.height = startHeight + deltaY + 'px';
break;
case 'point bottom':
box.style.height = startHeight + deltaY + 'px';
break;
case 'point bottom-left':
box.style.width = startWidth - deltaX + 'px';
box.style.height = startHeight + deltaY + 'px';
box.style.left = startLeft + deltaX + 'px';
break;
case 'point left':
box.style.width = startWidth - deltaX + 'px';
box.style.left = startLeft + deltaX + 'px';
break;
default:
break;
}
e.stopPropagation();
e.preventDefault();
}
function handleMouseUp(e) {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
}
e.stopPropagation();
e.preventDefault();
}
</script>
示例说明
下面给出两个示例说明:
示例1
在简单的 HTML 网页上添加上述 HTML 结构、CSS 样式和 JavaScript 代码,我们可以看到一个可以通过八个点拖动改变大小的方框。
你可以访问这个示例网页,以体验具体效果。
示例2
假设我们要在 React 网站上添加该功能,具体实现方式如下:
我们需在 React 组件中添加上述 HTML 结构,并加载上述 CSS 样式。然后添加以下 JavaScript 代码实现拖动功能:
import React, { useRef } from 'react';
function Box() {
const boxRef = useRef(null);
const pointsRef = useRef([]);
const handleMouseDown = e => {
const point = e.target;
const startX = e.pageX;
const startY = e.pageY;
const startWidth = parseInt(getComputedStyle(boxRef.current).width);
const startHeight = parseInt(getComputedStyle(boxRef.current).height);
const startTop = parseInt(getComputedStyle(boxRef.current).top);
const startLeft = parseInt(getComputedStyle(boxRef.current).left);
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
function handleMouseMove(e) {
const deltaX = e.pageX - startX;
const deltaY = e.pageY - startY;
switch (point.className) {
case 'point top-left':
boxRef.current.style.width = startWidth - deltaX + 'px';
boxRef.current.style.height = startHeight - deltaY + 'px';
boxRef.current.style.top = startTop + deltaY + 'px';
boxRef.current.style.left = startLeft + deltaX + 'px';
break;
case 'point top':
boxRef.current.style.height = startHeight - deltaY + 'px';
boxRef.current.style.top = startTop + deltaY + 'px';
break;
case 'point top-right':
boxRef.current.style.width = startWidth + deltaX + 'px';
boxRef.current.style.height = startHeight - deltaY + 'px';
boxRef.current.style.top = startTop + deltaY + 'px';
break;
case 'point right':
boxRef.current.style.width = startWidth + deltaX + 'px';
break;
case 'point bottom-right':
boxRef.current.style.width = startWidth + deltaX + 'px';
boxRef.current.style.height = startHeight + deltaY + 'px';
break;
case 'point bottom':
boxRef.current.style.height = startHeight + deltaY + 'px';
break;
case 'point bottom-left':
boxRef.current.style.width = startWidth - deltaX + 'px';
boxRef.current.style.height = startHeight + deltaY + 'px';
boxRef.current.style.left = startLeft + deltaX + 'px';
break;
case 'point left':
boxRef.current.style.width = startWidth - deltaX + 'px';
boxRef.current.style.left = startLeft + deltaX + 'px';
break;
default:
break;
}
e.stopPropagation();
e.preventDefault();
}
function handleMouseUp(e) {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
}
e.stopPropagation();
e.preventDefault();
};
const handleBoxRef = reactElement => {
boxRef.current = reactElement;
};
const handlePointsRef = (index, reactElement) => {
pointsRef.current[index] = reactElement;
};
return (
<div className="box" ref={handleBoxRef}>
<span className="point top-left" ref={element => handlePointsRef(0, element)} onMouseDown={handleMouseDown} />
<span className="point top" ref={element => handlePointsRef(1, element)} onMouseDown={handleMouseDown} />
<span className="point top-right" ref={element => handlePointsRef(2, element)} onMouseDown={handleMouseDown} />
<span className="point right" ref={element => handlePointsRef(3, element)} onMouseDown={handleMouseDown} />
<span className="point bottom-right" ref={element => handlePointsRef(4, element)} onMouseDown={handleMouseDown} />
<span className="point bottom" ref={element => handlePointsRef(5, element)} onMouseDown={handleMouseDown} />
<span className="point bottom-left" ref={element => handlePointsRef(6, element)} onMouseDown={handleMouseDown} />
<span className="point left" ref={element => handlePointsRef(7, element)} onMouseDown={handleMouseDown} />
</div>
);
}
此处我们使用了 React Hooks API 中的 useRef 来获取 box 和 point 元素,并为每个唯一的 point 元素分配了一个 ref。最终的效果和上面的普通 HTML 网页效果相同。
你可以访问这个示例网页,以查看完整的 React 实现例子。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:js通过八个点 拖动改变div大小的实现方法 - Python技术站