基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能


Posted in Vue.js onJanuary 05, 2021

用Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能 图片上传图片压缩拖拽排序、拖拽删除
之前在公司开发过一段时间的移动端H5页面,有个功能就是要上传图片+压缩。参考了一下网上的方法,外加自己摸索的过程,最终实现了这个功能。后面在家闲的时候又加多了个长按选中图片,并且可以拖拽排序、拖拽到指定位置删除的功能。

github地址:代码地址

下面直接进入正题:

图片上传

图片上传用的是HTML的input标签实现的。核心就是把获取到的文件通过FileReader转换成图片,代码如下:

<input type="file" accept="image/*" capture="camera" @change="selectFile">

selectFile(event:any){
 	this.showAlert = false  
 	if (event.target.files && event.target.files.length > 0) {
   this.isLoading = true
   let file:any = event.target.files[0]
   let fr:any = new FileReader()
   fr.readAsDataURL(file)
   fr.onload = (imgObj:any) => {
    let img:any = new Image()
    img.src = imgObj.target.result
    img.onload = (e:any) => {
     // 这里就可以获取到上传的图片了
     })
    }
   }
  }
}

图片压缩

图片压缩用的是canvas重绘的方法实现的,具体代码如下:

// 省略上面的代码
fr.onload = (imgObj:any) => {
	// 获取到图片文件后
 let img:any = new Image()
 img.src = imgObj.target.result
 img.onload = (e:any) => {
  Compress(img,e.path[0].height,e.path[0].width,(newImg:any) => {
   this.imgList.push(newImg)
   this.isLoading = false
   // 待添加拖拽功能
  })
 }
}

/**
 * 图片压缩
 * @param img 图片对象
 */
export function Compress(img:any,height:number,width:number,callback:Function) {
 let canvas:any = document.createElement('canvas')
 let context:any = canvas.getContext('2d')
 canvas.width = width
 canvas.height = height
 context.clearRect(0,0,width,height)
 context.drawImage(img,0,0,width,height)
 callback(canvas.toDataURL("image/jpeg", 0.75))
}

拖拽排序、拖拽删除

拖拽排序、拖拽到指定位置删除是通过监听touch事件来实现的。
核心思路:
1、获取到图片dom元素,给图片dom元素添加ontouchstart、ontouchend、ontouchmove 方法。
2、在ontouchstart方法中new一个时间节点,在ontouchend中也new一个时间节点,通过判断两个时间节点之间的时间间隔判断是点击事件还是长按事件。
3、ontouchstart中设置settimeout方法是延时判断是点击方法还是长按方法,如果是长按方法的则获取图片的所在页面中的位置,设置图片的位置为点击屏幕的位置,改变图片的布局方式,在ontouchmove方法中设置图片的位置跟随触摸屏幕的位置变化。
4、移动图片后松开手时,触发ontouchend方法,判断手指离开后,图片所在的位置是否处在删除的区域当中,如果在则删除图片,并且重新渲染图片列表,重新添加touch方法。
如果不在删除的区域中,则进行图片位置排序,排序后还原图片样式。并强制重新渲染图片列表。

代码如下:

Compress(img,e.path[0].height,e.path[0].width,(newImg:any) => {
 this.imgList.push(newImg)
 this.isLoading = false
 // 在这里给加入方法
 setTimeout(() => {
  this.addTouchEvent() 
 });
})



addTouchEvent(){
 let domList:any = document.querySelectorAll('.show-img')
 if (domList) {
  let domMoveFlag:boolean = true
  domList.forEach((item:any,index:any) => {
   item.ontouchstart = null
   item.ontouchmove = null
   item.ontouchend = null
   item.ontouchstart = (startEvent:any) => {
    startEvent.preventDefault()
    console.log(startEvent)
    this.touchStartTime = new Date()
    setTimeout(() => { 
     if (domMoveFlag) {  
      console.log('执行元素位置操作过程')
      this.showDeleteArea = true
      let domClient:any = item.getBoundingClientRect()
      console.log(domClient)
      this.firstPosition = {
       x:startEvent.changedTouches[0].pageX,
       y:startEvent.changedTouches[0].pageY
      }
      item.style.position = 'fixed'
      item.style.height = domClient.height + 'px'
      item.style.width = domClient.width + 'px'
      item.style.top = domClient.top + 'px'
      item.style.left = domClient.left + 'px'
      item.style.padding = 0
      item.style.zIndex = 9
      // 添加拖拽事件
      item.ontouchmove = (moveEvent:any) => {
       // console.log(moveEvent)
       item.style.top = moveEvent.changedTouches[0].pageY - this.firstPosition.y + domClient.top + 'px'
       item.style.left = moveEvent.changedTouches[0].pageX - this.firstPosition.x + domClient.left + 'px'
      }      
     }   
    }, 600);
   }
   item.ontouchend = (endEvent:any) => {
    let time:any = new Date()
    console.log(time - this.touchStartTime)
    if (time - this.touchStartTime <= 400) {
     domMoveFlag = false
     item.click()
     setTimeout(() => {
      this.addTouchEvent() 
     });
    } else {
     let newItemCenter:any = item.getBoundingClientRect()
     let centerY:any = newItemCenter.top + newItemCenter.height / 2
     let centerX:any = newItemCenter.left + newItemCenter.width / 2
     let deleteDom:any = document.querySelector(".deleteImg")
     let deleteArea:any = deleteDom.getBoundingClientRect()
     if (centerY >= deleteArea.top) {
      let _imgList = JSON.parse(JSON.stringify(this.imgList))
      let currentImg:any = _imgList.splice(index,1)
      this.imgList = []
      this.showDeleteArea = false
      setTimeout(() => {
       this.imgList = _imgList
       setTimeout(() => {
        this.addTouchEvent() 
       });
      });
      return
     }
     this.showDeleteArea = false
     // 计算所有图片元素所在页面位置
     let domParentList:any = document.querySelectorAll('.imgCtn')
     domParentList && domParentList.forEach((domParent:any,cindex:any) => {
      let domPos:any = (domParent.getBoundingClientRect())
      if ( 
       centerY >= domPos.top 
       && centerY <= domPos.bottom 
       && centerX >= domPos.left
       && centerX <= domPos.right
      ) {
       // 重新排序
       console.log('在目标区域内,重新排序')
       let _imgList = JSON.parse(JSON.stringify(this.imgList))
       let currentImg:any = _imgList.splice(index,1)
       _imgList.splice(cindex,0,...currentImg)
       this.imgList = []
       setTimeout(() => {
        this.imgList = _imgList
        setTimeout(() => {
         this.addTouchEvent() 
        });
       });
      }
     });
     // 还原样式
     item.style.position = 'absolute';
     item.style.height = '100%'
     item.style.width = '100%'
     item.style.top = '0'
     item.style.left = '0'
     item.style.padding = '10px'
    }
   }
  })
 }
}

至此,图片的上传、压缩、拖拽排序、拖拽删除功能就已经完成了。

到此这篇关于基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能的文章就介绍到这了,更多相关vue实现图片上传拖拽排序内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Vue.js 相关文章推荐
vue 表单输入框不支持focus及blur事件的解决方案
Nov 17 Vue.js
Vue如何循环提取对象数组中的值
Nov 18 Vue.js
在Vue中使用Echarts可视化库的完整步骤记录
Nov 18 Vue.js
ESLint 是如何检查 .vue 文件的
Nov 30 Vue.js
vue项目中企业微信使用js-sdk时config和agentConfig配置方式详解
Dec 15 Vue.js
vue3自定义dialog、modal组件的方法
Jan 04 Vue.js
vue keep-alive的简单总结
Jan 25 Vue.js
vue 使用饿了么UI仿写teambition的筛选功能
Mar 01 Vue.js
vite+vue3.0+ts+element-plus快速搭建项目的实现
Jun 24 Vue.js
Vue如何清空对象
Mar 03 Vue.js
vue cli4中mockjs在dev环境和build环境的配置详情
Apr 06 Vue.js
Vue操作Storage本地化存储
Apr 29 Vue.js
Vue+scss白天和夜间模式切换功能的实现方法
Jan 05 #Vue.js
jenkins自动构建发布vue项目的方法步骤
Jan 04 #Vue.js
vue3弹出层V3Popup实例详解
Jan 04 #Vue.js
vue3自定义dialog、modal组件的方法
Jan 04 #Vue.js
vue中父子组件的参数传递和应用示例
Jan 04 #Vue.js
如何在VUE中使用vue-awesome-swiper
Jan 04 #Vue.js
vue项目如何监听localStorage或sessionStorage的变化
Jan 04 #Vue.js
You might like
PHP实现的MongoDB数据库操作类分享
2014/05/12 PHP
JQuery打造PHP的AJAX表单提交实例
2009/11/03 Javascript
用JQuery 判断某个属性是否存在hasAttr的解决方法
2013/04/26 Javascript
模拟电子签章盖章效果的jQuery插件源码
2013/06/24 Javascript
JavaScript检测弹出窗口是否已经关闭的方法
2015/03/24 Javascript
jQuery验证插件validation使用指南
2015/04/21 Javascript
JavaScript数据结构与算法之链表
2016/01/29 Javascript
JavaScript实现图片自动加载的瀑布流效果
2016/04/11 Javascript
javascript面向对象程序设计高级特性经典教程(值得收藏)
2016/05/19 Javascript
总结javascript中的六种迭代器
2016/08/16 Javascript
Bootstrap popover 实现鼠标移入移除显示隐藏功能方法
2018/01/24 Javascript
jQuery实现轮播图源码
2019/10/23 jQuery
解决Vue打包上线之后部分CSS不生效的问题
2019/11/12 Javascript
Vue 组件的挂载与父子组件的传值实例
2020/09/02 Javascript
jdk1.8+vue elementui实现多级菜单功能
2020/09/24 Javascript
微信小程序实现购物车小功能
2020/12/30 Javascript
vuex的使用步骤
2021/01/06 Vue.js
浅谈python字符串方法的简单使用
2016/07/18 Python
pandas值替换方法
2018/07/10 Python
pytorch中tensor的合并与截取方法
2018/07/26 Python
python 读取摄像头数据并保存的实例
2018/08/03 Python
Python可迭代对象操作示例
2019/05/07 Python
python虚拟环境的安装和配置(virtualenv,virtualenvwrapper)
2019/08/09 Python
python隐藏类中属性的3种实现方法
2019/12/19 Python
使用TensorFlow-Slim进行图像分类的实现
2019/12/31 Python
python读取图片的几种方式及图像宽和高的存储顺序
2020/02/11 Python
idealfit英国:世界领先的女性健身用品和运动衣物品牌
2017/11/25 全球购物
土耳其新趋势女装购物网站:Addax
2020/01/07 全球购物
肯尼迪就职演说稿
2013/12/31 职场文书
促销活动计划书
2014/05/02 职场文书
保护环境建议书300字
2014/05/13 职场文书
驾驶员安全责任书范本
2014/07/24 职场文书
开服装店计划书
2014/08/15 职场文书
庆祝教师节标语
2014/10/09 职场文书
传单、海报早OUT了,另类传单营销方案送给你!
2019/07/15 职场文书
利用 SQL Server 过滤索引提高查询语句的性能分析
2021/07/15 SQL Server