在可拖动元素上模拟3像素拖动 [英] simulate a 3 pixel drag on draggable elem
问题描述
我只是想在可拖动的div元素上模拟一次单击并拖动-我在SO上找到了几个类似的问题,但都涉及使用其他插件...
I am simply trying to simulate a small click and drag on a draggable div elem — I've found several similar questions here on SO but all involving the use of additional plugins...
是否有普通的JavaScript或jQuery功能专门处理拖动?据我所知.click();
或按下鼠标可以启动.
Is there a plain JavaScript or jQuery ability to handle specifically the drag? as I know .click();
or mouse down can be called to initiate.
我并没有尝试创建拖放功能,我已经拥有了.我正在尝试创建一个小的函数来自动模拟此事件. 点击>按住>向上拖动3个像素
I am not trying to create the ability of a drag and drop, I already have that. I am trying to create a small function that simulates this event automatically. click > hold > drag up 3 pixels
更新:在不使用第三方库的情况下,无法在SO或其他地方找到与此有关的任何内容,因此在其上创建了500个赏金.当然可以.
Update: Cannot find anything about this on SO or elsewhere without using a third party library, so creating a 500 bounty on it. Surely it's possible.
推荐答案
您可以使用 MouseEvent
界面,并使用 DragEvent
接口.您必须使用 EventTarget.dispatchEvent()
触发正确的顺序
You can simulate mouse events using MouseEvent
interface and drag events using the DragEvent
interface. You have to trigger the right sequence using EventTarget.dispatchEvent()
.
我想您结合了"HTML拖放API" 与鼠标事件" 以创建拖放行为,因此,我将提供一个模拟 Drag&放下,然后放一个来模拟鼠标捕获和鼠标移动.
I guess that you combine "HTML Drag and Drop API" with "Mouse events" to create a drag and drop behaviour, so I'll provide one to simulate Drag & Drop and one to simulate Mouse capture and Mouse move.
请阅读内嵌评论
// 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元素是可拖动的,并且在不运行模拟计时器时可以单击并拖动它.单击模拟按钮以查看实际的模拟:
Run the code snippet. The square div element is draggable and you can click and drag it when the simulation timer is not running. Click the simulate button to see the simulation in action:
// 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);
运行代码段,然后单击模拟"按钮以触发拖动n放下事件序列:
Run the code snippet and hit the simulate button to trigger the drag n drop events sequence:
// 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>
这篇关于在可拖动元素上模拟3像素拖动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!