如何将多个 div 设置为特定目标位置的动画?
Posted
技术标签:
【中文标题】如何将多个 div 设置为特定目标位置的动画?【英文标题】:How to animate multiple divs to specific target location? 【发布时间】:2013-05-12 13:26:02 【问题描述】:我在使用 jQuery animate 为某些 div 设置位置的函数时遇到了一些问题。我用 jQuery 做了一个测验,并希望正确的“已回答”具有数字 id 的可拖动 div 自动转到具有相同 id 的目标位置 div。这是用于导航(每次只显示 12 个问题)。
html 看起来像这样
<div id="container"> //floats left
<div class="answer" id="1"></div> //droppables
<div class="answer" id="2"></div>
<div class="answer" id="3"></div>
<div class="answer" id="4"></div>
<div class="answer" id="5"></div>
<div class="answer" id="6"></div>
<div class="answer" id="7"></div>
<div class="answer" id="8"></div>
<div class="answer" id="9"></div>
<div class="answer" id="10"></div>
<div class="answer" id="11"></div>
<div class="answer" id="12"></div>
</div>
<div id="container>
<div class="drag" id="3"></div> //draggables are in random order
<div class="drag" id="1"></div>
<div class="drag" id="2"></div>
<div class="drag" id="6"></div>
<div class="drag" id="5"></div>
<div class="drag" id="12"></div>
<div class="drag" id="4"></div>
<div class="drag" id="8"></div>
<div class="drag" id="7"></div>
<div class="drag" id="11"></div>
<div class="drag" id="9"></div>
<div class="drag" id="10"></div>
</div>
每次有人将右边的可拖动对象放在右边的可放置对象上时,id 都会存储在一个名为 rightIds
的数组中。
假设 rightIds 是 array(0=>3, 1=>7 2=>9)
我还有一个名为 currentIds
的数组,其中包含现在显示的 ID。
currentIds
现在是 array(0=>1 to 11=>12)
我做了这个函数:
function resetAnimation(currentIds, rightIds)
$.each(currentIds, function (index, value)
$.each(rightIds, function(ind, val)
console.log('currentIds value: ' + value);
console.log('rightIds val: ' + val);
if (val == value)
var target = $('#' + value + '.answer');
console.log(target);
var targetTop = target.offset().top;
console.log('targetTop: ' + targetTop);
var targetLeft = target.offset().left;
console.log('targetLeft: ' + targetLeft);
var drag = $('#' + value + '.drag');
console.log(drag);
var dragTop = drag.offset().top;
console.log('dragTop: ' + dragTop);
var dragLeft = drag.offset().left;
console.log('dragLeft: ' + dragLeft);
drag.animate(
'top': -target.offset().top,
'left': -target.offset().left
, 3000);
);
);
但是当我运行它时,拖动 div 不会到达目标位置,而是到达其他位置。当我检查动画元素时,偏移量与目标偏移量相同,只是在值之前有一个“-”。我希望有人能告诉我我做错了什么以及如何解决这个问题。
感谢
【问题讨论】:
您的 html 无效。id
属性应该是唯一的。 (这并不意味着你仍然不能实现一些 JS 来达到预期的效果,但我喜欢不鼓励使用无效的 html。)
如果我想让两个 div 看起来一样我给它们相同的 id,为什么它必须是唯一的。
为什么独一无二?因为那是how the id
attribute is defined。相似的元素应该通过一个公共类进行分组。 (正如我已经说过的,打破这个规则并不一定会阻止你的页面工作,但是如果你可以不使用使用无效的html实现完全相同的效果不是更好吗?)
好的,但这不是我目前遇到的问题。但是谢谢你的信息,我不知道。
就在上面的多id点上,jquery在使用$('#id')时只会拾取一个对象
【参考方案1】:
在您的代码中,如果您的拖动元素位于同一个偏移父项中,并且两者都是绝对定位的,则应该像替换一样简单:
drag.animate(
'top': -target.offset().top,
'left': -target.offset().left
, 3000);
与:
drag.animate(
'top': target.offset().top,
'left': target.offset().left
, 3000);
如果不是绝对定位,那么它与设置偏移不完全相同,jQuery 足够聪明地计算出正确的相对定位,但 animate 不使用相同的功能。失败的你可以使用:
$drag.animate(
top: $target.position().top - $drag.position().top
, left: $target.position().left - $drag.position().left , 3000);
示例用法
版本 1 - jQuery 匹配
HTML 已更新,使其符合nnnnnn 的正确建议(无重复 ID):
<div class="container">
<div class="answer" id="answer-1"></div>
<div class="answer" id="answer-2"></div>
<div class="answer" id="answer-3"></div>
<div class="answer" id="answer-4"></div>
<div class="answer" id="answer-5"></div>
<div class="answer" id="answer-6"></div>
<div class="answer" id="answer-7"></div>
<div class="answer" id="answer-8"></div>
<div class="answer" id="answer-9"></div>
<div class="answer" id="answer-10"></div>
<div class="answer" id="answer-11"></div>
<div class="answer" id="answer-12"></div>
</div>
<div class="container">
<div class="drag" id="drag-3"></div>
<div class="drag" id="drag-1"></div>
<div class="drag" id="drag-2"></div>
<div class="drag" id="drag-6"></div>
<div class="drag" id="drag-5"></div>
<div class="drag" id="drag-12"></div>
<div class="drag" id="drag-4"></div>
<div class="drag" id="drag-8"></div>
<div class="drag" id="drag-7"></div>
<div class="drag" id="drag-11"></div>
<div class="drag" id="drag-9"></div>
<div class="drag" id="drag-10"></div>
</div>
<div>
<a id="get-answers">Get answers</a>
</div>
有了这个,可以简化 javascript 以匹配拖动 [id] 到答案 [id] 并使用 position jQuery method 将拖动元素移动到正确的位置:
// Animates right answered draggables
// to the right answers
function resetAnimation()
// Iterate over all of the drag elements
$(".drag").each(function()
var $drag = $(this)
// Get the id of the drag element
// by dropping "drag-" off the front
, id = $drag.attr("id").replace("drag-", "")
// Find the matching answer
, $target = $('#answer-' + id);
// The animation code, position gives
// the coordinates of the element relative
// to the offset parent, subtract the original
// position from the target position to get the
// correct translation deltas
$drag.animate(
top: $target.position().top - $drag.position().top
, left: $target.position().left - $drag.position().left, 3000);
);
$(function()
$("#get-answers").click(resetAnimation);
);
版本 2 - 数组匹配
如果您确实想坚持使用数组来支持它(我会使用对象文字并将数字视为字符串 id),那么对代码的修改如下:
// Animates right answered draggables
// to the right answers
function resetAnimation(answered, correct)
// Iterate over all of the drag elements
for(var id in answered)
if(answered[id] !== correct[id])
var $drag = $("#drag-" + id)
// Find the matching answer
, $target = $('#answer-' + correct[id]);
// The animation code, position gives
// the coordinates of the element relative
// to the offset parent, subtract the original
// position from the target position to get the
// correct translation deltas
$drag.animate(
top: $target.position().top - $drag.position().top
, left: $target.position().left - $drag.position().left, 3000);
$(function()
$("#get-answers").click(function()
resetAnimation(
"1" : "3",
"2" : "2",
"3" : "1"
,
"1" : "2",
"2" : "3",
"3" : "1"
);
);
);
我用于这些测试用例的 CSS:
.answer
float: left;
margin: 10px;
background: red;
width: 20px;
height: 20px;
.drag
position: relative;
float: left;
margin: 10px;
background: green;
width: 20px;
height: 20px;
.container
float: left;
width: 100%;
Here's a fiddle
【讨论】:
谢谢这就是我要找的东西。做目标 - 拖动位置。我现在也使我的 html 有效。 不错,我想这会让上面的很多评论者感到高兴……它让世界变得更美好! ;-)【参考方案2】:您可以使用 css 类不仅可以赋予样式,还可以指定元素。
你可以做类似的事情
<div class="answer" id="answer-2" class="answer q2"></div>
<div class="answer" id="answer-3" class="answer q3"></div>
...
<div class="drag" id="question-2" class="q2"></div>
<div class="drag" id="question-6" class="q6"></div>
现在,您可以使用他们的类来匹配问题和回答。例如,对于每个问题,获取类 var myClass = $(this).prop('class');
并找到匹配的答案 $("div.answer."+myClass);
【讨论】:
【参考方案3】:我会使用 jQuery 用于测试的模拟插件来“模拟”拖放;
https://github.com/jquery/jquery-ui
一些使用示例其实可以在测试中查看:
https://github.com/jquery/jquery-ui/blob/master/tests/unit/draggable/draggable_core.js
https://github.com/jquery/jquery-ui/blob/master/tests/unit/draggable/draggable_events.js
【讨论】:
以上是关于如何将多个 div 设置为特定目标位置的动画?的主要内容,如果未能解决你的问题,请参考以下文章
如何自动检测特定 Div 的 scrollTop 位置? [复制]