Vue實(shí)現(xiàn)移動(dòng)端拖拽交換位置
更新時(shí)間:2020年07月29日 09:16:47 作者:jeft_hai
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)移動(dòng)端拖拽交換位置,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
本文實(shí)例為大家分享了Vue實(shí)現(xiàn)移動(dòng)端拖拽交換位置的具體代碼,供大家參考,具體內(nèi)容如下
<template>
<div class="imageUploaderPage">
<ul ref='imgList' class="imgList">
<li ref='imgItem' class="imgCoverItem" v-for='(item, index) in filesResults' :key='index' @click="deleteImage(index)"
:data-index='index'
@touchstart="touchstart($event, item, index)"
@touchmove="touchmove($event)"
@touchend="touchend($event)" >
<img :id="'avarimgs' + index" :src="item">
</li>
<li class="imgCoverItem upLoadImageWrapper">
<input ref='upLoadImageFile' id='upLoadImage' type='file' multiple="multiple" accept="image/*" @change="change" />
</li>
</ul>
<p>點(diǎn)擊圖片刪除, 拖拽可更改順序,共4張</p>
<div class="btnConfimList" v-show="DeleteImageMask">
<div class="btnConfimListMask" @click='setDelete(false)'></div>
<transition name="transTop">
<div class="btnConfimListContent">
<ul>
<li class="borderT" >刪除該圖片?</li>
<li class="borderT" @click='setDelete(true)' style="color: var(--mRed);">刪除</li>
</ul>
<p class="cancelDeleteImage" @click='setDelete(false)'>取消</p>
</div>
</transition>
</div>
</div>
</template>
<script>
export default {
data () {
return {
files: [],
fileItem: {},
filesResults: [],
DeleteImageMask: false,
// isShow:false,
startX: 0, // 開始觸摸的位置
startY: 0,
moveX: 0, // 滑動(dòng)時(shí)的位置
moveY: 0,
endX: 0,
endY: 0, // 結(jié)束觸摸的位置
disX: 0, // 移動(dòng)距離
disY: 0,
slideEffect: [], // 滑動(dòng)時(shí)的效果
target: null,
startIndex: null,
zindex: 1,
leftW: 0,
targetW: 0,
clientW: 0,
targetX: 0,
targetY: 0,
allItems: [],
targetIndex: null
}
},
// computed: {
// toRightW () { return (this.leftW + this.targetW) * (this.startIndex + 1) - this.startX },
// toLeftW () { return this.startX - (this.leftW + this.targetW) * this.startIndex },
// toTopH () { return this.startY - parseInt(this.startIndex / 4) * (this.topH + this.targetW) },
// toBottomH () { return (this.topH + this.targetW) - this.startY + (this.leftW + this.targetW) * (parseInt(this.startIndex / 4)) }
// },
mounted () {
this.$nextTick(() => {
this.absoluteItems()
})
},
watch: {
slideEffect (newV) {
return newV
}
},
methods: {
change (e) {
var fileItem = e.target.files
let me = this
for (let i = e.target.files.length - 1; i >= 0; i--) {
var reader = new FileReader()
var file = e.target.files[i]
reader.onloadstart = function (e) {
// console.log('開始讀取....')
}
reader.onprogress = function (e) {
// console.log('正在讀取中....')
}
reader.onabort = function (e) {
// console.log('中斷讀取....')
}
reader.onerror = function (e) {
// console.log('讀取異常....')
}
reader.onload = function (e) {
if (me.filesResults.indexOf(e.target.result) >= 0) {
me.$toast('請(qǐng)勿重復(fù)上傳')
return
}
if (me.files.length >= 7) {
me.$toast('最多上傳4張圖片')
return
}
me.files.unshift(fileItem)
me.filesResults.unshift(e.target.result)
}
reader.readAsDataURL(file)
}
},
absoluteItems () {
for (let i = 0; i < 8; i++) {
this.allItems = []
}
},
deleteImage (index) {
this.curIndex = index
this.DeleteImageMask = true
},
setDelete (data) {
this.DeleteImageMask = false
this.curIndex = null
data && this.curIndex >= 0 && this.files.splice(this.curIndex, 1) && this.filesResults.splice(this.curIndex, 1)
},
touchstart (e, item, index) {
this.startIndex = index
this.targetIndex = index
this.target = e.target.nodeName.toLowerCase() === 'li' ? e.target : e.target.parentNode
!this.leftW && (this.leftW = this.target.parentNode.querySelectorAll('li')[0].getBoundingClientRect().left)
!this.topH && (this.topH = this.target.parentNode.querySelectorAll('li')[0].getBoundingClientRect().top)
!this.targetW && (this.targetW = this.target.offsetWidth)
!this.clientW && (this.clientW = this.leftW + this.targetW)
this.zindex++
this.target.style.zIndex = this.zindex
this.startX = e.touches[0].clientX
this.startY = e.touches[0].clientY
},
touchmove (ev) {
ev = ev || window.event
ev.preventDefault()
if (ev.touches.length === 1) {
this.moveX = ev.touches[0].clientX
this.moveY = ev.touches[0].clientY
this.disX = this.moveX - this.startX
this.disY = this.moveY - this.startY
// 邊界處理
this.disY <= 0 && (this.disY = 0)
this.disY >= (this.$refs.imgList.offsetHeight - this.clientW) && (this.disY = this.$refs.imgList.offsetHeight - this.clientW)
this.target.style.transform = 'translate3d(' + this.disX + 'px,' + this.disY + 'px, 0)'
this.target.getBoundingClientRect().left <= 0 && (this.target.style.transform = 'translate3d(' + (-this.clientW * this.startIndex) + 'px,' + this.disY + 'px, 0)')
this.target.getBoundingClientRect().right >= this.$refs.imgList.offsetWidth && (this.target.style.transform = 'translate3d(' + this.clientW * (3 - this.startIndex) + 'px,' + this.disY + 'px, 0)')
for (let i = 0; i < this.filesResults.length; i++) {
// && this.moveY > this.$refs.imgItem[i].getBoundingClientRect().top && this.moveY < this.$refs.imgItem[i].getBoundingClientRect().top + this.targetW
if (this.moveX >= this.$refs.imgItem[i].getBoundingClientRect().left && this.moveX < this.$refs.imgItem[i].getBoundingClientRect().left + this.targetW && (i !== this.startIndex)) {
if (i > this.targetIndex && this.moveX >= this.$refs.imgItem[i].getBoundingClientRect().left && this.moveX < this.$refs.imgItem[i].getBoundingClientRect().left + this.targetW) {
if (this.$refs.imgItem[i].style.transform) {
if (this.$refs.imgItem[i].style.transform === 'translate3d(0px, 0px, 0px)') {
this.$refs.imgItem[i].style.transform = 'translate3d(' + (-this.clientW) + 'px, 0, 0)'
this.targetIndex = i
} else {
this.$refs.imgItem[i].style.transform = 'translate3d(0px, 0px, 0px)'
this.targetIndex = i - 1
}
} else {
this.$refs.imgItem[i].style.transform = 'translate3d(' + (-this.clientW) + 'px, 0, 0)'
this.targetIndex = i
}
} else if (i < this.targetIndex && this.moveX >= this.$refs.imgItem[i].getBoundingClientRect().left && this.moveX < this.$refs.imgItem[i].getBoundingClientRect().left + this.targetW) {
if (this.$refs.imgItem[i].style.transform) {
if (this.$refs.imgItem[i].style.transform === 'translate3d(0px, 0px, 0px)') {
this.$refs.imgItem[i].style.transform = 'translate3d(' + (this.clientW) + 'px, 0, 0)'
this.targetIndex = i
} else {
this.$refs.imgItem[i].style.transform = 'translate3d(0px, 0px, 0px)'
this.targetIndex = i + 1
}
} else {
this.$refs.imgItem[i].style.transform = 'translate3d(' + (this.clientW) + 'px, 0, 0)'
this.targetIndex = i
}
} else {
this.targetIndex > this.startIndex && (this.targetIndex = i - 1)
this.targetIndex < this.startIndex && (this.targetIndex = i + 1)
}
}
}
}
},
touchend (e) {
this.target.style.transform = 'translate3d(' + (this.targetIndex - this.startIndex) * (this.leftW + this.targetW) + 'px,' + this.targetY + 'px, 0)'
let start = this.filesResults.splice(this.startIndex, 1)[0]
this.filesResults.splice(this.targetIndex, 0, start)
for (let i = 0; i < this.filesResults.length; i++) {
this.$refs.imgItem[i].style.transform = 'none'
}
}
}
}
</script>
<style lang="less">
.imageUploaderPage{
background: #f0f0f3;
color: #a8a8a8;
overflow: hidden;
p{
text-align: center;
color: #a7a7a7;
height: 4.07vw;
line-height: 4.07vw;
font-size: var(--mText);
margin-bottom: var(--nText);
}
.imgList{
padding: 2.78vw 0;
font-size: 0;
position: relative;
.imgCoverItem{
position: relative;
width: 23.25vw;
height: 23.25vw;
border-radius: 1.11vw;
display: inline-block;
vertical-align: top;
overflow: hidden;
margin-left: 1.4vw;
margin-bottom: 1.4vw;
}
.upLoadImageWrapper{
position: relative;
background: #e0e0e0;
#upLoadImage{
position: absolute;
outline: none;
z-index: 1;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
}
}
}
}
</style>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Vue實(shí)現(xiàn)數(shù)據(jù)篩選與搜索功能的示例代碼
在許多Web應(yīng)用程序中,數(shù)據(jù)篩選和搜索是關(guān)鍵的用戶體驗(yàn)功能,本文將深入探討在Vue中如何進(jìn)行數(shù)據(jù)篩選與搜索的實(shí)現(xiàn),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10
vue實(shí)現(xiàn)excel文件的導(dǎo)入和讀取完整步驟
Vue的數(shù)據(jù)綁定功能非常強(qiáng)大,很適合用來(lái)讀取Excel內(nèi)容,這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)excel文件的導(dǎo)入和讀取的相關(guān)資料,文中通過(guò)代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10
前端項(xiàng)目vue3/React如何使用pako庫(kù)解壓縮后端返回gzip數(shù)據(jù)
pako是一個(gè)流行的JS庫(kù),用于在瀏覽器中進(jìn)行數(shù)據(jù)壓縮和解壓縮操作,它提供了對(duì)常見(jiàn)的壓縮算法的實(shí)現(xiàn),使開發(fā)者能夠在客戶端上輕松進(jìn)行數(shù)據(jù)壓縮和解壓縮,這篇文章主要介紹了前端項(xiàng)目vue3/React使用pako庫(kù)解壓縮后端返回gzip數(shù)據(jù),需要的朋友可以參考下2024-07-07
Vant?Weapp組件picker選擇器初始默認(rèn)選中問(wèn)題
這篇文章主要介紹了Vant?Weapp組件picker選擇器初始默認(rèn)選中問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
Vue項(xiàng)目接入Paypal實(shí)現(xiàn)示例詳解
這篇文章主要介紹了Vue項(xiàng)目接入Paypal實(shí)現(xiàn)示例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06

