基于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 组件注册全解析
Dec 17 Vue.js
vue el-upload上传文件的示例代码
Dec 21 Vue.js
vue实现轮播图帧率播放
Jan 26 Vue.js
开发一个封装iframe的vue组件
Mar 29 Vue.js
使用vue-element-admin框架从后端动态获取菜单功能的实现
Apr 29 Vue.js
vue组件的路由高亮问题解决方法
May 11 Vue.js
如何用vue实现网页截图你知道吗
Nov 17 Vue.js
vue项目中的支付功能实现(微信支付和支付宝支付)
Feb 18 Vue.js
VUE解决跨域问题Access to XMLHttpRequest at
May 06 Vue.js
Vue组件化(ref,props, mixin,.插件)详解
May 15 Vue.js
Vue Mint UI mt-swipe的使用方式
Jun 05 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
广播爱好者需要了解的天线知识
2021/03/01 无线电
Uchome1.2 1.5 代码学习 common.php
2009/04/24 PHP
PHP写UltraEdit插件脚本实现方法
2011/12/26 PHP
php setcookie函数的参数说明及其用法
2014/04/20 PHP
PHP使用pcntl_fork实现多进程下载图片的方法
2014/12/16 PHP
php通过文件流方式复制文件的方法
2015/03/13 PHP
Laravel框架处理用户的请求操作详解
2019/12/20 PHP
Javascript操纵Cookie实现购物车程序
2006/11/23 Javascript
javascript multibox 全选
2009/03/22 Javascript
javascript setinterval 的正确语法如何书写
2014/06/17 Javascript
微信小程序 for 循环详解
2016/10/09 Javascript
jquery的父、子、兄弟节点查找,节点的子节点循环方法
2016/12/07 Javascript
微信小程序实现图片预加载组件
2017/01/18 Javascript
微信小程序 跳转方式总结
2017/04/20 Javascript
详解如何使用Node.js编写命令工具——以vue-cli为例
2017/06/29 Javascript
使用 vue-i18n 切换中英文效果
2018/05/23 Javascript
深入理解移动前端开发之viewport
2018/10/19 Javascript
Vue中Table组件Select的勾选和取消勾选事件详解
2019/03/19 Javascript
微信小程序开发实现的IP地址查询功能示例
2019/03/28 Javascript
VUE的history模式下除了index外其他路由404报错解决办法
2019/08/21 Javascript
[52:10]LGD vs Optic Supermajor小组赛D组胜者组决赛 BO3 第二场 6.3
2018/06/04 DOTA
python感知机实现代码
2019/01/18 Python
python列表,字典,元组简单用法示例
2019/07/11 Python
pytorch 预训练层的使用方法
2019/08/20 Python
python中with用法讲解
2020/02/07 Python
python爬虫开发之selenium模块详细使用方法与实例全解
2020/03/09 Python
Python super()函数使用及多重继承
2020/05/06 Python
HTML5之SVG 2D入门12—SVG DOM及DOM操作介绍
2013/01/30 HTML / CSS
应届毕业生的自我鉴定
2013/11/13 职场文书
岳父生日宴会答谢词
2014/01/13 职场文书
会计专业求职信范文
2014/03/16 职场文书
《秋游》教学反思
2014/04/24 职场文书
敲诈同学钱财检讨书范文
2014/11/18 职场文书
2016初一新生军训心得体会
2016/01/11 职场文书
MySQL 使用事件(Events)完成计划任务
2021/05/24 MySQL
Java Kafka 消费积压监控的示例代码
2021/07/01 Java/Android