首页 > 其他分享 >VUE-使用touchstart、touchmove、touchend实现拖拽卡片列表

VUE-使用touchstart、touchmove、touchend实现拖拽卡片列表

时间:2022-12-02 11:35:34浏览次数:64  
标签:VUE const touchstart selected height touchend icon true name

感谢本文参考地址:https://www.jb51.net/article/255385.htm

怕原链接失效,将代码拷贝(如有侵权,请联系删除,感谢!!)

  1 <template>
  2   <div>
  3     <ul>
  4       <li 
  5         class="libox" 
  6         v-for="(item, index) in list"
  7         :key="index"
  8         :id="'card' + (index + 1)"
  9       >
 10         <div
 11           @touchstart="touchstart($event, item)"
 12           @touchmove="touchMove($event, item)"
 13           @touchend="touchEnd($event, item)"
 14           v-show="item.name !== selectItem.name"
 15         >
 16           {{item.name}}
 17           <svg class="icon svg-icon" aria-hidden="true">
 18             <use :xlink:href="item.icon" rel="external nofollow" ></use>
 19           </svg>
 20         </div>
 21       </li>
 22       <li v-show="selectItem.name" class="selectBox" ref="selectBox">
 23         {{selectItem.name}}
 24         <svg class="icon svg-icon" aria-hidden="true">
 25           <use :xlink:href="selectItem.icon" rel="external nofollow" ></use>
 26         </svg>
 27       </li>
 28     </ul>
 29   </div>
 30 </template>
 31  
 32 <script>
 33  
 34 export default {
 35   data() {
 36     return {
 37       // 列表数据
 38       list: [
 39         { name: '1', selected: true, icon: '#icon-mianxingbenzivg' },
 40         { name: '2', selected: true, icon: '#icon-mianxingchizi' },
 41         { name: '3', selected: true, icon: '#icon-mianxingdiannao' },
 42         { name: '4', selected: true, icon: '#icon-mianxingdayinji' },
 43         { name: '5', selected: true, icon: '#icon-mianxingdingshuqi' },
 44         { name: '6', selected: true, icon: '#icon-mianxingheiban' },
 45         { name: '7', selected: true, icon: '#icon-mianxinggangbi' },
 46         { name: '8', selected: true, icon: '#icon-mianxingboshimao' },
 47         { name: '9', selected: true, icon: '#icon-mianxingjisuanqi' },
 48         { name: '10', selected: true, icon: '#icon-mianxinghuaxue' },
 49         { name: '11', selected: true, icon: '#icon-mianxingqianbi' },
 50         { name: '12', selected: true, icon: '#icon-mianxingshubao' },
 51         { name: '13', selected: true, icon: '#icon-mianxingshuicaibi' },
 52         { name: '14', selected: true, icon: '#icon-mianxingtushu' },
 53       ],
 54       // 选中元素内容
 55       selectItem: {},
 56       timeOutEvent: 0,
 57       oldNodePos: {
 58         x: 0,
 59         y: 0,
 60       },
 61       oldMousePos: {
 62         x: 0,
 63         y: 0
 64       },
 65       oldIndex: 0,
 66       // 长按标识
 67       longClick: 0
 68     };
 69   },
 70   watch: {
 71     oldIndex(newVal) {
 72       const oldIndex = this.list.findIndex(r=> r.name === this.selectItem.name);
 73       this.list.splice(oldIndex, 1);
 74       this.list.splice(newVal, 0, this.selectItem);
 75     }
 76   },
 77   methods: {
 78     touchstart(ev, item) {
 79       this.longClick = 0;
 80       const that = this;
 81       const selectDom = ev.currentTarget; // div元素
 82       this.timeOutEvent = setTimeout(() => {
 83         that.longClick = 1;
 84         that.selectItem = item;
 85         // 元素初始位置
 86         that.oldNodePos = {
 87           x: selectDom.offsetLeft,
 88           y: selectDom.offsetTop
 89         };
 90         // 鼠标原始位置
 91         that.oldMousePos = {
 92           x: ev.touches[0].pageX,
 93           y: ev.touches[0].pageY
 94         };
 95         const lefts = that.oldMousePos.x - that.oldNodePos.x; // x轴偏移量
 96         const tops = that.oldMousePos.y - that.oldNodePos.y; // y轴偏移量
 97         const { pageX, pageY } = ev.touches[0]; // 手指位置
 98         that.$refs.selectBox.style.left = `${pageX - lefts}px`;
 99         that.$refs.selectBox.style.top = `${pageY - tops}px`;
100       }, 500);
101     },
102     touchMove(ev) {
103       clearTimeout(this.timeOutEvent);
104       const selectDom = ev.currentTarget.parentNode; // li元素
105       if (this.longClick === 1) {
106         const lefts = this.oldMousePos.x - this.oldNodePos.x; // x轴偏移量
107         const tops = this.oldMousePos.y - this.oldNodePos.y; // y轴偏移量
108         const { pageX, pageY } = ev.touches[0]; // 手指位置
109         this.$refs.selectBox.style.left = `${pageX - lefts}px`;
110         this.$refs.selectBox.style.top = `${pageY - tops}px`;
111         this.cardIndex(selectDom, pageX, pageY);
112       }
113     },
114     touchEnd() {
115       clearTimeout(this.timeOutEvent);
116       this.selectItem = {};
117     },
118     /**
119      * 计算当前移动卡片位于卡片的哪一行哪一列
120      */
121     cardIndex(selDom, moveleft, movetop) {
122       const liWid = selDom.clientWidth;
123       const liHei = selDom.clientHeight;
124       const newWidthNum = Math.ceil((moveleft / liWid)); // 哪一列
125       const newHeightNum = Math.ceil((movetop / liHei)); // 哪一行
126       const newPositionNum = (newHeightNum - 1) * 4 + newWidthNum;
127       if (this.oldIndex !== newPositionNum - 1) {
128           if (newPositionNum <= this.list.length) {
129             this.oldIndex = newPositionNum - 1;
130           } else {
131             this.oldIndex = this.list.length - 1;
132           }
133       }
134     }
135   }
136 }
137 </script>
138  
139 <style lang="scss" scoped>
140   @mixin myFlexCenter{
141     display: flex;
142     justify-content: center;
143     align-items: center;
144   }
145   ul {
146     width: 100%;
147     height: 100%;
148     display: flex;
149     flex-wrap: wrap;
150     position: relative;
151     overflow: hidden;
152     .libox {
153       width: 25%;
154       height: 100px;
155       border-right: 1px dashed #cccccc;
156       border-bottom: 1px dashed #cccccc;
157       box-sizing: border-box;
158       @include myFlexCenter;
159       >div {
160         width: calc(100% - 10px);
161         height: 75px;
162         border-radius: 18px;
163         @include myFlexCenter;
164         position: relative;
165         &::after {
166             content: '';
167             width: 100%;
168             height: 100%;
169             background: rgba(255, 177, 177, 0.3);
170             position: absolute;
171             top: 0;
172             left: 0;
173         }
174         >svg {
175           width: 75px;
176           height: 75px;
177         }
178       }
179     }
180     .selectBox{
181       position: absolute;
182       width: calc(25% - 10px);
183       height: 75px;
184       border-radius: 18px;
185       >svg {
186         width: 75px;
187         height: 75px;
188       }
189       background-color: rgba(0, 0, 0, 0.1);
190       color:white;
191       @include myFlexCenter;
192       -moz-user-select:none; /*火狐*/
193       -webkit-user-select:none; /*webkit浏览器*/
194       -ms-user-select:none; /*IE10*/
195       -khtml-user-select:none; /*早期浏览器*/
196       user-select:none;
197     }
198   }
199 </style>
View Code

存在问题:只能放在卡片上方才能挪动其他卡片位置,未达到需要效果,所以进行了修改。

经实际测试后修改以下部分:

①将以下代码修改为:

 1 const newHeightNum = Math.ceil((movetop / liHei)) - 1; // 哪一行

 ②因为项目未使用scss,所以将css改成如下:

 1 <style  scoped>
 2   ul {
 3     width: 100%;
 4     height: 100%;
 5     display: flex;
 6     flex-wrap: wrap;
 7     position: relative;
 8     overflow: hidden;
 9   }
10   .libox {
11       width: 25%;
12       height: 100px;
13       box-sizing: border-box;
14       display: flex;
15       justify-content: center;
16       align-items: center;
17   }
18   .libox div {
19       width: calc(100% - 10px);
20       height: 75px;
21       border-radius: 18px;
22       display: flex;
23       justify-content: center;
24       align-items: center;
25       flex-direction: column;
26       position: relative;
27     }
28     .selectBox{
29       position: absolute;
30       width: calc(25% - 10px);
31       height: 75px;
32       border-radius: 18px;
33       background-color: inherit;
34       /* color:white; */
35       display: flex;
36       flex-direction: column;
37       justify-content: center;
38       align-items: center;
39       user-select:none;
40     }
41 </style>

 效果:

 

标签:VUE,const,touchstart,selected,height,touchend,icon,true,name
From: https://www.cnblogs.com/jiangcaicai/p/16943724.html

相关文章