feat: 首次提交
This commit is contained in:
201
components/firstui/fui-drag/bindingx.js
Normal file
201
components/firstui/fui-drag/bindingx.js
Normal file
@ -0,0 +1,201 @@
|
||||
// 本文件由FirstUI授权予新疆天衡创新研究院有限公司(手机号:18 614 07 2 5 4 9,身份证尾号:5A07X5)专用,请尊重知识产权,勿私下传播,违者追究法律责任。
|
||||
// #ifdef APP-NVUE
|
||||
const animation = uni.requireNativePlugin('animation');
|
||||
export default {
|
||||
watch: {
|
||||
list(vals) {
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.getRefs(vals)
|
||||
}, 50)
|
||||
})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
current: -1,
|
||||
startTouch: null,
|
||||
tDragging: false,
|
||||
sId: null,
|
||||
preStartKey: null,
|
||||
isAndroid: false,
|
||||
divisor: 1/2
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const res = uni.getSystemInfoSync();
|
||||
this.isAndroid = res.platform.toLocaleLowerCase() == "android"
|
||||
this.divisor = this.isAndroid ? 5/4 : 1/2
|
||||
this.allRefs = []
|
||||
},
|
||||
methods: {
|
||||
getEl(el) {
|
||||
return el.ref || el[0].ref;
|
||||
},
|
||||
getRefs(vals) {
|
||||
this.allRefs = []
|
||||
if (!vals || vals.length === 0) return;
|
||||
vals.forEach((item, index) => {
|
||||
let ref = this.getEl(this.$refs[`f_drag_${index}`])
|
||||
this.allRefs.push(ref)
|
||||
this._animation(ref, index, item.transX, item.transY)
|
||||
})
|
||||
},
|
||||
_animation(ref, index, x, y) {
|
||||
animation.transition(ref, {
|
||||
styles: {
|
||||
transform: `translate(${x},${y})`
|
||||
},
|
||||
duration: this.current === index ? 0 : 250,
|
||||
timingFunction: 'linear',
|
||||
needLayout: false,
|
||||
delay: 0
|
||||
});
|
||||
},
|
||||
outOfRange(x1, y1, x2, y2, x3, y3) {
|
||||
return x1 < 0 || x1 >= y1 || x2 < 0 || x2 >= y2 || x3 < 0 || x3 >= y3
|
||||
},
|
||||
listSort(sKey, eKey) {
|
||||
let endRealKey = -1;
|
||||
this.list.forEach((item) => {
|
||||
if (item.sortKey === eKey) endRealKey = item.realKey;
|
||||
});
|
||||
|
||||
return this.list.map((item) => {
|
||||
let cKey = item.sortKey;
|
||||
let rKey = item.realKey;
|
||||
if (sKey < eKey) {
|
||||
if (cKey > sKey && cKey <= eKey) {
|
||||
--rKey;
|
||||
--cKey;
|
||||
} else if (cKey === sKey) {
|
||||
rKey = endRealKey;
|
||||
cKey = eKey;
|
||||
}
|
||||
} else if (sKey > eKey) {
|
||||
if (cKey >= eKey && cKey < sKey) {
|
||||
++rKey;
|
||||
++cKey;
|
||||
} else if (cKey === sKey) {
|
||||
rKey = endRealKey;
|
||||
cKey = eKey;
|
||||
}
|
||||
}
|
||||
if (item.sortKey !== cKey) {
|
||||
let columns = Number(this.columns)
|
||||
item.transX = (cKey % columns) * this.cellWidth + "px";
|
||||
item.transY = Math.floor(cKey / columns) * this.cellHeight + "px";
|
||||
item.sortKey = cKey;
|
||||
item.realKey = rKey;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
},
|
||||
emitsEvent(list, type) {
|
||||
let changeList = [],
|
||||
itemList = [];
|
||||
|
||||
list.forEach((item) => {
|
||||
changeList[item.sortKey] = item;
|
||||
});
|
||||
|
||||
changeList.forEach((item) => {
|
||||
itemList.push(item.entity);
|
||||
});
|
||||
if (type == "change") {
|
||||
this.change({
|
||||
itemList: itemList
|
||||
});
|
||||
} else {
|
||||
this.sortend({
|
||||
itemList: itemList
|
||||
});
|
||||
}
|
||||
},
|
||||
getXY(touch) {
|
||||
if (this.isAndroid) {
|
||||
touch.pageX = touch.screenX
|
||||
touch.pageY = touch.screenY
|
||||
}
|
||||
return touch
|
||||
},
|
||||
longPress(e) {
|
||||
if (!this.isDrag) return;
|
||||
let touch = e.changedTouches && e.changedTouches[0] ? e.changedTouches[0] : this.startTouch;
|
||||
if (!touch) return;
|
||||
this.current = Number(e.currentTarget.dataset.index);
|
||||
if (this.tDragging) return;
|
||||
let ref = this.allRefs[this.current]
|
||||
if (!ref) return;
|
||||
touch = this.getXY(touch)
|
||||
let transX = this.columns == 1 ? 0 : touch.pageX - (this.cellWidth / 2 + this.wrapLeft) + 'px';
|
||||
// this.initY = touch.pageY - (this.wrapTop + this.cellHeight * (Math.ceil(this.current / this.columns)))
|
||||
let transY = touch.pageY - (this.cellHeight * this.divisor + this.wrapTop ) + 'px';
|
||||
this._animation(ref, this.current, transX, transY)
|
||||
this.sId = touch.identifier;
|
||||
this.tDragging = true;
|
||||
},
|
||||
touchstart(e) {
|
||||
if (!this.isDrag) return;
|
||||
this.startTouch = e.changedTouches[0] || e.touches[0];
|
||||
},
|
||||
touchmove(e) {
|
||||
if (!this.isDrag || !this.tDragging) return;
|
||||
let touch = e.changedTouches[0] || e.touches[0];
|
||||
// || this.sId !== touch.identifier
|
||||
if (!touch) return;
|
||||
touch = this.getXY(touch)
|
||||
let transX = this.columns == 1 ? 0 : touch.pageX - (this.cellWidth / 2 + this.wrapLeft);
|
||||
let transY = touch.pageY - (this.cellHeight * this.divisor + this.wrapTop);
|
||||
if (touch.pageY > this.windowHeight - this.cellHeight) {
|
||||
this.pageScroll({
|
||||
scrollTop: touch.pageY + this.cellHeight - this.windowHeight
|
||||
})
|
||||
} else if (touch.pageY < this.cellHeight) {
|
||||
this.pageScroll({
|
||||
scrollTop: touch.pageY - this.cellHeight
|
||||
})
|
||||
}
|
||||
let ref = this.allRefs[this.current]
|
||||
if (!ref) return;
|
||||
this._animation(ref, this.current, transX + 'px', transY + 'px')
|
||||
let startKey = this.list[this.current].sortKey;
|
||||
let curX = Math.round(transX / this.cellWidth);
|
||||
let curY = Math.round(transY / this.cellHeight);
|
||||
let endKey = curX + Number(this.columns) * curY;
|
||||
|
||||
if (this.outOfRange(curX, Number(this.columns), curY, this.rows, endKey, this.list.length)) return;
|
||||
if (startKey === endKey || startKey === this.preStartKey) return;
|
||||
this.preStartKey = startKey;
|
||||
let list = this.listSort(startKey, endKey);
|
||||
this.allRefs.forEach((ins, index) => {
|
||||
var item = list[index];
|
||||
if (index !== this.current) {
|
||||
this._animation(ins, index, item.transX, item.transY)
|
||||
}
|
||||
});
|
||||
this.listChange({
|
||||
itemList: list
|
||||
})
|
||||
this.emitsEvent(list, "change");
|
||||
},
|
||||
touchend(e) {
|
||||
if (!this.isDrag || !this.tDragging) return;
|
||||
this.emitsEvent(this.list, "sortend");
|
||||
let cur = this.current
|
||||
this.current = -1;
|
||||
let ref = this.allRefs[cur]
|
||||
if (!ref) return
|
||||
this._animation(ref, cur, this.list[cur].transX, this.list[cur].transY)
|
||||
this.preStartKey = -1;
|
||||
this.tDragging = false;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifndef APP-NVUE
|
||||
export default {}
|
||||
// #endif
|
209
components/firstui/fui-drag/f-drag-item.vue
Normal file
209
components/firstui/fui-drag/f-drag-item.vue
Normal file
@ -0,0 +1,209 @@
|
||||
<!--本文件由FirstUI授权予新疆天衡创新研究院有限公司(手机号: 18 61407 2 5 49,身份证尾号:5A07X5)专用,请尊重知识产权,勿私下传播,违者追究法律责任。-->
|
||||
<template>
|
||||
<view class="fui-drag__item-outer" :style="{width:width+'px',height:height+'px'}">
|
||||
<view class="fui-drag__item-wrap" :class="{'fui-drag__item-padding':type==2}"
|
||||
:style="{width:width-(padding*2)+'px',height:height-(padding*2)+'px',background:background,'justify-content':type==1?'center':'space-between'}">
|
||||
<view class="fui-drag__item-inner" :class="{'fui-drag__item-column':type==1}">
|
||||
<view class="fui-drag__item-icon" @tap.stop="handleDel" :class="{'fui-drag__item-mr':type==2}"
|
||||
v-if="type==2 && isDel">
|
||||
<fui-icon name="minussign-fill" :color="delColor" :size="48"></fui-icon>
|
||||
</view>
|
||||
<image :draggable="false" :style="{width:width-(padding*2)+'px',height:height-(padding*2)+'px'}"
|
||||
:src="src" class="fui-drag__item-img" :class="{'fui-drag__item-mr':type==2}"
|
||||
v-if="src && src!==true && src!=='true' && type==1">
|
||||
</image>
|
||||
<view class="fui-drag__item-icon" @tap.stop="handleDel" :class="{'fui-drag__item-ab':type==1}"
|
||||
v-if="type==1 && isDel">
|
||||
<fui-icon name="clear-fill" :color="delColor" :size="48"></fui-icon>
|
||||
</view>
|
||||
<text class="fui-drag__item-text" :style="{color:color,fontSize:size+'rpx'}"
|
||||
v-if="text!='' && text!==true && type==2">{{text}}</text>
|
||||
</view>
|
||||
<fui-icon v-if="type==2" name="menu" :size="48" :color="slideColor"></fui-icon>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
//非easycom模式取消注释引入字体组件,按实际路径进行调整
|
||||
// import fuiIcon from "@/components/firstui/fui-icon/fui-icon.vue"
|
||||
export default {
|
||||
name: "f-drag-item",
|
||||
emits: ['delete'],
|
||||
// components:{
|
||||
// fuiIcon
|
||||
// },
|
||||
props: {
|
||||
width: {
|
||||
type: [Number, String],
|
||||
default: 40
|
||||
},
|
||||
height: {
|
||||
type: [Number, String],
|
||||
default: 40
|
||||
},
|
||||
src: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
index: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
styles: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: 1,
|
||||
padding: 0,
|
||||
background: "#fff",
|
||||
size: 30,
|
||||
color: '#181818',
|
||||
isDel: false,
|
||||
delColor: '#FF2B2B',
|
||||
slideColor: '#B2B2B2'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
styles(vals) {
|
||||
this.init(vals)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init(this.styles)
|
||||
},
|
||||
methods: {
|
||||
init(styles) {
|
||||
styles = styles || {}
|
||||
this.type = styles.type || 1
|
||||
this.padding = Number(styles.padding || 0)
|
||||
this.background = styles.background || "#fff"
|
||||
this.size = styles.size || 30
|
||||
this.color = styles.color || '#181818'
|
||||
this.isDel = styles.isDel || false
|
||||
const app = uni && uni.$fui && uni.$fui.color;
|
||||
const dangerColor = (app && app.danger) || '#FF2B2B';
|
||||
this.delColor = styles.delColor || dangerColor
|
||||
this.slideColor = styles.slideColor || '#B2B2B2'
|
||||
},
|
||||
handleDel() {
|
||||
this.$emit('delete', {
|
||||
index: this.index
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fui-drag__item-outer {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
transform: translate3d(0, 0, 0);
|
||||
backface-visibility: hidden;
|
||||
/* #endif */
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fui-drag__item-wrap {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fui-drag__item-padding {
|
||||
padding: 0 32rpx;
|
||||
position: absolute;
|
||||
/* #ifdef APP-NVUE */
|
||||
border-bottom-width: 0.5px;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-color: #eee;
|
||||
z-index: -1;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.fui-drag__item-padding::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-bottom: 1px solid #eee;
|
||||
transform: scaleY(0.5) translateZ(0);
|
||||
transform-origin: 0 100%;
|
||||
left: 32rpx;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
.fui-drag__item-inner {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fui-drag__item-icon {
|
||||
/* #ifndef APP-NVUE */
|
||||
flex-shrink: 0;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.fui-drag__item-ab {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 2;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.fui-drag__item-mr {
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.fui-drag__itemicon {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.fui-drag__item-img {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: block;
|
||||
pointer-events: none;
|
||||
flex-shrink: 0;
|
||||
transform: translate3d(0, 0, 0);
|
||||
backface-visibility: hidden;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.fui-drag__item-text {
|
||||
font-size: 30rpx;
|
||||
font-weight: normal;
|
||||
flex: 1;
|
||||
/* #ifdef APP-NVUE */
|
||||
lines: 1;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
/* #endif */
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
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>
|
290
components/firstui/fui-drag/index.wxs
Normal file
290
components/firstui/fui-drag/index.wxs
Normal file
@ -0,0 +1,290 @@
|
||||
// 本文件由FirstUI授权予新疆天衡创新研究院有限公司(手机号: 18 6 14 0725 4 9,身份证尾号:5A07X5)专用,请尊重知识产权,勿私下传播,违者追究法律责任。
|
||||
var wrapParam = {}
|
||||
|
||||
function isPC() {
|
||||
if (typeof navigator !== 'object') return false;
|
||||
var userAgentInfo = navigator.userAgent;
|
||||
var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
|
||||
var flag = true;
|
||||
for (var v = 0; v < Agents.length - 1; v++) {
|
||||
if (userAgentInfo.indexOf(Agents[v]) > 0) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
var isH5 = false
|
||||
if (typeof window === 'object') isH5 = true
|
||||
|
||||
function outOfRange(x1, y1, x2, y2, x3, y3) {
|
||||
return x1 < 0 || x1 >= y1 || x2 < 0 || x2 >= y2 || x3 < 0 || x3 >= y3
|
||||
};
|
||||
|
||||
function listSort(sKey, eKey, st) {
|
||||
var param = st.param
|
||||
var endRealKey = -1;
|
||||
st.list.forEach(function(item) {
|
||||
if (item.sortKey === eKey) endRealKey = item.realKey;
|
||||
});
|
||||
|
||||
return st.list.map(function(item) {
|
||||
var cKey = item.sortKey;
|
||||
var rKey = item.realKey;
|
||||
if (sKey < eKey) {
|
||||
if (cKey > sKey && cKey <= eKey) {
|
||||
--rKey;
|
||||
--cKey;
|
||||
} else if (cKey === sKey) {
|
||||
rKey = endRealKey;
|
||||
cKey = eKey;
|
||||
}
|
||||
} else if (sKey > eKey) {
|
||||
if (cKey >= eKey && cKey < sKey) {
|
||||
++rKey;
|
||||
++cKey;
|
||||
} else if (cKey === sKey) {
|
||||
rKey = endRealKey;
|
||||
cKey = eKey;
|
||||
}
|
||||
}
|
||||
if (item.sortKey !== cKey) {
|
||||
item.transX = (cKey % param.columns) * param.cellWidth + "px";
|
||||
item.transY = Math.floor(cKey / param.columns) * param.cellHeight + "px";
|
||||
item.sortKey = cKey;
|
||||
item.realKey = rKey;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
function emitsEvent(list, type, ins) {
|
||||
if (!ins) return;
|
||||
var changeList = [],
|
||||
itemList = [];
|
||||
|
||||
list.forEach(function(item) {
|
||||
changeList[item.sortKey] = item;
|
||||
});
|
||||
|
||||
changeList.forEach(function(item) {
|
||||
itemList.push(item.entity);
|
||||
});
|
||||
if (type == "change") {
|
||||
ins.callMethod("change", {
|
||||
itemList: itemList
|
||||
});
|
||||
} else {
|
||||
ins.callMethod("sortend", {
|
||||
itemList: itemList
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function longPress(e, ownerInstance) {
|
||||
var ins = e.instance;
|
||||
var dataset = ins.getDataset()
|
||||
var st = ins.getState();
|
||||
st.isDrag = +dataset.isdrag == 1 ? true : false
|
||||
if (!st.isDrag) return;
|
||||
|
||||
if (!st.param || st.param == 'undefined') {
|
||||
st.param = JSON.parse(dataset.param)
|
||||
}
|
||||
var param = st.param;
|
||||
var touch = null
|
||||
if (isH5 && isPC()) {
|
||||
touch = e;
|
||||
} else {
|
||||
touch = e.changedTouches ? e.changedTouches[0] : st.startTouch
|
||||
}
|
||||
if (!touch) return;
|
||||
st.cur = +dataset.index;
|
||||
|
||||
if (st.dragging) return;
|
||||
// #ifdef MP-WEIXIN
|
||||
ownerInstance.callMethod("drag", {
|
||||
wxdrag: true
|
||||
});
|
||||
// #endif
|
||||
st.transX = param.columns === 1 ? 0 : touch.pageX - (param.cellWidth / 2 + param.wrapLeft);
|
||||
st.transY = touch.pageY - (param.cellHeight / 2 + param.wrapTop);
|
||||
st.sId = touch.identifier;
|
||||
st.prevIns && st.prevIns.removeClass("fui-drag__trans-end")
|
||||
ins.setStyle({
|
||||
'transform': 'translate3d(' + st.transX + 'px, ' + st.transY + 'px, 0)'
|
||||
});
|
||||
st.itemsInstance.forEach(function(item, index) {
|
||||
item.removeClass("fui-drag__cur").removeClass("fui-drag__trans")
|
||||
item.addClass(index === st.cur ? "fui-drag__cur" : "fui-drag__trans");
|
||||
})
|
||||
st.dragging = true;
|
||||
}
|
||||
|
||||
function touchStart(e, ownerInstance) {
|
||||
var ins = e.instance;
|
||||
var st = ins.getState()
|
||||
st.list = wrapParam.list
|
||||
st.itemsInstance = wrapParam.itemsInstance
|
||||
st.param = wrapParam.param
|
||||
if (isH5 && isPC()) {
|
||||
st.startTouch = e;
|
||||
} else {
|
||||
st.startTouch = e.changedTouches[0] || e.touches[0]
|
||||
}
|
||||
var dataset = ins.getDataset()
|
||||
st.isDrag = +dataset.isdrag == 1 ? true : false
|
||||
// #ifdef MP-WEIXIN
|
||||
ownerInstance.callMethod("drag", {
|
||||
wxdrag: false
|
||||
});
|
||||
// #endif
|
||||
}
|
||||
|
||||
function touchMove(e, ownerInstance, event) {
|
||||
var st = {}
|
||||
var touch = null
|
||||
var ins = null
|
||||
if (isH5 && isPC()) {
|
||||
touch = e;
|
||||
st = event.instance.getState()
|
||||
ins = event.instance;
|
||||
} else {
|
||||
touch = e.changedTouches[0] || e.touches[0]
|
||||
st = e.instance.getState()
|
||||
ins = e.instance
|
||||
}
|
||||
if (e.preventDefault && st.dragging) {
|
||||
e.preventDefault()
|
||||
}
|
||||
var param = st.param;
|
||||
|
||||
if (!st.dragging || !st.isDrag) return;
|
||||
if (!touch || st.sId !== touch.identifier) return;
|
||||
|
||||
var transX = param.columns === 1 ? 0 : touch.pageX - (param.cellWidth / 2 + param.wrapLeft);
|
||||
var transY = touch.pageY - (param.cellHeight / 2 + param.wrapTop);
|
||||
|
||||
if (touch.clientY > param.windowHeight - param.cellHeight) {
|
||||
ownerInstance.callMethod("pageScroll", {
|
||||
scrollTop: touch.pageY + param.cellHeight - param.windowHeight
|
||||
});
|
||||
} else if (touch.clientY < param.cellHeight) {
|
||||
ownerInstance.callMethod("pageScroll", {
|
||||
scrollTop: touch.pageY - param.cellHeight
|
||||
});
|
||||
}
|
||||
|
||||
ins.setStyle({
|
||||
'transform': 'translate3d(' + transX + 'px, ' + transY + 'px, 0)'
|
||||
})
|
||||
|
||||
var startKey = st.list[st.cur].sortKey;
|
||||
var curX = Math.round(transX / param.cellWidth);
|
||||
var curY = Math.round(transY / param.cellHeight);
|
||||
var endKey = curX + param.columns * curY;
|
||||
|
||||
if (outOfRange(curX, param.columns, curY, param.rows, endKey, st.list.length)) return;
|
||||
|
||||
if (startKey === endKey || startKey === st.preStartKey) return;
|
||||
st.preStartKey = startKey;
|
||||
|
||||
var list = listSort(startKey, endKey, st);
|
||||
st.itemsInstance.forEach(function(itemIns, index) {
|
||||
var item = list[index];
|
||||
if (index !== st.cur) {
|
||||
itemIns.setStyle({
|
||||
'transform': 'translate3d(' + item.transX + ',' + item.transY + ', 0)'
|
||||
});
|
||||
}
|
||||
});
|
||||
ownerInstance.callMethod("listChange", {
|
||||
itemList: list
|
||||
});
|
||||
emitsEvent(list, "change", ownerInstance);
|
||||
}
|
||||
|
||||
function touchEnd(e, ownerInstance, event) {
|
||||
var ins = null
|
||||
var st = {}
|
||||
if (isH5 && isPC()) {
|
||||
ins = event.instance
|
||||
st = event.instance.getState()
|
||||
} else {
|
||||
st = e.instance.getState()
|
||||
ins = e.instance
|
||||
}
|
||||
if (!st.dragging || !st.isDrag) return;
|
||||
emitsEvent(st.list, "sortend", ownerInstance);
|
||||
ins.addClass("fui-drag__trans-end")
|
||||
ins.setStyle({
|
||||
'transform': 'translate3d(' + st.list[st.cur].transX + ',' + st.list[st.cur].transY + ', 0)'
|
||||
});
|
||||
st.itemsInstance.forEach(function(item, index) {
|
||||
item.removeClass("fui-drag__trans").removeClass("fui-drag__cur");
|
||||
})
|
||||
st.prevIns = ins
|
||||
st.preStartKey = -1;
|
||||
st.dragging = false;
|
||||
// #ifdef MP-WEIXIN
|
||||
ownerInstance.callMethod("drag", {
|
||||
wxdrag: false
|
||||
});
|
||||
// #endif
|
||||
st.cur = -1;
|
||||
st.transX = 0;
|
||||
st.transY = 0;
|
||||
}
|
||||
|
||||
function paramChange(newVal, oldVal, ownerInstance, ins) {
|
||||
wrapParam.param = newVal;
|
||||
}
|
||||
|
||||
function listChange(newVal, oldVal, ownerInstance, ins) {
|
||||
wrapParam.itemsInstance = ownerInstance.selectAllComponents('.fui-drag-item__wrap');
|
||||
wrapParam.list = newVal || [];
|
||||
if (!wrapParam.itemsInstance || wrapParam.itemsInstance.length === 0) return;
|
||||
|
||||
wrapParam.list.forEach(function(item, index) {
|
||||
var itemIns = wrapParam.itemsInstance[index];
|
||||
if (item && itemIns) {
|
||||
itemIns.setStyle({
|
||||
'transform': 'translate3d(' + item.transX + ',' + item.transY + ', 0)'
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var movable = false;
|
||||
|
||||
function mousedown(e, ins) {
|
||||
if (!isH5 || !isPC()) return
|
||||
touchStart(e, ins)
|
||||
longPress(e, ins)
|
||||
movable = true
|
||||
window.onmousemove = function(event) {
|
||||
if (!isH5 || !isPC() || !movable) return
|
||||
touchMove(event, ins, e)
|
||||
}
|
||||
window.onmouseup = function(event) {
|
||||
if (!isH5 || !isPC() || !movable) return
|
||||
touchEnd(event, ins, e)
|
||||
movable = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function stopTouchMove(e) {
|
||||
return true
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
longPress: longPress,
|
||||
touchStart: touchStart,
|
||||
touchMove: touchMove,
|
||||
touchEnd: touchEnd,
|
||||
paramChange: paramChange,
|
||||
listChange: listChange,
|
||||
mousedown: mousedown,
|
||||
stopTouchMove:stopTouchMove
|
||||
}
|
145
components/firstui/fui-drag/mpjs.js
Normal file
145
components/firstui/fui-drag/mpjs.js
Normal file
@ -0,0 +1,145 @@
|
||||
// 本文件由FirstUI授权予新疆天衡创新研究院有限公司(手机号:1 8 6140 7 2 5 4 9,身份证尾号:5A07X5)专用,请尊重知识产权,勿私下传播,违者追究法律责任。
|
||||
// #ifndef APP-PLUS || MP-WEIXIN || H5
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
current: -1,
|
||||
transX: '0px',
|
||||
transY: '0px',
|
||||
startTouch: null,
|
||||
tDragging: false,
|
||||
sId: null,
|
||||
preStartKey: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
outOfRange(x1, y1, x2, y2, x3, y3) {
|
||||
return x1 < 0 || x1 >= y1 || x2 < 0 || x2 >= y2 || x3 < 0 || x3 >= y3
|
||||
},
|
||||
listSort(sKey, eKey) {
|
||||
let endRealKey = -1;
|
||||
this.list.forEach((item) => {
|
||||
if (item.sortKey === eKey) endRealKey = item.realKey;
|
||||
});
|
||||
|
||||
return this.list.map((item) => {
|
||||
let cKey = item.sortKey;
|
||||
let rKey = item.realKey;
|
||||
if (sKey < eKey) {
|
||||
if (cKey > sKey && cKey <= eKey) {
|
||||
--rKey;
|
||||
--cKey;
|
||||
} else if (cKey === sKey) {
|
||||
rKey = endRealKey;
|
||||
cKey = eKey;
|
||||
}
|
||||
} else if (sKey > eKey) {
|
||||
if (cKey >= eKey && cKey < sKey) {
|
||||
++rKey;
|
||||
++cKey;
|
||||
} else if (cKey === sKey) {
|
||||
rKey = endRealKey;
|
||||
cKey = eKey;
|
||||
}
|
||||
}
|
||||
if (item.sortKey !== cKey) {
|
||||
let columns = Number(this.columns)
|
||||
item.transX = (cKey % columns) * this.cellWidth + "px";
|
||||
item.transY = Math.floor(cKey / columns) * this.cellHeight + "px";
|
||||
item.sortKey = cKey;
|
||||
item.realKey = rKey;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
},
|
||||
emitsEvent(list, type) {
|
||||
let changeList = [],
|
||||
itemList = [];
|
||||
|
||||
list.forEach((item) => {
|
||||
changeList[item.sortKey] = item;
|
||||
});
|
||||
|
||||
changeList.forEach((item) => {
|
||||
itemList.push(item.entity);
|
||||
});
|
||||
if (type == "change") {
|
||||
this.change({
|
||||
itemList: itemList
|
||||
});
|
||||
} else {
|
||||
this.sortend({
|
||||
itemList: itemList
|
||||
});
|
||||
}
|
||||
},
|
||||
longPress(e) {
|
||||
if (!this.isDrag) return;
|
||||
let touch = e.changedTouches && e.changedTouches[0] ? e.changedTouches[0] : this.startTouch;
|
||||
if (!touch) return;
|
||||
this.current = Number(e.currentTarget.dataset.index);
|
||||
|
||||
if (this.tDragging) return;
|
||||
//pageX
|
||||
this.transX = this.columns == 1 ? 0 : touch.clientX - (this.cellWidth / 2 + this.wrapLeft) + 'px';
|
||||
this.transY = touch.clientY - (this.cellHeight / 2 + this.wrapTop) + 'px';
|
||||
this.sId = touch.identifier;
|
||||
this.tDragging = true;
|
||||
},
|
||||
touchstart(e) {
|
||||
if (!this.isDrag) return;
|
||||
this.startTouch = e.changedTouches[0] || e.touches[0];
|
||||
},
|
||||
touchmove(e) {
|
||||
if (!this.isDrag || !this.tDragging) return;
|
||||
let touch = e.changedTouches[0] || e.touches[0];
|
||||
if (!touch || this.sId !== touch.identifier) return;
|
||||
let transX = this.columns == 1 ? 0 : touch.clientX - (this.cellWidth / 2 + this.wrapLeft);
|
||||
let transY = touch.clientY - (this.cellHeight / 2 + this.wrapTop);
|
||||
|
||||
if (touch.clientY > this.windowHeight - this.cellHeight) {
|
||||
this.pageScroll({
|
||||
scrollTop: touch.pageY + this.cellHeight - this.windowHeight
|
||||
})
|
||||
} else if (touch.clientY < this.cellHeight) {
|
||||
this.pageScroll({
|
||||
scrollTop: touch.pageY - this.cellHeight
|
||||
})
|
||||
}
|
||||
this.transX = transX + 'px'
|
||||
this.transY = transY + 'px'
|
||||
|
||||
let startKey = this.list[this.current].sortKey;
|
||||
let curX = Math.round(transX / this.cellWidth);
|
||||
let curY = Math.round(transY / this.cellHeight);
|
||||
let endKey = curX + Number(this.columns) * curY;
|
||||
|
||||
if (this.outOfRange(curX, Number(this.columns), curY, this.rows, endKey, this.list.length)) return;
|
||||
|
||||
if (startKey === endKey || startKey === this.preStartKey) return;
|
||||
this.preStartKey = startKey;
|
||||
|
||||
let list = this.listSort(startKey, endKey);
|
||||
this.listChange({
|
||||
itemList: list
|
||||
})
|
||||
this.emitsEvent(list, "change");
|
||||
},
|
||||
touchend(e) {
|
||||
if (!this.isDrag || !this.tDragging) return;
|
||||
this.emitsEvent(this.list, "sortend");
|
||||
this.preStartKey = -1;
|
||||
this.tDragging = false;
|
||||
this.current = -1;
|
||||
this.transX = '0px';
|
||||
this.transY = '0px';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS|| MP-WEIXIN || H5
|
||||
export default {}
|
||||
// #endif
|
Reference in New Issue
Block a user