基于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使用echarts图表自适应的几种解决方案
Dec 04 Vue.js
vue-router定义元信息meta操作
Dec 07 Vue.js
vue 使用class创建和清除水印的示例代码
Dec 25 Vue.js
在vue项目中封装echarts的步骤
Dec 25 Vue.js
vue动态设置路由权限的主要思路
Jan 13 Vue.js
Vue使用Ref跨层级获取组件的步骤
Jan 25 Vue.js
vue 使用饿了么UI仿写teambition的筛选功能
Mar 01 Vue.js
详解Vue的options
May 15 Vue.js
Vue vee-validate插件的简单使用
Jun 22 Vue.js
vue ref如何获取子组件属性值
Mar 31 Vue.js
Vue+TypeScript中处理computed方式
Apr 02 Vue.js
vue如何在data中引入图片的正确路径
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
基于empty函数的判断详解
2013/06/17 PHP
使用PHP下载CSS文件中的图片的代码
2013/09/24 PHP
PHP连接MySQL的2种方法小结以及防止乱码
2014/03/11 PHP
10个实用的PHP正则表达式汇总
2014/10/23 PHP
php上传文件常见问题总结
2015/02/03 PHP
php获取开始与结束日期之间所有日期的方法
2016/11/29 PHP
php求斐波那契数的两种实现方式【递归与递推】
2019/09/09 PHP
JQuery获取元素文档大小、偏移和位置和滚动条位置的方法集合
2010/01/12 Javascript
JQuery插件开发示例代码
2013/11/06 Javascript
当某个文本框成为焦点时即清除文本框内容
2014/04/28 Javascript
javascript函数中的3个高级技巧
2016/09/22 Javascript
详解js的异步编程技术的方法
2017/02/09 Javascript
JS中IP地址与整数相互转换的实现代码
2017/04/10 Javascript
JavaScript之promise_动力节点Java学院整理
2017/07/03 Javascript
ES7中利用Await减少回调嵌套的方法详解
2017/11/01 Javascript
微信小程序实现自上而下字幕滚动
2018/07/14 Javascript
vue实现前台列表数据过滤搜索、分页效果
2019/05/28 Javascript
微信小程序官方动态自定义底部tabBar的例子
2019/09/04 Javascript
浅谈Vue3.0新版API之composition-api入坑指南
2020/04/30 Javascript
详解vue v-model
2020/08/31 Javascript
关于Vue中$refs的探索浅析
2020/11/05 Javascript
Python 中迭代器与生成器实例详解
2017/03/29 Python
python版本五子棋的实现代码
2018/12/11 Python
Django上使用数据可视化利器Bokeh解析
2019/07/31 Python
Python解压 rar、zip、tar文件的方法
2019/11/19 Python
python正则表达式匹配IP代码实例
2019/12/28 Python
python_array[0][0]与array[0,0]的区别详解
2020/02/18 Python
Python3 操作 MySQL 插入一条数据并返回主键 id的实例
2020/03/02 Python
jupyter notebook 恢复误删单元格或者历史代码的实现
2020/04/17 Python
New Balance澳大利亚官网:运动鞋和健身服装
2019/02/23 全球购物
奶茶店创业计划书范文
2014/01/17 职场文书
内衣营销方案
2014/03/15 职场文书
教师一岗双责责任书
2014/04/16 职场文书
廉洁校园实施方案
2014/05/25 职场文书
CSS3 制作的书本翻页特效
2021/04/13 HTML / CSS
css中:last-child不生效的解决方法
2022/08/05 HTML / CSS