如何在jQuery中实现可拖拽对象在容器内随机位置放置及留存
解决jQuery UI拖拽元素无法在容器任意位置放置的问题
问题现状
使用jQuery UI的draggable和droppable组件时,存在两个问题:
- 新增的拖拽元素在容器里只能按列表顺序排列,没法随机放在任意初始位置
- 拖拽元素到目标容器后,会被强制重置到容器顶部左侧,不能停留在释放的位置
期望效果
- 点击添加按钮时,元素随机出现在容器内的任意位置
- 拖拽元素到容器任意位置松开后,元素保持在该位置
解决方案
1. 调整定位规则
要让元素能自由摆放,必须给容器和拖拽元素设置正确的定位属性:
.droppable { position: relative; /* 作为绝对定位元素的父容器,限制子元素定位范围 */ min-height: 200px; /* 确保容器有足够高度容纳元素 */ } .draggable { position: absolute; /* 让元素脱离文档流,支持自由定位 */ cursor: move; } .alwaysTop { width: 40%; }
2. 新增元素时随机设置位置
在创建元素时,根据容器尺寸计算随机的top和left值,避免元素堆叠:
$("#addBtn").click(function() { var $dropbox = $("#dropbox"); // 获取容器可用尺寸 var containerWidth = $dropbox.width(); var containerHeight = $dropbox.height(); // 元素的宽高(如果是动态计算可调整为获取实际元素尺寸) var elemWidth = 200; var elemHeight = 80; // 计算随机位置,确保元素不会超出容器边界 var randomTop = Math.floor(Math.random() * (containerHeight - elemHeight)); var randomLeft = Math.floor(Math.random() * (containerWidth - elemWidth)); var $div = $("<div>", { "class": "alert alert-info draggable alwaysTop", text: "Say-Da-Tay!", css: { top: randomTop + "px", left: randomLeft + "px" } }).draggable({ containment: ".droppable" // 限制拖拽只能在容器内进行 }); $("#dropbox").append($div); });
3. 修正放置逻辑,保留释放位置
在drop事件中,不要重置元素位置,而是计算元素相对于目标容器的偏移量:
$(".droppable").droppable({ accept: ".draggable", drop: function(event, ui) { var dropped = ui.draggable; var droppedOn = $(this); // 计算元素相对于目标容器的偏移值 var containerOffset = droppedOn.offset(); var newTop = ui.position.top - containerOffset.top; var newLeft = ui.position.left - containerOffset.left; // 移动元素到目标容器并设置正确位置 $(dropped).detach().css({ top: newTop + "px", left: newLeft + "px" }).appendTo(droppedOn); } });
完整代码整合
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://code.jquery.com/ui/1.13.1/jquery-ui.min.js"></script> <div> <div class="col-md-4"> <div class="panel panel-primary parentPanel"> <div class="panel-heading"> <h3 class="panel-title">Dropbox</h3> </div> <div class="panel-body droppable" id="dropbox"> </div> </div> </div> <div class="btn btn-warning col-md-2" id="addBtn"> Add Item </div> <div class="col-md-4"> <div class="panel panel-success parentPanel"> <div class="panel-heading"> <h3 class="panel-title">Final Destination</h3> </div> <div class="panel-body droppable" id="final_dest"> </div> </div> </div> </div>
CSS
.droppable { position: relative; min-height: 200px; } .draggable { position: absolute; cursor: move; } .alwaysTop { width: 40%; }
JavaScript
$(document).ready(function() { $("#addBtn").click(function() { var $dropbox = $("#dropbox"); var containerWidth = $dropbox.width(); var containerHeight = $dropbox.height(); var elemWidth = $dropbox.find(".draggable").outerWidth() || 200; var elemHeight = $dropbox.find(".draggable").outerHeight() || 80; // 确保随机位置不会让元素超出容器 var randomTop = Math.max(0, Math.floor(Math.random() * (containerHeight - elemHeight))); var randomLeft = Math.max(0, Math.floor(Math.random() * (containerWidth - elemWidth))); var $div = $("<div>", { "class": "alert alert-info draggable alwaysTop", text: "Say-Da-Tay!", css: { top: randomTop + "px", left: randomLeft + "px" } }).draggable({ containment: ".droppable" }); $("#dropbox").append($div); }); $(".droppable").droppable({ accept: ".draggable", drop: function(event, ui) { var dropped = ui.draggable; var droppedOn = $(this); var containerOffset = droppedOn.offset(); var newTop = ui.position.top - containerOffset.top; var newLeft = ui.position.left - containerOffset.left; $(dropped).detach().css({ top: newTop + "px", left: newLeft + "px" }).appendTo(droppedOn); } }); });
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

