feat: 首次提交
This commit is contained in:
373
components/firstui/fui-drag/fui-drag.vue
Normal file
373
components/firstui/fui-drag/fui-drag.vue
Normal file
@ -0,0 +1,373 @@
|
||||
<!--本文件由FirstUI授权予新疆天衡创新研究院有限公司(手机号: 1861 4072 54 9,身份证尾号:5A07X5)专用,请尊重知识产权,勿私下传播,违者追究法律责任。-->
|
||||
<template>
|
||||
<!-- #ifndef APP-VUE || MP-WEIXIN || H5 -->
|
||||
<view class="fui-drag__wrap" ref="fui_drag" :id="elId"
|
||||
:style="{width:wrapWidth+'px',height:(rows * cellHeight)+'px'}"
|
||||
:class="[dragging?'fui-drag-item__show':'fui-drag-item__hidden']">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-VUE || MP-WEIXIN || H5 -->
|
||||
<!-- vue3下编译到小程序data数据与wxs混用中无法获取 $data数据无法直接应用到页面,uni-app官方编译bug-->
|
||||
<view class="fui-drag__wrap" :catch:touchmove="wxDrag?true:''"
|
||||
:class="[dragging?'fui-drag-item__show':'fui-drag-item__hidden']" ref="fui_drag" :id="elId"
|
||||
:style="{width:wrapWidth+'px',height:(rows * cellHeight)+'px'}" :list="list"
|
||||
:change:list="handler.listChange" :param="param" :change:param="handler.paramChange">
|
||||
<view class="fui-drag-item__wrap" :style="{width:cellWidth+'px',height:cellHeight+'px'}"
|
||||
v-for="(item, index) in list" :key="item.id" :data-index="index" @longpress="handler.longPress"
|
||||
:data-param="param" :data-isdrag="isDrag && dragging?1:0" @touchstart="handler.touchStart"
|
||||
@touchmove="handler.touchMove" @touchend="handler.touchEnd" @mousedown="handler.mousedown"
|
||||
@tap="itemClick(index)">
|
||||
<template v-if="custom">
|
||||
<slot :model="item.entity" :width="cellWidth" :height="cellHeight" :index="index"></slot>
|
||||
</template>
|
||||
<template v-else>
|
||||
<f-drag-item @delete="deleteItem" :src="(item.entity && item.entity.src) || 'true'"
|
||||
:text="item.entity && item.entity.text" :width="cellWidth" :height="cellHeight"
|
||||
:styles="styles" :index="index">
|
||||
</f-drag-item>
|
||||
</template>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<view fireEventSync="true" class="fui-drag-item__wrap" v-for="(item, index) in list" :key="item.id"
|
||||
:style="{width:cellWidth+'px',height:cellHeight+'px'}" @touchstart="touchstart"
|
||||
@touchmove="touchmove" @touchend="touchend" @longpress="longPress" :data-index="index"
|
||||
:ref="'f_drag_'+index">
|
||||
<template v-if="custom">
|
||||
<slot :model="item.entity" :width="cellWidth" :height="cellHeight" :index="index"></slot>
|
||||
</template>
|
||||
<template v-else>
|
||||
<f-drag-item @delete="deleteItem" :src="item.entity && item.entity.src"
|
||||
:text="item.entity && item.entity.text" :width="cellWidth" :height="cellHeight"
|
||||
:styles="styles" :index="index">
|
||||
</f-drag-item>
|
||||
</template>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifndef APP-PLUS || MP-WEIXIN || H5-->
|
||||
<view class="fui-drag-item__wrap"
|
||||
:class="{'fui-drag__cur':current===index,'fui-drag__trans':current!==index}"
|
||||
v-for="(item, index) in list" :key="item.id"
|
||||
:style="{width:cellWidth+'px',height:cellHeight+'px',transform: `translate3d(${index === current ? transX : item.transX}, ${index === current ? transY: item.transY}, 0px)`}"
|
||||
@touchstart="touchstart" @touchmove.stop.prevent="touchmove" @touchend="touchend"
|
||||
@longpress="longPress" :data-index="index">
|
||||
<template v-if="custom">
|
||||
<slot :model="item.entity" :width="cellWidth" :height="cellHeight" :index="index"></slot>
|
||||
</template>
|
||||
<template v-else>
|
||||
<f-drag-item @delete="deleteItem" :src="(item.entity && item.entity.src) || ''"
|
||||
:text="item.entity && item.entity.text" :width="cellWidth" :height="cellHeight"
|
||||
:styles="styles" :index="index">
|
||||
</f-drag-item>
|
||||
</template>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
<!-- #ifdef APP-VUE || MP-WEIXIN || H5-->
|
||||
<script src="./index.wxs" module="handler" lang="wxs"></script>
|
||||
<!-- #endif -->
|
||||
<script>
|
||||
// #ifdef APP-NVUE
|
||||
const dom = uni.requireNativePlugin('dom');
|
||||
// #endif
|
||||
import fDragItem from './f-drag-item.vue'
|
||||
import bindingx from './bindingx.js'
|
||||
import mpjs from './mpjs.js'
|
||||
export default {
|
||||
name: "fui-drag",
|
||||
mixins: [mpjs, bindingx],
|
||||
emits: ['change', 'end', 'click', 'delete'],
|
||||
components: {
|
||||
fDragItem
|
||||
},
|
||||
props: {
|
||||
itemList: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
width: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
// 每行显示个数
|
||||
columns: {
|
||||
type: [Number, String],
|
||||
default: 1
|
||||
},
|
||||
//必传(square为true时失效)
|
||||
itemHeight: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
// 是否正方形显示,为true时itemHeight失效
|
||||
square: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
// 页面滚动高度
|
||||
scrollTop: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
//是否可拖拽
|
||||
isDrag: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
custom: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
itemList(val) {
|
||||
this.list = []
|
||||
setTimeout(() => {
|
||||
this.reset()
|
||||
}, 0);
|
||||
},
|
||||
width(val) {
|
||||
this.list = []
|
||||
setTimeout(() => {
|
||||
this.reset()
|
||||
}, 0);
|
||||
},
|
||||
columns(val) {
|
||||
this.list = []
|
||||
setTimeout(() => {
|
||||
this.reset()
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const elId = `fui_${Math.ceil(Math.random() * 10e5).toString(36)}`
|
||||
return {
|
||||
elId,
|
||||
// #ifdef APP-VUE || MP-WEIXIN || H5
|
||||
param: {},
|
||||
// #endif
|
||||
windowHeight: 0,
|
||||
wrapWidth: 0,
|
||||
wrapHeight: 0,
|
||||
cellWidth: 0,
|
||||
cellHeight: 0,
|
||||
changeList: [],
|
||||
rows: 3,
|
||||
options: [],
|
||||
dragging: true,
|
||||
wrapTop: 0,
|
||||
wrapLeft: 0,
|
||||
list: [],
|
||||
wxDrag: true
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.reset();
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getId() {
|
||||
return `${Math.ceil(Math.random() * 10e5).toString(36)}_${new Date().getTime()}`
|
||||
},
|
||||
getWidth(fn) {
|
||||
let width = Number(this.width)
|
||||
let sys = uni.getSystemInfoSync()
|
||||
this.windowHeight = sys.windowHeight;
|
||||
if (width === 0) {
|
||||
width = sys.windowWidth
|
||||
} else {
|
||||
width = uni.upx2px(width)
|
||||
}
|
||||
this.wrapWidth = width
|
||||
//此处小数会导致出现误差
|
||||
this.cellWidth = width / Number(this.columns)
|
||||
let cellHeight = uni.upx2px(this.itemHeight)
|
||||
if (this.square) {
|
||||
cellHeight = this.cellWidth
|
||||
}
|
||||
this.cellHeight = cellHeight
|
||||
fn && fn()
|
||||
},
|
||||
reset() {
|
||||
this.options = []
|
||||
// #ifndef APP-NVUE
|
||||
this.wxDrag = true;
|
||||
this.dragging = false
|
||||
// #endif
|
||||
this.getWidth(() => {
|
||||
setTimeout(() => {
|
||||
this.init()
|
||||
}, 0);
|
||||
})
|
||||
},
|
||||
getDom(callback, index = 0) {
|
||||
// #ifndef APP-NVUE
|
||||
uni.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this)
|
||||
// #endif
|
||||
.select(`#${this.elId}`)
|
||||
.boundingClientRect()
|
||||
.exec(ret => {
|
||||
if (index >= 10) return
|
||||
if (!ret && !ret[0]) {
|
||||
index++
|
||||
this.getDom(callback, index)
|
||||
return
|
||||
}
|
||||
let wrapTop = ret[0].top + this.scrollTop;
|
||||
let wrapLeft = ret[0].left
|
||||
callback && callback(wrapTop, wrapLeft)
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
dom.getComponentRect(this.$refs['fui_drag'], (ret) => {
|
||||
if (ret && ret.size) {
|
||||
let wrapTop = ret.size.top + this.scrollTop;
|
||||
let wrapLeft = ret.size.left
|
||||
callback && callback(wrapTop, wrapLeft)
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
init(index = 0) {
|
||||
let options = JSON.parse(JSON.stringify(this.itemList));
|
||||
let columns = Number(this.columns)
|
||||
this.rows = Math.ceil(options.length / this.columns);
|
||||
if (options.length === 0) return;
|
||||
setTimeout(() => {
|
||||
this.getDom((wrapTop, wrapLeft) => {
|
||||
let list = options.map((item, index) => {
|
||||
return {
|
||||
id: this.getId(),
|
||||
realKey: index,
|
||||
sortKey: index,
|
||||
//若有误差,cellWidth、cellHeight取整
|
||||
transX: `${index%columns * this.cellWidth}px`,
|
||||
transY: `${Math.floor(index/columns) * this.cellHeight}px`,
|
||||
entity: item
|
||||
}
|
||||
});
|
||||
this.changeList = list;
|
||||
this.list = list
|
||||
this.wrapTop = wrapTop;
|
||||
this.wrapLeft = wrapLeft;
|
||||
// #ifdef APP-VUE || MP-WEIXIN || H5
|
||||
this.param = {
|
||||
windowHeight: this.windowHeight,
|
||||
columns: Number(this.columns),
|
||||
rows: this.rows,
|
||||
cellWidth: this.cellWidth,
|
||||
cellHeight: this.cellHeight,
|
||||
wrapLeft: this.wrapLeft,
|
||||
wrapTop: this.wrapTop
|
||||
};
|
||||
// #endif
|
||||
this.dragging = true
|
||||
})
|
||||
}, 500)
|
||||
},
|
||||
drag(e) {
|
||||
this.wxDrag = e.wxdrag;
|
||||
},
|
||||
sortend(e) {
|
||||
this.$emit('end', {
|
||||
itemList: e.itemList
|
||||
});
|
||||
},
|
||||
change(e) {
|
||||
this.$emit('change', {
|
||||
itemList: e.itemList
|
||||
});
|
||||
},
|
||||
itemClick(index) {
|
||||
if (!this.changeList || this.changeList.length === 0) return;
|
||||
let item = this.changeList[index];
|
||||
this.$emit('click', {
|
||||
index: item.realKey,
|
||||
item: item.entity
|
||||
});
|
||||
},
|
||||
deleteItem(e) {
|
||||
this.$emit('delete', {
|
||||
index: e.index
|
||||
});
|
||||
},
|
||||
listChange(e) {
|
||||
this.changeList = e.itemList;
|
||||
},
|
||||
pageScroll(e) {
|
||||
// #ifndef APP-NVUE
|
||||
uni.pageScrollTo({
|
||||
scrollTop: e.scrollTop,
|
||||
duration: 0
|
||||
});
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fui-drag__wrap {
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
transform: translate3d(0, 0, 0);
|
||||
/* #endif */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fui-drag-item__wrap {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1;
|
||||
/* #ifdef H5 */
|
||||
cursor: grab;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.fui-drag-item__hidden {
|
||||
opacity: 0;
|
||||
transition-property: opacity;
|
||||
transition-duration: .35s;
|
||||
}
|
||||
|
||||
.fui-drag-item__show {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.fui-drag__trans {
|
||||
transition-property: transform;
|
||||
transition-duration: .35s;
|
||||
}
|
||||
|
||||
.fui-drag__trans-end {
|
||||
transition-property: transform;
|
||||
transition-duration: .35s;
|
||||
}
|
||||
|
||||
.fui-drag__cur {
|
||||
z-index: 5 !important;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user