VUE-使用touchstart、touchmove、touchend实现拖拽卡片列表,实现更新排序功能

2023-03-07,,

感谢本文参考地址,原文解析更加清晰如有需要请移步:https://blog.csdn.net/weixin_40400844/article/details/114849253

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

  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>

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

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

①将下方图片代码修改为(只做了减1的操作):

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-使用touchstart、touchmove、touchend实现拖拽卡片列表,实现更新排序功能的相关教程结束。

《VUE-使用touchstart、touchmove、touchend实现拖拽卡片列表,实现更新排序功能.doc》

下载本文的Word格式文档,以方便收藏与打印。