В этой заметка реализуем кастомный drag-and-drop на JavaScript с помощью обработки событий мыши.

See the Pen dnd by FurryCat (@mohnatus-the-lessful) on CodePen.

Верстка

<div id='dnd-container'>
  <div id='dnd-item'></div>
</div>

Стили

#dnd-container {
  width:100%;
  height:400px;
  background: #eee;
  border: 2px solid #000;
  position:relative;
  overflow:hidden;
}
#dnd-item {
  width:30px;
  height:30px;
  border-radius:50%;
  background: green;
  position:absolute;
}

Скрипт

let dndContainer = document.getElementById('dnd-container');
let dndItem = document.getElementById('dnd-item');

// Мяч позиционируется относительно контейнера
// Находим координаты контейнера в документе
let containterRect = dndContainer.getBoundingClientRect();

// Координаты контейнера с учетом прокрутки страницы
let containerRectWithScroll = {};
containerRectWithScroll.top = containterRect.top + pageYOffset;
containerRectWithScroll.left = containterRect.left + pageXOffset;

// Зажатие левой кнопки мыши на мяче
dndItem.onmousedown = function(e){

    // Отменяем нативную реакцию браузера на событие перетаскивания
    // так как мы реализуем ее самостоятельно
    dndItem.ondragstart = function() {
      return false;
    }

    // Находим текущие координаты мяча на странице
    let itemRect = dndItem.getBoundingClientRect();
  
    // Находим позицию мяча относительно контейнера
    let itemRectInContainer = {};
    itemRectInContainer.top = itemRect.top + pageYOffset 
      - containerRectWithScroll.top;
    itemRectInContainer.left = itemRect.left + pageXOffset 
      - containerRectWithScroll.left;

    // Находим смещение курсора от левого верхнего угла мяча при клике
    let shiftX = e.pageX - itemRectInContainer.left;
    let shiftY = e.pageY - itemRectInContainer.top;
    
    // Передвигаем мяч
    moveAt(e);

    function moveAt(e){
      // При достижении мячом границ контейнера передвижение прекращается
      
      let itemLeftPosition = e.pageX - shiftX;
      // Если достигнута левая граница контейнера 
      if (itemLeftPosition < 0) {
        dndItem.style.left = 0;
      } else {
        let rightBoundary = dndContainer.clientWidth - dndItem.clientWidth;
        // Если достигнута правая граница контейнер
        if (itemLeftPosition > rightBoundary) {
          dndItem.style.left = rightBoundary + 'px';
        } else {
          dndItem.style.left = itemLeftPosition + 'px';
        }
      }
      
      let itemTopPosition = e.pageY - shiftY;
      // Если достигнута верхняя граница контейнера
      if (itemTopPosition < 0) {
        dndItem.style.top = 0;
      } else {
        let bottomBoundary = dndContainer.clientHeight - dndItem.clientHeight;
        // Если достигнута нижняя граница контейнера
        if (itemTopPosition > bottomBoundary) {
          dndItem.style.top = bottomBoundary + 'px';
        } else {
          dndItem.style.top = itemTopPosition + 'px';
        }
      }
    }
  
    // При движении мышью перемещаем мяч
    dndContainer.onmousemove = function(e){
      moveAt(e);
    }
  
    // При отпускании клавиши мыши прекращаем перемещение
    dndContainer.onmouseup = function(){
      dndContainer.onmousemove = null;
      dndItem.onmouseup = null;
    }
}

Похожие статьи

0 комментариев

Оставить комментарий

*Доступные HTML-теги: a, abbr, blockquote, code, pre, del, i, em, strong, b, strike
*Не будет опубликован