基于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使用Element实现增删改查+打包的步骤
Nov 25 Vue.js
使用vue编写h5公众号跳转小程序的实现代码
Nov 27 Vue.js
vue3.0实现插件封装
Dec 14 Vue.js
Vue 简单实现前端权限控制的示例
Dec 25 Vue.js
vue 递归组件的简单使用示例
Jan 14 Vue.js
vue如何使用rem适配
Feb 06 Vue.js
vue 数据双向绑定的实现方法
Mar 04 Vue.js
详解Vue的options
May 15 Vue.js
详解Vue slot插槽
Nov 20 Vue.js
vue使用localStorage持久性存储实现评论列表
Apr 14 Vue.js
详解Vue3使用axios的配置教程
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面向对象编程快速入门
2006/12/14 PHP
php 无限级 SelectTree 类
2009/05/19 PHP
谈PHP生成静态页面分析 模板+缓存+写文件
2009/08/17 PHP
js禁止页面复制功能禁用页面右键菜单示例代码
2013/08/29 Javascript
Jquery如何实现点击时高亮显示代码
2014/01/22 Javascript
编写高效jQuery代码的4个原则和5个技巧
2014/04/24 Javascript
使用javascript实现json数据以csv格式下载
2015/01/09 Javascript
JavaScript中Number.MAX_VALUE属性的使用方法
2015/06/04 Javascript
极力推荐10个短小实用的JavaScript代码段
2016/08/03 Javascript
ng-options和ng-checked在表单中的高级运用(推荐)
2017/01/21 Javascript
VUE开发一个图片轮播的组件示例代码
2017/03/06 Javascript
js+html5实现侧滑页面效果
2017/07/15 Javascript
jQuery+HTML5实现WebGL高性能烟花绽放动画效果【附demo源码下载】
2017/08/18 jQuery
js链表操作(实例讲解)
2017/08/29 Javascript
js合并两个数组生成合并后的key:value数组
2018/05/09 Javascript
详解React native fetch遇到的坑
2018/08/30 Javascript
小白教程|一小时上手最流行的前端框架vue(推荐)
2019/04/10 Javascript
[04:32]DOTA2著名解说配音敌法师 现场专访海涛怒切假腿
2013/12/20 DOTA
Python警察与小偷的实现之一客户端与服务端通信实例
2014/10/09 Python
python获取当前用户的主目录路径方法(推荐)
2017/01/12 Python
python requests使用socks5的例子
2019/07/25 Python
django+tornado实现实时查看远程日志的方法
2019/08/12 Python
将matplotlib绘图嵌入pyqt的方法示例
2020/01/08 Python
500行python代码实现飞机大战
2020/04/24 Python
Python内置异常类型全面汇总
2020/05/28 Python
使用Django的JsonResponse返回数据的实现
2021/01/15 Python
详解Canvas实用库Fabric.js使用手册
2019/01/07 HTML / CSS
找到不普通的东西:Bonanza
2016/10/20 全球购物
英国领先的家庭时尚品牌:Peacocks
2018/01/11 全球购物
印度和世界各地的精美产品:Ikka Dukka
2018/02/12 全球购物
法国票务网站:Ticketmaster法国
2018/07/09 全球购物
社区包粽子活动方案
2014/01/21 职场文书
学校先进集体事迹材料
2014/05/31 职场文书
异地年检委托书范本
2014/09/24 职场文书
环境卫生整治简报
2015/07/20 职场文书
Javascript使用integrity属性进行安全验证
2021/11/07 Javascript