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

 更新时间:2021年01月05日 11:44:11   作者:前端小白菜~  
这篇文章主要介绍了基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

用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实现监听dom节点宽高变化方式

    Vue实现监听dom节点宽高变化方式

    这篇文章主要介绍了Vue实现监听dom节点宽高变化方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • Vue3 vite配置css 的sourceMap及文件引用配置别名的过程

    Vue3 vite配置css 的sourceMap及文件引用配置别名的过程

    这篇文章主要介绍了Vue3 vite配置css的sourceMap,及文件引用配置别名的过程,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • Vue qiankun微前端实现详解

    Vue qiankun微前端实现详解

    这篇文章主要为大家介绍了Vue qiankun微前端实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • vue.js实现的全选与全不选功能示例【基于elementui】

    vue.js实现的全选与全不选功能示例【基于elementui】

    这篇文章主要介绍了vue.js实现的全选与全不选功能,结合实例形式分析了vue.js基于elementui实现全选与全不选功能的相关页面渲染、初始化数据及功能函数等相关操作技巧,需要的朋友可以参考下
    2018-12-12
  • vue中手动封装iconfont组件解析(三种引用方式的封装和使用)

    vue中手动封装iconfont组件解析(三种引用方式的封装和使用)

    这篇文章主要介绍了vue中手动封装iconfont组件(三种引用方式的封装和使用),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • 关于vue-router路由的传参方式params query

    关于vue-router路由的传参方式params query

    这篇文章主要介绍了关于vue-router路由的传参方式params query,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • Vue3计算属性computed和监听属性watch区别解析

    Vue3计算属性computed和监听属性watch区别解析

    计算属性适用于对已有的数据进行计算,派生新的数据,并在模板中使用;而监听属性适用于监听数据的变化,并执行一些特定的操作,根据具体的需求和场景,选择适合的机制这篇文章主要介绍了Vue3计算属性computed和监听属性watch,需要的朋友可以参考下
    2024-02-02
  • vue之debounce属性被移除及处理详解

    vue之debounce属性被移除及处理详解

    今天小编就为大家分享一篇vue之debounce属性被移除及处理详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • vue之webpack -v报错解决方案总结

    vue之webpack -v报错解决方案总结

    这篇文章主要介绍了vue之webpack -v报错解决方案总结,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • Vue 与 Vuex 的第一次接触遇到的坑

    Vue 与 Vuex 的第一次接触遇到的坑

    在 Vue.js 的项目中,如果项目结构简单, 父子组件之间的数据传递可以使用 props 或者 $emit 等方式,如果是大型项目,很多时候都需要在子组件之间传递数据,使用vue的状态管理工具vuex很好的解决
    2018-08-08

最新评论