简单的拖放代码
Posted
技术标签:
【中文标题】简单的拖放代码【英文标题】:Simple drag and drop code 【发布时间】:2013-08-27 19:39:22 【问题描述】:我正在为看似简单的 javascript 练习而苦苦挣扎,正在编写一个香草拖放。我认为我的“addeventlisteners”有误,代码如下:
var ele = document.getElementsByClassName ("target")[0];
var stateMouseDown = false;
//ele.onmousedown = eleMouseDown;
ele.addEventListener ("onmousedown" , eleMouseDown , false);
function eleMouseDown ()
stateMouseDown = true;
document.addEventListener ("onmousemove" , eleMouseMove , false);
function eleMouseMove (ev)
do
var pX = ev.pageX;
var pY = ev.pageY;
ele.style.left = pX + "px";
ele.style.top = pY + "px";
document.addEventListener ("onmouseup" , eleMouseUp , false);
while (stateMouseDown === true);
function eleMouseUp ()
stateMouseDown = false;
document.removeEventListener ("onmousemove" , eleMouseMove , false);
document.removeEventListener ("onmouseup" , eleMouseUp , false);
【问题讨论】:
【参考方案1】:这是一个可以运行的 jsfiddle:http://jsfiddle.net/fpb7j/1/
有两个主要问题,首先是onmousedown
、onmousemove
和onmouseup
的使用。我相信这些只能与附加事件一起使用:
document.body.attachEvent('onmousemove',drag);
而 mousedown
、mousemove
和 mouseup
用于事件侦听器:
document.body.addEventListener('mousemove',drag);
第二个问题是移动事件函数中的 do-while 循环。每次鼠标移动一个像素时都会调用该函数,因此不需要循环:
var ele = document.getElementsByClassName ("target")[0];
ele.addEventListener ("mousedown" , eleMouseDown , false);
function eleMouseDown ()
stateMouseDown = true;
document.addEventListener ("mousemove" , eleMouseMove , false);
function eleMouseMove (ev)
var pX = ev.pageX;
var pY = ev.pageY;
ele.style.left = pX + "px";
ele.style.top = pY + "px";
document.addEventListener ("mouseup" , eleMouseUp , false);
function eleMouseUp ()
document.removeEventListener ("mousemove" , eleMouseMove , false);
document.removeEventListener ("mouseup" , eleMouseUp , false);
顺便说一句,我必须将目标的位置设置为绝对位置才能正常工作。
【讨论】:
感谢您的详细回复。我在 mousedown 处于活动状态时使用 Do While 进行 mousemove,否则它不应该运行......如果我启用 Do While 循环,Firefox 会停止。 @Kayote 我明白了,但由于mousemove
事件调用eleMouseMove()
的频率,这不是必需的
我根据自己的要求对其进行了一些更新。它也可以对其他人有所帮助,因此jsfiddle.net/kjwLe9bq分享。
这是很久以前的事了,但值得注意的是(正如最后评论中的代码所示)mouseup 的事件监听器应该添加到eleMouseDown 函数中,而不是添加到eleMouseMove 中;后者称为 lot,您不希望每次用户移动鼠标时都添加 mouseup 侦听器。
避免鼠标初始移动时跳转的版本:jsfiddle.net/fpb7j/308【参考方案2】:
你也可以试试这个小提琴,http://jsfiddle.net/dennisbot/4AH5Z/
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>titulo de mi pagina</title>
<style>
#target
width: 100px;
height: 100px;
background-color: #ffc;
border: 2px solid blue;
position: absolute;
</style>
<script>
window.onload = function()
var el = document.getElementById('target');
var mover = false, x, y, posx, posy, first = true;
el.onmousedown = function()
mover = true;
;
el.onmouseup = function()
mover = false;
first = true;
;
el.onmousemove = function(e)
if (mover)
if (first)
x = e.offsetX;
y = e.offsetY;
first = false;
posx = e.pageX - x;
posy = e.pageY - y;
this.style.left = posx + 'px';
this.style.top = posy + 'px';
;
</script>
</head>
<body>
<div id="target" style="left: 10px; top:20px"></div>
</body>
</html>
【讨论】:
为什么要使用 offsetX/Y? 停止可拖动的跳转到鼠标指针。我明白了。【参考方案3】:我刚刚做了一个简单的拖动。
这是一种单行用法,它处理诸如鼠标到元素左上角的偏移、onDrag/onStop 回调和 SVG 元素拖动等事情
这里是代码。
// simple drag
function sdrag(onDrag, onStop)
var startX = 0;
var startY = 0;
var el = this;
var dragging = false;
function move(e)
el.style.left = (e.pageX - startX ) + 'px';
el.style.top = (e.pageY - startY ) + 'px';
onDrag && onDrag(el, e.pageX, startX, e.pageY, startY);
function startDragging(e)
if (e.currentTarget instanceof HTMLElement || e.currentTarget instanceof SVGElement)
dragging = true;
var left = el.style.left ? parseInt(el.style.left) : 0;
var top = el.style.top ? parseInt(el.style.top) : 0;
startX = e.pageX - left;
startY = e.pageY - top;
window.addEventListener('mousemove', move);
else
throw new Error("Your target must be an html element");
this.addEventListener('mousedown', startDragging);
window.addEventListener('mouseup', function (e)
if (true === dragging)
dragging = false;
window.removeEventListener('mousemove', move);
onStop && onStop(el, e.pageX, startX, e.pageY, startY);
);
Element.prototype.sdrag = sdrag;
并使用它:
document.getElementById('my_target').sdrag();
您还可以使用 onDrag 和 onStop 回调:
document.getElementById('my_target').sdrag(onDrag, onStop);
在此处查看我的存储库以获取更多详细信息: https://github.com/lingtalfi/simpledrag
【讨论】:
【参考方案4】:我就是这样做的
var MOVE =
startX: undefined,
startY: undefined,
item: null
;
function contentDiv(color, width, height)
var result = document.createElement('div');
result.style.width = width + 'px';
result.style.height = height + 'px';
result.style.backgroundColor = color;
return result;
function movable(content)
var outer = document.createElement('div');
var inner = document.createElement('div');
outer.style.position = 'relative';
inner.style.position = 'relative';
inner.style.cursor = 'move';
inner.style.zIndex = 1000;
outer.appendChild(inner);
inner.appendChild(content);
inner.addEventListener('mousedown', function(evt)
MOVE.item = this;
MOVE.startX = evt.pageX;
MOVE.startY = evt.pageY;
)
return outer;
function bodyOnload()
document.getElementById('td1').appendChild(movable(contentDiv('blue', 100, 100)));
document.getElementById('td2').appendChild(movable(contentDiv('red', 100, 100)));
document.addEventListener('mousemove', function(evt)
if (!MOVE.item) return;
if (evt.which!==1) return;
var dx = evt.pageX - MOVE.startX;
var dy = evt.pageY - MOVE.startY;
MOVE.item.parentElement.style.left = dx + 'px';
MOVE.item.parentElement.style.top = dy + 'px';
);
document.addEventListener('mouseup', function(evt)
if (!MOVE.item) return;
var dx = evt.pageX - MOVE.startX;
var dy = evt.pageY - MOVE.startY;
var sty = MOVE.item.style;
sty.left = (parseFloat(sty.left) || 0) + dx + 'px';
sty.top = (parseFloat(sty.top) || 0) + dy + 'px';
MOVE.item.parentElement.style.left = '';
MOVE.item.parentElement.style.top = '';
MOVE.item = null;
MOVE.startX = undefined;
MOVE.startY = undefined;
);
bodyOnload();
table
user-select: none
<table>
<tr>
<td id='td1'></td>
<td id='td2'></td>
</tr>
</table>
拖动时,被拖动元素的parentElement的样式left
和right
不断更新。然后,在 mouseup (='drop') 上,“更改已提交”,可以这么说;我们将父元素的(水平和垂直)位置变化(即左侧和顶部)添加到元素本身的位置,然后再次清除父元素的左侧/顶部。这样,我们只需要用于 pageX、pageY(拖动开始时的鼠标位置)的 JavaScript 变量,而关于拖动开始时的元素位置,我们不需要 JavaScript 变量(只需将该信息保存在 DOM 中)。
如果您正在处理 SVG 元素,则可以使用相同的父/子/提交技术。只需使用两个嵌套的g
,并使用transform=translate(dx,dy)
代替style.left=dx
、style.top=dy
【讨论】:
当然你应该使用 CSS 类而不是内联样式。认为它“又快又脏”。以上是关于简单的拖放代码的主要内容,如果未能解决你的问题,请参考以下文章
为啥这个 Selenium 的拖放 C# 代码在 Chrome 上不起作用?