在拖动开始时捕捉到父网格
Snap to parent grid on start of drag
我是 JavaScript 和 JQuery 的新手,如果我遗漏了一两个技巧,请见谅。
我已经弄清楚如何让 JQuery UI 可拖动对象使用网格选项,并且在页面加载后,"snap to an imaginary grid" 所有可拖动对象都有引用到(在代码注释中解释)。但是,我不知道如何让这种行为发生 .on("dragstart")
。
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="jquery-1.10.2.js"></script>
<script type="text/javascript" src="jquery-ui.js"></script>
<script type="text/javascript" src="dragger.js"></script>
</head>
<body>
<div id="parent">
<svg width="300" height="100" class="draggable" id="number1">
<rect x="0" y="0" rx="10" ry="10" width="300" height="100" style="fill:rgb(121,0,121);stroke-width:3;stroke:rgb(0,0,0);">
</svg>
<svg width="300" height="100" class="draggable" id="letterA">
<rect x="0" y="0" rx="100" ry="10" width="300" height="100" style="fill:rgb(0,121,121);stroke-width:3;stroke:rgb(255,0,0);">
</svg>
</div>
</body>
</html>
注: 两个矩形之间有一个白色的空隙,通过第二个JavaScript下面,一旦块被捕捉到网格,它就会消失。或者,这 2 个矩形应该可以相互拖动并相互对齐,以被视为捕捉到网格上。
JavaScript (dragger.js):
var roundedRemainder = function(numer, denom) {
return numer - (Math.round(numer / denom) * denom);
}
var snapPosition = function(obj, granularity) {
obj.position({
my: "left top", // Unchanging reference point on draggable object
at: "left top", // Unchanging reference point on reference object
of: "#parent", // The object that you want to move items with respect to.
using: function(position, data) {
var newPositions = {
// Get the difference between the "imaginary grid" and the current grid
left: function() {
return roundedRemainder(position.left, granularity);
},
top: function() {
return roundedRemainder(position.top, granularity);
}
}
// Move to the imaginary grid
$(this).css(newPositions);
return newPositions;
}
});
}
$(function() {
var gridSize = 50;
$(".draggable")
// Enable grid usage
.draggable({
grid: [gridSize, gridSize]
})
.on("dragstart", function(event, ui) {
var newPos = snapPosition(ui.helper, gridSize);
})
});
证明 snapPosition
中的代码有效:
var roundedRemainder = function(numer, denom) {
return numer - (Math.round(numer / denom) * denom);
}
$(function() {
var gridSize = 50;
$(".draggable")
// Enable grid usage
.draggable({
grid: [gridSize, gridSize]
})
.position({
my: "left top", // Unchanging reference point on draggable object
at: "left top", // Unchanging reference point on reference object
of: "#parent", // The object that you want to move items with respect to.
using: function(position, data) {
var newPositions = {
// Get the difference between the "imaginary grid" and the current grid
left: function() {
return roundedRemainder(position.left, granularity);
},
top: function() {
return roundedRemainder(position.top, granularity);
}
}
// Move to the imaginary grid
$(this).css(newPositions);
}
})
});
第一个 JavaScript 尝试在拖动开始后更改块的位置,以将其捕捉到假想的网格。第二个在加载页面时自动执行此操作,但不会再执行此操作。例如,如果我要将假想网格的粒度从 50 更改为 79,则拖动不会将对象按需要带回网格。
有没有什么地方可以让我学习如何做到这一点?可行吗?
澄清一下:
- JQuery = 1.10.2(与 JQuery UI 演示相同)
- JQuery UI = 1.11.4(与 JQuery UI 演示相同)
- 浏览器 = Ubuntu 14.04 上的 Firefox,一切都是最新的
我已经经历过 Google,但是类似于 "start"、"drag" 和 "position" 的术语不够独特,无法缩小范围,或者我还没有找到合适的地方。我还搜索了 JQuery (UI) 档案。
非常感谢!
好吧,事实证明有一些代表我无知的例子。我将在下面通过它们来帮助其他人,但如果你只是在寻找解决方案,那就不要再看了:
var roundedRemainder = function(numer, denom) {
if (denom > 1) // Only calculate when there is a chance the draggable isn't on the grid.
return numer - (Math.round(numer / denom) * denom); // Note: denom = 0 is invalid.
else
return 0; // If denom is invalid, or 1, then assume the draggable is on the grid.
}
$(function() {
var gridSize = 79;
var _this = this;
$(".draggable")
.draggable({
// Enable grid constraints
grid: [gridSize, gridSize],
// At start of dragging (aka, only do once at the beginning)
// snap the draggable object onto its parents grid.
drag: function(event, ui) {
var gridOffsetLeft;
var gridOffsetTop;
ui.helper.position({
my: "left top", // For the top left of the draggable object
at: "left top", // Link to the top left of the reference object
of: $(this).parent(), // Make the reference object the parent of the draggable object
// Calculate the grid offset from where the object ORIGINATED from
using: function(position, data) {
gridOffsetLeft = roundedRemainder(position.left, gridSize);
gridOffsetTop = roundedRemainder(position.top, gridSize);
}
});
// Calculate the total offset based off of the current
// location of the draggable object, and the previously
// calculated offset.
gridOffsetLeft -= roundedRemainder(ui.position.left, gridSize);
gridOffsetTop -= roundedRemainder(ui.position.top, gridSize);
// Apply offsets & hence snap the draggable onto the
// parents grid.
ui.position.left += gridOffsetLeft;
ui.position.top += gridOffsetTop;
}
})
});
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="jquery-1.10.2.js"></script>
<script type="text/javascript" src="jquery-ui.js"></script>
<script type="text/javascript" src="dragger.js"></script>
</head>
<body>
<div id="parent">
<svg width="300" height="100" class="draggable" id="number1">
<rect x="0" y="0" rx="10" ry="10" width="300" height="100" style="fill:rgb(121,0,121);stroke-width:3;stroke:rgb(0,0,0);">
</svg>
<svg width="300" height="100" class="draggable" id="letterA">
<rect x="0" y="0" rx="100" ry="10" width="300" height="100" style="fill:rgb(0,121,121);stroke-width:3;stroke:rgb(255,0,0);">
</svg>
</div>
</body>
</html>
错误:
- 第一个错误是我试图将定位功能与拖动功能分开的方式。具体来说,当试图发送
then
过来时。我还没有真正理解这一点,这就是为什么它不在解决方案中的原因,但是我确实阅读了(并丢失了 link)堆栈溢出,其中提到使用 var _then = then;
或使用绑定方法.如果我找到 link 我会编辑答案。
- 下一个错误与我的 "at start" 规格有关。我想要的方法是仅在每次拖动开始时捕捉到父网格。因此,根据文档,使用
start:
或 .on("dragstart", ...)
功能听起来合乎逻辑。这导致 preventDefault
问题,即启动命令被忽略,因此没有捕捉,但我可以拖动,或者如果我在开始开始时使用 event.preventDefault
,它会捕捉但不再拖动。原来 drag:
功能仅在拖动开始时 运行s 一次(如果我错了请纠正我)。通过将捕捉功能放回原处,解决了另一个错误。
- 最后,我原来捕捉到网格的逻辑是错误的。它只使用一次时有效,但一旦每次拖动对象时它都是 运行,每次拖动都会 "creep" 一点点。这是因为 "snap" 功能从拖动对象的 ORIGINAL 位置到父对象起作用。因此,每次都添加差异,即使对象已经捕捉,也会导致错误。为了解决这个问题,我只是将对象的 original 位置与 current 位置的差异,以及以 为中心的相同网格对象的原始位置。
(要清楚,有3个参考位置,parent,被拖动对象的original位置,以及当前拖动对象的位置)。
我是 JavaScript 和 JQuery 的新手,如果我遗漏了一两个技巧,请见谅。
我已经弄清楚如何让 JQuery UI 可拖动对象使用网格选项,并且在页面加载后,"snap to an imaginary grid" 所有可拖动对象都有引用到(在代码注释中解释)。但是,我不知道如何让这种行为发生 .on("dragstart")
。
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="jquery-1.10.2.js"></script>
<script type="text/javascript" src="jquery-ui.js"></script>
<script type="text/javascript" src="dragger.js"></script>
</head>
<body>
<div id="parent">
<svg width="300" height="100" class="draggable" id="number1">
<rect x="0" y="0" rx="10" ry="10" width="300" height="100" style="fill:rgb(121,0,121);stroke-width:3;stroke:rgb(0,0,0);">
</svg>
<svg width="300" height="100" class="draggable" id="letterA">
<rect x="0" y="0" rx="100" ry="10" width="300" height="100" style="fill:rgb(0,121,121);stroke-width:3;stroke:rgb(255,0,0);">
</svg>
</div>
</body>
</html>
注: 两个矩形之间有一个白色的空隙,通过第二个JavaScript下面,一旦块被捕捉到网格,它就会消失。或者,这 2 个矩形应该可以相互拖动并相互对齐,以被视为捕捉到网格上。
JavaScript (dragger.js):
var roundedRemainder = function(numer, denom) {
return numer - (Math.round(numer / denom) * denom);
}
var snapPosition = function(obj, granularity) {
obj.position({
my: "left top", // Unchanging reference point on draggable object
at: "left top", // Unchanging reference point on reference object
of: "#parent", // The object that you want to move items with respect to.
using: function(position, data) {
var newPositions = {
// Get the difference between the "imaginary grid" and the current grid
left: function() {
return roundedRemainder(position.left, granularity);
},
top: function() {
return roundedRemainder(position.top, granularity);
}
}
// Move to the imaginary grid
$(this).css(newPositions);
return newPositions;
}
});
}
$(function() {
var gridSize = 50;
$(".draggable")
// Enable grid usage
.draggable({
grid: [gridSize, gridSize]
})
.on("dragstart", function(event, ui) {
var newPos = snapPosition(ui.helper, gridSize);
})
});
证明 snapPosition
中的代码有效:
var roundedRemainder = function(numer, denom) {
return numer - (Math.round(numer / denom) * denom);
}
$(function() {
var gridSize = 50;
$(".draggable")
// Enable grid usage
.draggable({
grid: [gridSize, gridSize]
})
.position({
my: "left top", // Unchanging reference point on draggable object
at: "left top", // Unchanging reference point on reference object
of: "#parent", // The object that you want to move items with respect to.
using: function(position, data) {
var newPositions = {
// Get the difference between the "imaginary grid" and the current grid
left: function() {
return roundedRemainder(position.left, granularity);
},
top: function() {
return roundedRemainder(position.top, granularity);
}
}
// Move to the imaginary grid
$(this).css(newPositions);
}
})
});
第一个 JavaScript 尝试在拖动开始后更改块的位置,以将其捕捉到假想的网格。第二个在加载页面时自动执行此操作,但不会再执行此操作。例如,如果我要将假想网格的粒度从 50 更改为 79,则拖动不会将对象按需要带回网格。
有没有什么地方可以让我学习如何做到这一点?可行吗?
澄清一下:
- JQuery = 1.10.2(与 JQuery UI 演示相同)
- JQuery UI = 1.11.4(与 JQuery UI 演示相同)
- 浏览器 = Ubuntu 14.04 上的 Firefox,一切都是最新的
我已经经历过 Google,但是类似于 "start"、"drag" 和 "position" 的术语不够独特,无法缩小范围,或者我还没有找到合适的地方。我还搜索了 JQuery (UI) 档案。
非常感谢!
好吧,事实证明有一些代表我无知的例子。我将在下面通过它们来帮助其他人,但如果你只是在寻找解决方案,那就不要再看了:
var roundedRemainder = function(numer, denom) {
if (denom > 1) // Only calculate when there is a chance the draggable isn't on the grid.
return numer - (Math.round(numer / denom) * denom); // Note: denom = 0 is invalid.
else
return 0; // If denom is invalid, or 1, then assume the draggable is on the grid.
}
$(function() {
var gridSize = 79;
var _this = this;
$(".draggable")
.draggable({
// Enable grid constraints
grid: [gridSize, gridSize],
// At start of dragging (aka, only do once at the beginning)
// snap the draggable object onto its parents grid.
drag: function(event, ui) {
var gridOffsetLeft;
var gridOffsetTop;
ui.helper.position({
my: "left top", // For the top left of the draggable object
at: "left top", // Link to the top left of the reference object
of: $(this).parent(), // Make the reference object the parent of the draggable object
// Calculate the grid offset from where the object ORIGINATED from
using: function(position, data) {
gridOffsetLeft = roundedRemainder(position.left, gridSize);
gridOffsetTop = roundedRemainder(position.top, gridSize);
}
});
// Calculate the total offset based off of the current
// location of the draggable object, and the previously
// calculated offset.
gridOffsetLeft -= roundedRemainder(ui.position.left, gridSize);
gridOffsetTop -= roundedRemainder(ui.position.top, gridSize);
// Apply offsets & hence snap the draggable onto the
// parents grid.
ui.position.left += gridOffsetLeft;
ui.position.top += gridOffsetTop;
}
})
});
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="jquery-1.10.2.js"></script>
<script type="text/javascript" src="jquery-ui.js"></script>
<script type="text/javascript" src="dragger.js"></script>
</head>
<body>
<div id="parent">
<svg width="300" height="100" class="draggable" id="number1">
<rect x="0" y="0" rx="10" ry="10" width="300" height="100" style="fill:rgb(121,0,121);stroke-width:3;stroke:rgb(0,0,0);">
</svg>
<svg width="300" height="100" class="draggable" id="letterA">
<rect x="0" y="0" rx="100" ry="10" width="300" height="100" style="fill:rgb(0,121,121);stroke-width:3;stroke:rgb(255,0,0);">
</svg>
</div>
</body>
</html>
错误:
- 第一个错误是我试图将定位功能与拖动功能分开的方式。具体来说,当试图发送
then
过来时。我还没有真正理解这一点,这就是为什么它不在解决方案中的原因,但是我确实阅读了(并丢失了 link)堆栈溢出,其中提到使用var _then = then;
或使用绑定方法.如果我找到 link 我会编辑答案。 - 下一个错误与我的 "at start" 规格有关。我想要的方法是仅在每次拖动开始时捕捉到父网格。因此,根据文档,使用
start:
或.on("dragstart", ...)
功能听起来合乎逻辑。这导致preventDefault
问题,即启动命令被忽略,因此没有捕捉,但我可以拖动,或者如果我在开始开始时使用event.preventDefault
,它会捕捉但不再拖动。原来drag:
功能仅在拖动开始时 运行s 一次(如果我错了请纠正我)。通过将捕捉功能放回原处,解决了另一个错误。 - 最后,我原来捕捉到网格的逻辑是错误的。它只使用一次时有效,但一旦每次拖动对象时它都是 运行,每次拖动都会 "creep" 一点点。这是因为 "snap" 功能从拖动对象的 ORIGINAL 位置到父对象起作用。因此,每次都添加差异,即使对象已经捕捉,也会导致错误。为了解决这个问题,我只是将对象的 original 位置与 current 位置的差异,以及以 为中心的相同网格对象的原始位置。
(要清楚,有3个参考位置,parent,被拖动对象的original位置,以及当前拖动对象的位置)。