我只是想在可拖动的div元素上模拟一次单击并拖动—我在SO上找到了几个类似的问题,但都涉及使用其他插件...
是否有普通的JavaScript或jQuery功能专门处理拖动?据我所知.click();
或按下鼠标可以启动。
我没有尝试创建拖放功能,我已经拥有了。我正在尝试创建一个小的函数来自动模拟此事件。 点击>按住>向上拖动3个像素
更新:在未使用第三方库的情况下,无法在SO或其他地方找到任何与此相关的信息,因此在其上创建了500个赏金。当然可以。
答案 0 :(得分:11)
您可以使用MouseEvent
界面模拟鼠标事件,并使用DragEvent
界面拖动事件。您必须使用EventTarget.dispatchEvent()
触发正确的顺序。
我猜您将"HTML Drag and Drop API"与"Mouse events"结合在一起以创建拖放行为,所以我将提供一个模拟 Drag&Drop 和一个模拟< em>鼠标捕获和鼠标移动。
请阅读内嵌评论
// We create 3 mouse events using MouseEvent interface,
// one for mousedown to initiate the process,
// one for mousemove to handle to movement
// and one for mouseup to terminate the process
const mouseDownEvent = new MouseEvent('mousedown', {
clientX: element.getBoundingClientRect().left,
clientY: element.getBoundingClientRect().top,
bubbles: true,
cancelable: true
});
const mouseMoveEvent = new MouseEvent('mousemove', {
clientX: element.getBoundingClientRect().left + 3,
clientY: element.getBoundingClientRect().top,
bubbles: true,
cancelable: true
});
const mouseUpEvent = new MouseEvent('mouseup', {
bubbles: true,
cancelable: true
});
// Dispatch the mousedown event to the element that has the listener
element.dispatchEvent(mouseDownEvent);
// For mousemove, the listener may be the parent or even the document
<element|document>.dispatchEvent(mouseMoveEvent);
// Dispatch mouseup to terminate the process
element.dispatchEvent(mouseUpEvent);
运行代码段。 square div元素是可拖动的,并且在不运行模拟计时器时可以单击并拖动它。单击模拟按钮以查看实际的模拟:
// Timer ID holder
let linearSimulationTimer;
// Simulation X/Y calculation
let calcX = 0, calcY = 0;
// Simulation X/Y axis orientation to handle parent collisions
let xAxisOrientation = 1, yAxisOrientation = 1;
// How many pixels to move the element for X/Y axis
const pixelsShift = 3;
// Elements
const simulateButton = document.getElementById('simulate-dnm');
const movable = document.getElementById('movable');
const movableContainer = movable.parentNode;
simulateButton.addEventListener('click', function() {
// If there is a timer running
if (linearSimulationTimer) {
// Stop and clear the timer
clearInterval(linearSimulationTimer);
linearSimulationTimer = null;
// Create a simple mouseup event with no custom properties
const mouseUpEvent = new MouseEvent('mouseup', {
bubbles: true,
cancelable: true,
});
// Dispatch it to the movable element
movable.dispatchEvent(mouseUpEvent);
// Handle button label text (start/stop)
simulateButton.classList.remove('running');
// Else if there is no timer running
} else {
// Create the mousedown event using movable element client left/top for event clientX.clientY
const mouseDownEvent = new MouseEvent('mousedown', {
clientX: movable.getBoundingClientRect().left,
clientY: movable.getBoundingClientRect().top,
pageX: 0,
pageY: 0,
bubbles: true,
cancelable: true,
view: window
});
// Dispatch the mousedown event to the movable element
movable.dispatchEvent(mouseDownEvent);
// Get movable parent client rect
const parentRect = movable.parentNode.getBoundingClientRect();
// Start the simulation timer
linearSimulationTimer = setInterval(() => {
// Get movable element size
const { width, height } = movable.getBoundingClientRect();
// Calculate new X/Y position and orientation
calcX += pixelsShift * xAxisOrientation;
calcY += pixelsShift * yAxisOrientation;
// If we hit movable parent X axis bounds, reverse X axis
if (calcX + width > parentRect.width) {
calcX = parentRect.width - width;
xAxisOrientation = -xAxisOrientation;
} else if (calcX < 0) {
calcX = 0;
xAxisOrientation = -xAxisOrientation;
}
// If we hit movable parent Y axis bounds, reverse Y axis
if (calcY + height > parentRect.height) {
calcY = parentRect.height - height;
yAxisOrientation = -yAxisOrientation;
} else if (calcY < 0) {
calcY = 0;
yAxisOrientation = -yAxisOrientation;
}
// Create mousemove event using calcX/calcY and the parent client position
const mouseMoveEvent = new MouseEvent('mousemove', {
clientX: parentRect.left + calcX,
clientY: parentRect.top + calcY,
pageX: 0,
pageY: 0,
bubbles: true,
cancelable: true,
view: window
});
// Dispatch the mousemove event to the parent which it has the listener
movableContainer.dispatchEvent(mouseMoveEvent);
}, 50);
// Handle button label text (start/stop)
simulateButton.classList.add('running');
}
});
// Mouse capture and drag handler (https://javascript.info/mouse-drag-and-drop)
movable.onmousedown = function(event) {
let shiftX = event.clientX - movable.getBoundingClientRect().left;
let shiftY = event.clientY - movable.getBoundingClientRect().top;
moveAt(event.pageX, event.pageY);
function moveAt(pageX, pageY) {
movable.style.left = pageX - shiftX - movableContainer.offsetLeft + 'px';
movable.style.top = pageY - shiftY - movableContainer.offsetTop + 'px';
}
function onMouseMove(event) {
moveAt(event.pageX, event.pageY);
}
movableContainer.addEventListener('mousemove', onMouseMove);
movable.onmouseup = function() {
movableContainer.removeEventListener('mousemove', onMouseMove);
movable.onmouseup = null;
}
}
movable.ondragstart = function() {
return false;
}
#movable-container {
position: relative;
height: 80px;
width: 200px;
margin: auto;
margin-bottom: 20px;
border: 1px dotted silver;
}
#movable {
position: relative;
left: 0;
width: 30px;
height: 30px;
background-color: cornflowerblue;
border-radius: 5px;
border: 1px solid grey;
}
#simulate-dnm > span:before {
content: 'Start ';
}
#simulate-dnm.running > span:before {
content: 'Stop ';
}
<div id="movable-container">
<div id="movable"></div>
</div>
<div>
<button id="simulate-dnm"><span>Mouse capture & move simulation</span></button>
</div>
请阅读内嵌评论
// We create 3 drag events using DragEvent interface,
// one for dragstart to initiate the process,
// one for drop to handle the drag element drop inside the drop container
// and one for dragend to terminate the process
const dragStartEvent = new DragEvent('dragstart', {
bubbles: true,
cancelable: true
});
const dragEndEvent = new DragEvent('dragend', {
bubbles: true,
cancelable: true
});
const dropEvent = new DragEvent('drop', {
bubbles: true,
cancelable: true
});
// Dispatch the dragstart event to the source element to initiate
sourceNode.dispatchEvent(dragStartEvent);
// Dispatch the drop event to the destination element to get the drag
destinationNode.dispatchEvent(dropEvent);
// Dispatch the dragend event to the source element to finish
sourceNode.dispatchEvent(dragEndEvent);
运行代码段,然后单击“模拟”按钮以触发拖放事件序列:
// The current parent index that the drag element is inside
let currentParentIndex = 0;
// Elements
const simulateButton = document.getElementById('simulate-dnd');
const sourceNode = document.getElementById('drag');
function simulateDragDrop(sourceNode, destinationNode) {
// Create dragstart event
const dragStartEvent = new DragEvent('dragstart', {
bubbles: true,
cancelable: true
});
// Create dragend event
const dragEndEvent = new DragEvent('dragend', {
bubbles: true,
cancelable: true
});
// Create drop event
const dropEvent = new DragEvent('drop', {
bubbles: true,
cancelable: true
});
// Dispatch dragstart event to the draggable element
sourceNode.dispatchEvent(dragStartEvent);
// Dispatch drop event to container element we want to drop the draggable
destinationNode.dispatchEvent(dropEvent);
// Dispatch dragend event to the draggable element
sourceNode.dispatchEvent(dragEndEvent);
}
simulateButton.addEventListener('click', function() {
// Change drop container index to other container than the current
const newParentIndex = currentParentIndex === 0 ? 1 : 0;
// Get the drop container element
const destinationNode = document.getElementsByClassName('dropzone')[newParentIndex];
// Initiate simulation sequence
simulateDragDrop(sourceNode, destinationNode);
// Save the new container index
currentParentIndex = newParentIndex;
});
// Drag n Drop handling
let dragged;
document.addEventListener("dragstart", function(event) {
// store a ref. on the dragged elem
dragged = event.target;
// make it half transparent
event.target.style.opacity = .5;
}, false);
document.addEventListener("dragend", function(event) {
// reset the transparency
event.target.style.opacity = "";
}, false);
/* events fired on the drop targets */
document.addEventListener("dragover", function(event) {
// prevent default to allow drop
event.preventDefault();
}, false);
document.addEventListener("dragenter", function(event) {
// highlight potential drop target when the draggable element enters it
if (event.target.className == "dropzone") {
event.target.style.background = "yellow";
}
}, false);
document.addEventListener("dragleave", function(event) {
// reset background of potential drop target when the draggable element leaves it
if (event.target.className == "dropzone") {
event.target.style.background = "";
}
}, false);
document.addEventListener("drop", function(event) {
// prevent default action (open as link for some elements)
event.preventDefault();
// move dragged elem to the selected drop target
if (event.target.className == "dropzone") {
event.target.style.background = "";
dragged.parentNode.removeChild(dragged);
event.target.appendChild(dragged);
currentParentIndex = Array.prototype.indexOf.call(event.target.parentNode.children, event.target);
}
}, false);
.dropzones {
display: flex;
justify-content: space-evenly;
}
.dropzone {
width: 100px;
height: 100px;
background-color: mintcream;
border-radius: 5px;
border: 2px dashed darkgrey;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 10px;
}
#drag {
margin: unset;
width: 40px;
height: 40px;
background-color: coral;
border-radius: 4px;
border: 1px solid grey;
}
<div class="dropzones">
<div class="dropzone">
<div id="drag" draggable="true"></div>
</div>
<div class="dropzone"></div>
</div>
<div>
<button id="simulate-dnd">Simulate Drag & Drop</button>
</div>
答案 1 :(得分:3)
如果您是说“模拟拖动”,则触发一个mousedown事件,然后更新元素的位置,您应该可以执行以下操作:
let element = document.getElementById('draggable-div');
element.dispatchEvent(new Event('mousedown'));
element.style.top += 3
根据元素的位置(绝对,相对,粘性),style.top
的更改可能会也可能不会移动元素。
如果您有尝试触发的拖放库。然后,您甚至可以通过简单地将元素移动到放置区域(向上3像素)然后将鼠标向上触发来模拟拖动:
let element = document.getElementById('draggable-div');
element.style.top += 3
element.dispatchEvent(new Event('mouseup'));
该列表继续存在,因为现在还存在拖动事件(尽管尚未被所有浏览器完全支持它们:https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API)。
但是从您的问题中尚不清楚您要进行哪种模拟。