You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 16:40:22