Frontend/javaScript

[JavaScript] draggable 옵션 및 예제

dddzr 2023. 5. 4. 13:59

자바스크립트의 draggable 속성과 dragstart, dragend 이벤트를 사용하여 요소를 드래그할 수 있습니다.

 

draggable 옵션입니다.

  • cancel: false는 드래그 가능한 요소 내의 특정 하위 요소를 클릭하여 드래그 작업이 취소되는 것을 방지합니다.
    불투명도: 0.7은 드래그 동작 중 드래그 가능 요소의 불투명도를 설정합니다.
  • snap: "[elem]"은 요소를 요소 클래스가 있는 다른 요소로 스냅하도록 지정합니다.
  • snapMode: "둘 다"는 스냅이 수평과 수직 모두에서 발생해야 함을 나타냅니다.
  • snap Tolerance: 10은 스냅이 발생해야 하는 스냅 대상으로부터의 거리(픽셀)를 지정합니다.
  • stack: "[elem]"은 끌어온 요소의 z-index를 요소 클래스가 있는 어떤 요소보다 높게 설정합니다.
  • start: function(이벤트, UI)은 드래그 액션이 시작될 때 실행되는 콜백 함수입니다. 요소의 원래 위치를 저장하고 요소가 스냅될 위치를 나타내는 데 사용되는 가이드라인을 작성합니다.
  • drag: 함수(event, ui)는 요소를 끌 때 실행되는 콜백 함수입니다. 요소의 위치를 조정하고 다른 요소로 스냅할지 여부를 결정합니다.
  • stop: function(이벤트, UI)은 드래그 동작이 중지될 때 실행되는 콜백 기능입니다. 가이드라인을 숨깁니다.
  • axis: 수평 또는 수직 축으로 끌 수 있는 한계.
  • containment: 드래그 영역을 지정된 상위 요소 또는 뷰포트로 제한합니다.
  • cursor: 드래그 작업 중에 표시할 커서를 설정합니다.
  • helper: 끌 때 표시할 도우미 요소를 지정합니다.
  • revert: 드래그 작업이 취소된 경우 드래그 요소를 원래 위치로 되돌릴 것인지 여부를 지정합니다.
  • revertDuration: 되돌리기 애니메이션의 지속 시간을 설정합니다.


아래는 예제 코드 입니다.

let positionX;
let positionY;
function bindDragEvent(id) {
  $("#" + id).attr("draggable", true);
  $("#" + id).draggable({
    cancel: false,
    opacity: 0.7,
    snap: "[elem]",
    snapMode: "both",
    snapTolerance: 10,
    stack: "[elem]",
    start: function(event, ui) {
      positionY = ui.originalPosition.top;
      positionX = ui.originalPosition.left;
      createGuideLine();
      $(".editor-guidelines").css("z-index", $(this).css("z-index"));
    },
    drag: function(event, ui) {
      if (event.ctrlKey) {
        $(this).draggable("option", "snapTolerance", 1);
      } else {
        $(this).draggable("option", "snapTolerance", 10);
      }

      let currentLoc = ui.position;

      let moveY = currentLoc.top - positionY;
      let moveX = currentLoc.left - positionX;
                
      let zoom = $("#container").css('zoom');
      var factor = (1 / zoom) -1;

      moveGroup(moveY, moveX, factor);// 여러 컴포넌트가 선택 되었을 때
      positionY = currentLoc.top;
      positionX = currentLoc.left;
      
      let snapped = $(this).data('uiDraggable').snapElements;
      let snappedTo = $.map(snapped, function (element) {
        return element.snapping ? element : null;
      });

      if (snappedTo.length > 0) {
        if(snappedTo[0].item.parentElement.id !== id){
          if ((snappedTo[0].left + snappedTo[0].width) == $(this).offset().left) {
            $('#editor-guide-v').offset({top: 0, left: $(this).offset().left}).show();
          } else if ((snappedTo[0].left) == $(this).offset().left) {
            $('#editor-guide-v').offset({top: 0, left: $(this).offset().left}).show();
          } else if ((snappedTo[0].left) == $(this).offset().left + $(this).outerWidth()) {
            $('#editor-guide-v').offset({top: 0, left: $(this).offset().left + $(this).outerWidth()}).show();
          } else $('#editor-guide-v').hide();

          if ((snappedTo[0].top) == $(this).offset().top) {
            $('#editor-guide-h').offset({top: $(this).offset().top, left: 0}).show();
          } else if ((snappedTo[0].top + snappedTo[0].height) == $(this).offset().top) {
            $('#editor-guide-h').offset({top: $(this).offset().top, left: 0}).show();
          } else if ((snappedTo[0].top) == $(this).offset().top + $(this).outerHeight()) {
            $('#editor-guide-h').offset({top: $(this).offset().top + $(this).outerHeight(), left: 0}).show();
          } else $('#editor-guide-h').hide();
        }
      }
    },
    stop: function(event, ui) {
      $('#editor-guide-h,#editor-guide-v').hide();
    }
  });
}


  function moveGroup(moveY, moveX, factor) { 
    Object.keys(selectedObjects).forEach(function(id, idx, arr) {
      let elem = document.querySelector("#" + id);
      let $this = $(elem);

      let currLoc = $this.position();

      let top = currLoc.top + moveY;// + Math.round(moveY * factor);
      let left = currLoc.left + moveX;// + Math.round(moveX * factor);
      $this.css("top", top + "px");
      $this.css("left", left  + "px");
    });
  }