Javascript JQuery Draggable-防止网格对象位于同一位置
我使用jquerydraggable在网格上移动项目。对象捕捉到32x32栅格区域。如果对象处于相同位置,我希望能够取消栅格捕捉 不能取消拖动,只能阻止它进入正方形。阻止并移回前一位置后,如果用户继续拖动到新的未占用网格位置,则必须捕捉到该位置 我已经创建了一个演示,用于上面解释的目的,但是当它试图进入新位置时,图像会出现小故障,但随后被取消回到旧位置 这是小提琴中的代码:Javascript JQuery Draggable-防止网格对象位于同一位置,javascript,jquery,jquery-ui,jquery-draggable,Javascript,Jquery,Jquery Ui,Jquery Draggable,我使用jquerydraggable在网格上移动项目。对象捕捉到32x32栅格区域。如果对象处于相同位置,我希望能够取消栅格捕捉 不能取消拖动,只能阻止它进入正方形。阻止并移回前一位置后,如果用户继续拖动到新的未占用网格位置,则必须捕捉到该位置 我已经创建了一个演示,用于上面解释的目的,但是当它试图进入新位置时,图像会出现小故障,但随后被取消回到旧位置 这是小提琴中的代码: <div class="drop-target"> <div class="dr
<div class="drop-target">
<div class="drag-item" object-id="0"></div>
<div class="drag-item" style="left: 32px;" object-id="1"></div>
</div>
var objects = [
[0, 0],
[1, 1]
];
$(function() {
$(".drag-item").draggable({
grid: [ 32, 32 ],
containment: '.drop-target',
drag: function (event, obj){
let objectId = $(this).attr('object-id');
var objectPositionX = $(this).position().left / 32;
var objectPositionY = $(this).position().top / 32;
var previousPositionX = Math.floor(objects[objectId][0]);
var previousPositionY = Math.floor(objects[objectId][1]);
if (objectPositionX != previousPositionX || objectPositionY != previousPositionY) {
if(!isObjectInPosition(objects, [objectPositionX, objectPositionY])) {
objects[objectId] = [objectPositionX, objectPositionY];
} else {
obj.position.left = previousPositionX * 32;
obj.position.top = previousPositionY * 32;
}
}
}
});
});
function isObjectInPosition(arrayToSearch, positionToFind)
{
for (let i = 0; i < arrayToSearch.length; i++) {
if (arrayToSearch[i][0] == positionToFind[0]
&& arrayToSearch[i][1] == positionToFind[1]) {
return true;
}
}
return false;
}
.drag-item {
background-image: url("http://i.imgur.com/lBIWrWw.png");
background-size: 32px auto;
width: 32px;
height: 32px;
cursor: move;
}
.drop-target {
background: whitesmoke url("http://i.imgur.com/uUvTRLx.png") repeat scroll 0 0 / 32px 32px;
border: 1px dashed orange;
height: 736px;
left: 0;
position: absolute;
top: 0;
width: 736px;
}
HTML:
<div class="drop-target">
<div class="drag-item" object-id="0"></div>
<div class="drag-item" style="left: 32px;" object-id="1"></div>
</div>
var objects = [
[0, 0],
[1, 1]
];
$(function() {
$(".drag-item").draggable({
grid: [ 32, 32 ],
containment: '.drop-target',
drag: function (event, obj){
let objectId = $(this).attr('object-id');
var objectPositionX = $(this).position().left / 32;
var objectPositionY = $(this).position().top / 32;
var previousPositionX = Math.floor(objects[objectId][0]);
var previousPositionY = Math.floor(objects[objectId][1]);
if (objectPositionX != previousPositionX || objectPositionY != previousPositionY) {
if(!isObjectInPosition(objects, [objectPositionX, objectPositionY])) {
objects[objectId] = [objectPositionX, objectPositionY];
} else {
obj.position.left = previousPositionX * 32;
obj.position.top = previousPositionY * 32;
}
}
}
});
});
function isObjectInPosition(arrayToSearch, positionToFind)
{
for (let i = 0; i < arrayToSearch.length; i++) {
if (arrayToSearch[i][0] == positionToFind[0]
&& arrayToSearch[i][1] == positionToFind[1]) {
return true;
}
}
return false;
}
.drag-item {
background-image: url("http://i.imgur.com/lBIWrWw.png");
background-size: 32px auto;
width: 32px;
height: 32px;
cursor: move;
}
.drop-target {
background: whitesmoke url("http://i.imgur.com/uUvTRLx.png") repeat scroll 0 0 / 32px 32px;
border: 1px dashed orange;
height: 736px;
left: 0;
position: absolute;
top: 0;
width: 736px;
}
谢谢,非常感谢您的帮助
托比。如果您愿意修改draggable本身,我认为这将使逻辑更易于应用。一旦触发拖动事件,您可以执行很多操作,但是如果您修改Dragable的\u generatePosition方法,您将拥有更多的控制权。一开始看起来可能更复杂,但对于这种行为,有时更容易操作 基本上,您可以在应用网格和安全壳检查后运行isInPosition功能。通常下一步是设置新位置,但如果isInPosition返回true,则会阻止拖动。大概是这样的:
'use strict'
// This is the function generating the position by calculating
// mouse position, different offsets and option.
$.ui.draggable.prototype._generatePosition = function(event, constrainPosition) {
var containment, co, top, left,
o = this.options,
scrollIsRootNode = this._isRootNode(this.scrollParent[0]),
pageX = event.pageX,
pageY = event.pageY;
// Cache the scroll
if (!scrollIsRootNode || !this.offset.scroll) {
this.offset.scroll = {
top: this.scrollParent.scrollTop(),
left: this.scrollParent.scrollLeft()
};
}
/*
* - Position constraining -
* Constrain the position to a mix of grid, containment.
*/
// If we are not dragging yet, we won't check for options
if (constrainPosition) {
if (this.containment) {
if (this.relativeContainer) {
co = this.relativeContainer.offset();
containment = [
this.containment[0] + co.left,
this.containment[1] + co.top,
this.containment[2] + co.left,
this.containment[3] + co.top
];
} else {
containment = this.containment;
}
if (event.pageX - this.offset.click.left < containment[0]) {
pageX = containment[0] + this.offset.click.left;
}
if (event.pageY - this.offset.click.top < containment[1]) {
pageY = containment[1] + this.offset.click.top;
}
if (event.pageX - this.offset.click.left > containment[2]) {
pageX = containment[2] + this.offset.click.left;
}
if (event.pageY - this.offset.click.top > containment[3]) {
pageY = containment[3] + this.offset.click.top;
}
}
if (o.grid) {
//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
}
if (o.axis === "y") {
pageX = this.originalPageX;
}
if (o.axis === "x") {
pageY = this.originalPageY;
}
}
// This is the only part added to the original function.
// You have access to the updated position after it's been
// updated through containment and grid, but before the
// element is modified.
// If there's an object in position, you prevent dragging.
if (isObjectInPosition(objects, [pageX - this.offset.click.left - this.offset.parent.left, pageY - this.offset.click.top - this.offset.parent.top])) {
return false;
}
return {
top: (
pageY - // The absolute mouse position
this.offset.click.top - // Click offset (relative to the element)
this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
(this.cssPosition === "fixed" ? -this.offset.scroll.top : (scrollIsRootNode ? 0 : this.offset.scroll.top))
),
left: (
pageX - // The absolute mouse position
this.offset.click.left - // Click offset (relative to the element)
this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
(this.cssPosition === "fixed" ? -this.offset.scroll.left : (scrollIsRootNode ? 0 : this.offset.scroll.left))
)
};
}
var objects = [
[0, 0],
[1, 1]
];
$(function() {
$(".drag-item").draggable({
grid: [32, 32],
containment: '.drop-target',
// on start you remove coordinate of dragged item
// else it'll check its own coordinates
start: function(event, obj) {
var objectId = $(this).attr('object-id');
objects[objectId] = [null, null];
},
// on stop you update your array
stop: function(event, obj) {
var objectId = $(this).attr('object-id');
var objectPositionX = $(this).position().left / 32;
var objectPositionY = $(this).position().top / 32;
objects[objectId] = [objectPositionX, objectPositionY];
}
});
});
function isObjectInPosition(arrayToSearch, positionToFind) {
for (let i = 0; i < arrayToSearch.length; i++) {
if (arrayToSearch[i][0] === (positionToFind[0] / 32) && arrayToSearch[i][1] === (positionToFind[1] / 32)) {
return true;
}
}
return false;
}
“严格使用”
//这是通过计算生成位置的函数
//鼠标位置、不同的偏移和选项。
$.ui.draggable.prototype._generatePosition=函数(事件、位置){
var安全壳,co,顶部,左侧,
o=此选项,
scrollIsRootNode=this.\u isRootNode(this.scrollParent[0]),
pageX=event.pageX,
pageY=event.pageY;
//缓存滚动条
如果(!scrollIsRootNode | |!this.offset.scroll){
this.offset.scroll={
top:this.scrollParent.scrollTop(),
左:this.scrollParent.scrollLeft()
};
}
/*
*-位置约束-
*将该位置约束为栅格、安全壳的混合。
*/
//如果我们还没有拖动,我们将不会检查选项
如果(约束位置){
如果(本安全壳){
if(此相对容器){
co=this.relativeContainer.offset();
遏制=[
这个.安全壳[0]+一氧化碳左,
本安全壳[1]+co.top,
这是安全壳[2]+一氧化碳左,
这是安全壳[3]+co.top
];
}否则{
遏制=这是遏制;
}
if(event.pageX-this.offset.click.leftcontainment[2]){
pageX=包容[2]+this.offset.click.left;
}
if(event.pageY-this.offset.click.top>containment[3]){
pageY=包容[3]+this.offset.click.top;
}
}
if(o.grid){
//检查网格元素是否设置为0,以防止被0除的错误导致IE中的无效参数错误(请参阅票据#6950)
top=o.grid[1]?this.originalpage+Math.round((pageY-this.originalpage)/o.grid[1])*o.grid[1]:this.originalpage;
pageY=安全壳?((top-this.offset.click.top>=安全壳[1]| top-this.offset.click.top>安全壳[3])?top:((top-this.offset.click.top>=安全壳[1])?top-o.grid[1]:top+o.grid[1]):top;
left=o.grid[0]?this.originalPageX+Math.round((pageX-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX;
pageX=包容?((left-this.offset.click.left>=包容[0]| | left-this.offset.click.left>包容[2])?left:((left-this.offset.click.left>=包容[0])?left-o.grid[0]:left+o.grid[0]):left;
}
如果(o轴==“y”){
pageX=this.originalPageX;
}
如果(o轴==“x”){
pageY=此。原始页面;
}
}
//这是唯一添加到原始函数的部分。
//更新后的职位被删除后,您可以访问该职位
//通过安全壳和网格更新,但在
//元素被修改。
//如果位置上有对象,则可以防止拖动。
if(isObjectInPosition(对象[pageX-this.offset.click.left-this.offset.parent.left,pageY-this.offset.click.top-this.offset.parent.top])){
返回false;
}
返回{
顶部:(
pageY-//鼠标的绝对位置
this.offset.click.top-//单击偏移(相对于元素)
this.offset.relative.top-//仅适用于相对定位的节点:从元素到偏移父节点的相对偏移
this.offset.parent.top+//offsetParent的无边框偏移(offset+border)
(this.cssposposition==“fixed”?-this.offset.scroll.top:(scrollIsRootNode?0:this.offset.scroll.top))
),
左:(
pageX-//鼠标的绝对位置
this.offset.click.left-//单击偏移(相对于元素)
this.offset.relative.left-//仅适用于相对定位的节点:从元素到偏移父节点的相对偏移
this.offset.parent.left+//offsetParent的无边框偏移(offset+border)
(this.cssposposition==“fixed”?-this.offset.scroll.left:(scrollIsRootNode?0:this.offset.scroll.left))
)
};
}
变量对象=[
[0, 0],
[1, 1]
];
$(函数(){
$(“.drag项”).draggable({
网格:[32,32],
包含:'.drop目标',
//开始时,删除拖动项目的坐标
//否则它会检查自己的坐标
启动:功能(事件,obj){
var objectId=$(this.attr('object-id');
objects[objectId]=[null,null];
},
//停止时更新阵列
停止:功能(事件,obj){
var objectId=$(this.attr('object-id');