感谢本文参考地址,原文解析更加清晰如有需要请移步: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实现拖拽卡片列表,实现更新排序功能的更多相关文章

  1. 获取touchstart,touchmove,touchend 坐标

    简单说下如何用jQuery 和 js原生代码获取touchstart,touchmove,touchend 坐标值: jQuery 代码: $('#id').on('touchstart',funct ...

  2. 移动端的touchstart,touchmove,touchend事件中的获取当前touch位置

    前提:touchstart,touchmove,touchend这三个事件可以通过原生和jq绑定. 原生:document.querySelector("#aa").addEven ...

  3. touchstart,touchmove,touchend触摸事件的小小实践心得

    近段时间使用html5开发一个公司内部应用,而触摸事件必然是移动应用中所必须的,刚开始以为移动设备上或许也会支持鼠标事件,原来是不支持的,好在webkit内核的移动浏览器支持touch事件,并且打包成 ...

  4. 移动端touchstart,touchmove,touchend

    近段时间使用html5开发一个公司内部应用,而触摸事件必然是移动应用中所必须的,刚开始以为移动设备上或许也会支持鼠标事件,原来是不支持的,好在webkit内核的移动浏览器支持touch事件,并且打包成 ...

  5. Vue 结合 echarts 原生 html5 实现拖拽排版报表系统

    前言 不知道各位 coder 有没有碰到过许多重复的业务需求,比如排版相类似的报表,只不过是顺序稍微换了一下,就是一个新的页面,虽然基于模板思想来写的话也能减少不少代码,但是相对的不那么方便,笔者最近 ...

  6. Vue拖拽组件列表实现动态页面配置

    需求描述 最近在做一个后台系统,有一个功能产品需求是页面分为左右两部分,通过右边的组件列表来动态配置左边的页面视图,并且左边由组件拼装起来的视图,可以实现上下拖拽改变顺序,也可以删除. 根据这个需求我 ...

  7. Vue富文本编辑器(图片拖拽缩放)

    富文本编辑器(图片拖拽缩放) 需求: 根据业务要求,需要能够上传图片,且上传的图片能在移动端中占满屏幕宽度,故需要能等比缩放上传的图片,还需要能拖拽.缩放.改变图片大小.尝试多个第三方富文本编辑器,很 ...

  8. 【UWP】拖拽列表项的排序功能实现

    在一些允许用户自定义栏目顺序的app(如:凤凰新闻.网易云音乐等),我们可以方便地拖拽列表项来完成列表的重新排序,进而完成对栏目顺序的重排.这个功能很人性化,而实现起来其实很简单(甚至都不用写什么后台 ...

  9. C# 图片缩放,拖拽后保存成图片的功能

    窗体界面部分如下: 鼠标的缩放功能需要手动在 OpertaionImg.Designer.cs 文件里面添加一句代码,具体代码如下: //picturePhoto显示图片的控件 this.pictur ...

  10. touchstart,touchmove,touchend事件 写法

    jQuery写法: $('#id').on('touchstart',function(e) { var _touch = e.originalEvent.targetTouches[0]; var ...

随机推荐

  1. APP与Web测试区别

    相同点: WEB 测试和 App 测试从流程上来说,没有区别.都需要经历测试计划方 案,用例设计,测试执行,缺陷管理,测试报告等相关活动.从技术上来说, WEB 测试和 APP 测试其测试类型也基本相 ...

  2. 央行DR007在哪里查看

    1.中国外汇交易中心,点击官网进入 https://www.chinamoney.com.cn/chinese/ 2.点击数据选项,接着选择货币市场行情 3.点击质押式回购

  3. 蓝桥杯训练赛二-1141 问题 C: C语言训练-百钱百鸡问题

    题目描述 中国古代数学家张丘建在他的<算经>中提出了著名的"百钱买百鸡问题":鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一,百钱买百鸡,问翁.母.雏各几何? 输入 无 ...

  4. nop 中创建任务(Task)

    NopCommerce 中Task 原理是服务端开启线程定时跑. 1.在数据表ScheduleTask中添加一条数据, 2.自定义类,继承ITask 即可 using Data.Log4Net; us ...

  5. python3 小知识

    本博客分为三部分,一是字典和函数结合,代替if-else判断语句:二是数组的元素带有括号:三是完整代码.图片略多. 1. 字典和函数结合,代替if-else判断语句   写函数时经常会遇到一个函数的某 ...

  6. Java实现输出三角形

    本来是想实现空心的,想了太久没写出来就算了 代码 package com.qaq.strruct;public class TestDemo01 { //打印三角形 //思路:空格的距离和星星的数量成 ...

  7. windows下创建con文件夹

    有时候,我们会碰到必须创建一个名为CON的文件夹,而这个名称在Windows下属于保留字(DOS时代的遗留产物). 方法如下: 1.打开命令行窗口(开始-->运行-->cmd) 2.输入完 ...

  8. tomcat8 无法解析 请求url 中 包含 [: 或者 :] 等特殊符号

    使用如下URL: http://127.0.0.1:8080/xx/[:xOGxeSSk5ENaYh89ziEFJA==:].do 如果使用tomcat8 无法正常访问,浏览器network 报错 4 ...

  9. SPI接口(续一)

    SPI接口共涉及到11个寄存器,下面就来对它们进行具体分析. 先来看SPI配置寄存器CFG,下表是它的全部位结构,其地址分别为0x40058000(SPI0),0x4005C000(SPI1). (1 ...

  10. 用C#的控制台程序写一个飞行棋项目

    using System; namespace 飞行棋项目 { class Program { ///1.画游戏头 ///2.初始化地图 ///把整数数组中数字编程控制台中显示的特殊字符显示的过程,就 ...