【转】jquery-ui draggable中div拖动出现辅助线方便对齐(优化)

<html>
  <head>
    <link rel="stylesheet" href="./jquery-ui-1.12.1/jquery-ui.min.css" />
    <title>实现div拖拽时出现辅助线,以方便和其它div很容易的对齐</title>
  </head>

  <body>
    <div class="container">
      <!-- 需要拖动的div -->
      <div class="draggable">第一个div</div>
      <div class="draggable">第二个div</div>
      <div class="draggable">第三个div</div>
      <div class="draggable">第四个div</div>
      <div class="draggable">第五个div</div>
      <div class="draggable">第六个div</div>

      <!-- 拖动辅助线 -->
      <div id="guide-h" class="guide"></div>
      <div id="guide-v" class="guide"></div>
    </div>

    <script src="./jquery-ui-1.12.1/external/jquery/jquery.js"></script>
    <script src="./jquery-ui-1.12.1/jquery-ui.min.js"></script>
    <script type="text/javascript">
      var MIN_DISTANCE = 8 //捕获的最小距离
      var guides = [] // 指标拖动辅助标线
      var innerOffsetX, innerOffsetY

      $('.draggable').draggable({
        start: function(event, ui) {
          guides = $.map($('.draggable').not(this), computeGuidesForElement)
          // offsetX、offsetY:源元素(srcElement)的X, Y坐标
          innerOffsetX = event.offsetX
          innerOffsetY = event.offsetY
        },
        drag: function(event, ui) {
          // 迭代所有的guids,记住最近的h和v guids
          var guideV,
            guideH,
            distV = MIN_DISTANCE + 1,
            distH = MIN_DISTANCE + 1,
            offsetV,
            offsetH

          var chosenGuides = {
            top: {
              dist: MIN_DISTANCE + 1
            },
            left: {
              dist: MIN_DISTANCE + 1
            }
          }
          var $t = $(this)
          // pageX、pageY:文档坐标x、y
          var pos = {
            // top: event.pageY - innerOffsetY,
            // left: event.pageX - innerOffsetX
            top: event.clientY - innerOffsetY,
            left: event.clientX - innerOffsetX
          }
          // outerHeight、outerWidth:整个浏览器的高度、宽度
          var w = $t.outerWidth() - 1
          var h = $t.outerHeight() - 1
          var elemGuides = computeGuidesForElement(null, pos, w, h)
          $.each(guides, function(i, guide) {
            $.each(elemGuides, function(i, elemGuide) {
              if (guide.type == elemGuide.type) {
                var prop = guide.type == 'h' ? 'top' : 'left'
                var d = Math.abs(elemGuide[prop] - guide[prop])
                if (d < chosenGuides[prop].dist) {
                  chosenGuides[prop].dist = d
                  chosenGuides[prop].offset = elemGuide[prop] - pos[prop]
                  chosenGuides[prop].guide = guide
                }
              }
            })
          })

          if (chosenGuides.top.dist <= MIN_DISTANCE) {
            $('#guide-h')
              .css('top', chosenGuides.top.guide.top)
              .show()

            ui.position.top = chosenGuides.top.guide.top - chosenGuides.top.offset
          } else {
            $('#guide-h').hide()
            ui.position.top = pos.top
          }

          if (chosenGuides.left.dist <= MIN_DISTANCE) {
            $('#guide-v')
              .css('left', chosenGuides.left.guide.left)
              .show()

            ui.position.left = chosenGuides.left.guide.left - chosenGuides.left.offset
          } else {
            $('#guide-v').hide()
            ui.position.left = pos.left
          }
        },

        stop: function(event, ui) {
          $('#guide-v, #guide-h').hide()
        }
      })

      /**
       * 计算 DOM 元素辅助线
       * @param {String, Object} elem DOM 选择器
       * @param {Object} pos 位置坐标
       * @param {Number} w 宽度
       * @param {Number} h 高度
       * @returns {Array} 辅助线对象数组
       */
      function computeGuidesForElement(elem, pos, w, h) {
        if (elem != null) {
          var $t = $(elem)
          // offset - 返回当前元素的偏移量
          pos = $t.offset()
          w = $t.outerWidth() - 1
          h = $t.outerHeight() - 1
        }
        // type,方向类型,h - 垂直方向;v - 水平方向。
        const guids = [
          // 垂直方向 - 顶端对齐线
          { type: 'h', left: pos.left, top: pos.top },
          // 垂直方向 - 中心对齐线
          { type: 'h', left: pos.left, top: pos.top + h / 2 },
          // 垂直方向 - 中心对齐线
          { type: 'h', left: pos.left, top: pos.top + h },

          // 水平方向 - 左侧对齐线
          { type: 'v', left: pos.left, top: pos.top },
          // 水平方向 - 中心对齐线
          { type: 'v', left: pos.left + w / 2, top: pos.top },
          // 水平方向 - 左侧对齐线
          { type: 'v', left: pos.left + w, top: pos.top }
        ]
        return guids
      }
    </script>
    <style type="text/css">
      * {
        padding: 0px;
        margin: 0px;
      }

      body {
        height: 100%;
        overflow-x: hidden;
        overflow-y: hidden;
      }

      .container {
        width: 100vw;
        min-height: 90vh;
        margin: 0px auto;
        position: relative;
        overflow: auto;
        border-bottom: 1px gray solid;
      }

      .draggable {
        width: 200px;
        height: 100px;
        border: 1px solid #ccc;
        display: inline-block;
        cursor: move;
        position: absolute !important;
        top: 0px;
        left: 0px;
      }

      .guide {
        display: none;
        position: absolute;
        left: 0;
        top: 0;
      }

      #guide-h {
        border-top: 1px red solid;
        width: 100%;
      }

      #guide-v {
        border-left: 1px red solid;
        height: 100%;
      }
    </style>
  </body>
</html>

 

posted @ 2020-11-27 17:56  jardeng  阅读(293)  评论(0编辑  收藏  举报