用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' } } }) } }
至此,图片的上传、压缩、拖拽排序、拖拽删除功能就已经完成了。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- Tank《我不伟大,至少我能改变我。》[FLAC/分轨][236.89MB]
- CD圣经推荐-夏韶声《谙2》SACD-ISO
- 钟镇涛-《百分百钟镇涛》首批限量版SACD-ISO
- 群星《继续微笑致敬许冠杰》[低速原抓WAV+CUE]
- 潘秀琼.2003-国语难忘金曲珍藏集【皇星全音】【WAV+CUE】
- 林东松.1997-2039玫瑰事件【宝丽金】【WAV+CUE】
- 谭咏麟.2022-倾·听【环球】【WAV+CUE】
- 4complete《丛生》[320K/MP3][85.26MB]
- 4complete《丛生》[FLAC/分轨][218.01MB]
- 羽泉《给未来的你&天黑天亮》[WAV+CUE][968M]
- 庄心妍《我也许在等候》[低速原抓WAV+CUE]
- 王雅洁《小调歌后2》[原抓WAV+CUE]
- 中国武警男声合唱团《辉煌之声1天路》[DTS-WAV分轨]
- 紫薇《旧曲新韵》[320K/MP3][175.29MB]
- 紫薇《旧曲新韵》[FLAC/分轨][550.18MB]