拖动开始时捕捉到父网格

时间:2015-05-26 22:35:27

标签: javascript jquery html jquery-ui draggable

我是一个相当陌生的JavaScript& JQuery,如果我错过了一两个技巧,那么道歉。

我已经弄清楚如何让JQuery UI可拖动对象使用网格选项,并且,一旦页面加载,"捕捉到想象中的网格"所有可拖动对象都参考(在代码注释中解释)。但是,我无法弄清楚如何让这种行为发生.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>
&#13;
&#13;
&#13;

注意: 两个矩形之间有一个白色的间隙,通过下面的第二个JavaScript,一旦块被捕捉到网格后,它就会消失。或者,2个矩形应该可以相互拖动,并且相互齐平排列,以便被认为是卡在网格上。

JavaScript(dragger.js):

&#13;
&#13;
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);
    })
});
&#13;
&#13;
&#13;

证明snapPosition中的代码有效:

&#13;
&#13;
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);
      }
    })
});
&#13;
&#13;
&#13;

第一个JavaScript试图在拖动开始后更改块的位置,将其捕捉到虚构网格。第二个在加载页面时自动执行此操作,但不会再次执行此操作。例如,如果我要将虚构网格粒度从50更改为79,则拖动不会根据需要将对象带回网格。

我有什么地方可以学习如何做到这一点吗?它可行吗?

澄清:

  • JQuery = 1.10.2(与JQuery UI演示相同)
  • JQuery UI = 1.11.4(与JQuery UI演示相同)
  • 浏览器= Ubuntu 14.04上的Firefox,一切都是最新的

我已经通过谷歌,但任何条款都类似于&#34;开始&#34;,&#34;拖动&#34;和&#34;位置&#34;并不是唯一足以缩小范围的东西,或者我找不到合适的地方。我还浏览了JQuery(UI)档案。

非常感谢提前!

1 个答案:

答案 0 :(得分:0)

好的,事实证明,有一些代表我的无知的例子。我也会在下面通过它们来帮助其他人,但如果您只是在解决方案之后,那么请不要再犹豫了:

&#13;
&#13;
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;
      }
    })
});
&#13;
<!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>
&#13;
&#13;
&#13;

<强>错误:

  1. 第一个错误就在于我试图将定位功能与拖动功能分开。特别是,当尝试发送then时。我还没有真正理解这个,这就是为什么它不在解决方案中,但是我确实读过(并丢失链接)使用var _then = then;或使用绑定方法提到的堆栈溢出。如果我找到链接,我将编辑答案。
  2. 下一个错误与我在开始时的#34;规范有关。我想要的方法是在每次拖动开始时仅捕捉到父网格。因此,根据文档,使用start:.on("dragstart", ...)功能是合乎逻辑的。这会导致preventDefault问题,即启动命令被忽略,因此没有捕捉,但我可以拖动,或者如果我在开始时使用event.preventDefault,它会捕捉但不再拖动。事实证明drag:功能仅在拖动开始时运行一次(如果我错了,请纠正我)。通过将捕捉功能放回原处,另一个错误就解决了。
  3. 最后,我捕捉到网格的原始逻辑是错误的。它只使用一次就可以工作,但是每次拖动对象时它都会运行,它就会“蠕动”。每一次阻力都有一点点。这是因为&#34; snap&#34;功能从拖动对象的 ORIGINAL 位置工作到父级。因此,即使对象已经被捕捉,每次添加该差异也会导致错误。为了解决这个问题,我简单地将对象的原始当前位置区别开来,改为以原始位置为中心的相同网格。对象。
  4. (要明确的是,有3个参考位置,,拖动对象的原始位置以及当前位置被拖动的物体)。