익명의 개발노트

[vue.js] dragula를 이용하여 drag and drop 구현하기 본문

코딩일기/TIL

[vue.js] dragula를 이용하여 drag and drop 구현하기

캡틴.JS 2020. 2. 26. 20:03
반응형

dragula를 이용한 드래그 앤 드랍 구현하기.

drag and drop in Vue.js

1. 라이브러리 설치

npm i dragula

2. 템플릿 작성

<template>
  <div class="about">
    <div class="container">
      <div class="left">
        <div ref="left" id="drag-elements">
            <div>Element 1</div>
            <div>Element 2</div>
            <div>Element 3</div>
        </div>

        <div ref="right" id="drop-target">
        </div>
      </div>
      <div class="right">
        <div id="display" ref="display1">Display</div>
      </div>
    </div>
  </div>
</template>

Vue.js에서 DOM에 직접 접근하기 위하여 ref를 사용한다.

3. 스크립트 코드작성

<script >
import dragula from 'dragula'

export default {

 mounted(){
    const { right, display1, left } = this.$refs;

    dragula([
     left, right  //어디서 어디로 옮기는지
    ],{
      revertOnSpill: true  //클릭한 요소 컨테이너 밖으로 보내도 순서유지.
    }
    
    ).on('drop', el => {
        if(right.children.length > 0) {
          display1.innerHTML = right.innerHTML
        }else{
          display1.innerHTML = "Display"
        }
    })
  }
}

</script>

dragula를 import하고,  dragula의 첫번째 인자값은 어디에서 어디로 옮길 것인지, 그것에 대한 DOM을 넣어주면 되고,

두번째 인자값은 옵션이다.

.on은 드랍했을때 이벤트 처리를 나타낸다. 없어도 무관하다.

4. 스타일

<style scoped lang="scss">
.container {
  max-width: 960px;
  margin: 0 auto;
}

.left {
  float: left;
  position: relative;
  width: 50%;
  height: 100%;
}

.right {
  float: left;
  position: relative;
  width: 40%;
  margin-left: 5%;
  height: 100%;
}

#display {
  background: #2d2d2d;
  border: 10px solid #000000;
  border-radius: 5px;
  font-size: 2em;
  color: white;
  height: 100px;
  min-width:200px;
  text-align: center;
  padding: 1em;
  display:table-cell;
  vertical-align:middle;
}

#drag-elements {
  display: block;
  background-color: #dfdfdf;
  border-radius: 5px;
  min-height: 50px;
  margin: 0 auto;
  padding: 2em;
}

#drag-elements > div {
  text-align: center;
  float: left;
  padding: 1em;
  margin: 0 1em 1em 0;
  box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
  border-radius: 100px;
  border: 2px solid #ececec;
  background: #F7F7F7;
  transition: all .5s ease;
}

#drag-elements > div:active {
  -webkit-animation: wiggle 0.3s 0s infinite ease-in;
  animation: wiggle 0.3s 0s infinite ease-in;
  opacity: .6;
  border: 2px solid #000;
}

#drag-elements > div:hover {
  border: 2px solid gray;
  background-color: #e5e5e5;
}

#drop-target {
  border: 2px dashed #D9D9D9;
  border-radius: 5px;
  min-height: 50px;
  margin: 0 auto;
  margin-top: 10px;
  padding: 2em;
  display: block;
  text-align: center;
}

#drop-target > div {
  text-align: center;
  float: left;
  padding: 1em;
  margin: 0 1em 1em 0;
  box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
  border-radius: 100px;
  border: 2px solid #ececec;
  background: #F7F7F7;
  transition: all .5s ease;
}

#drop-target > div:active {
  -webkit-animation: wiggle 0.3s 0s infinite ease-in;
  animation: wiggle 0.3s 0s infinite ease-in;
  opacity: .6;
  border: 2px solid #000;
}

@-webkit-keyframes wiggle {
  0% {
    -webkit-transform: rotate(0deg);
  }
  25% {
    -webkit-transform: rotate(2deg);
  }
  75% {
    -webkit-transform: rotate(-2deg);
  }
  100% {
    -webkit-transform: rotate(0deg);
  }
}

@keyframes wiggle {
  0% {
    transform: rotate(-2deg);
  }
  25% {
    transform: rotate(2deg);
  }
  75% {
    transform: rotate(-2deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

.gu-mirror {
  position: fixed !important;
  margin: 0 !important;
  z-index: 9999 !important;
  padding: 1em;
}
.gu-hide {
  display: none !important;
}
.gu-unselectable {
  -webkit-user-select: none !important;
  -moz-user-select: none !important;
  -ms-user-select: none !important;
  user-select: none !important;
}
.gu-transit {
  opacity: 0.5;
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
  filter: alpha(opacity=50);
}
.gu-mirror {
  opacity: 0.5;
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
  filter: alpha(opacity=50);
}
</style>

코어기능은 이러하고, 여기서 응용해서 제작하면 될 듯 싶다.

반응형
Comments