265 lines
8.1 KiB
XML
265 lines
8.1 KiB
XML
// 判断是否出界
|
||
var isOutRange = function(x1, y1, x2, y2, x3, y3) {
|
||
return x1 < 0 || x1 >= y1 || x2 < 0 || x2 >= y2 || x3 < 0 || x3 >= y3
|
||
}
|
||
var edit = false
|
||
|
||
function bool(str) {
|
||
return str === 'true' || str === true
|
||
}
|
||
/**
|
||
* 排序核心
|
||
* @param {Object} startKey 开始时位置
|
||
* @param {Object} endKey 结束时位置
|
||
* @param {Object} instance wxs内的局部变量快照
|
||
*/
|
||
var sortCore = function(startKey, endKey, state) {
|
||
var basedata = state.basedata
|
||
var excludeFix = function(sortKey, type) {
|
||
// fixed 元素位置不会变化, 这里直接用 sortKey 获取,更加便捷
|
||
if (state.list[sortKey].fixed) {
|
||
var _sortKey = type ? --sortKey : ++sortKey
|
||
return excludeFix(sortKey, type)
|
||
}
|
||
return sortKey
|
||
}
|
||
|
||
// 先获取到 endKey 对应的 realKey, 防止下面排序过程中该 realKey 被修改
|
||
var endRealKey = -1
|
||
state.list.forEach(function(item) {
|
||
if (item.sortKey === endKey) endRealKey = item.realKey
|
||
})
|
||
|
||
return state.list.map(function(item) {
|
||
if (item.fixed) return item
|
||
var sortKey = item.sortKey
|
||
var realKey = item.realKey
|
||
|
||
if (startKey < endKey) {
|
||
// 正序拖动
|
||
if (sortKey > startKey && sortKey <= endKey) {
|
||
--realKey
|
||
sortKey = excludeFix(--sortKey, true)
|
||
} else if (sortKey === startKey) {
|
||
realKey = endRealKey
|
||
sortKey = endKey
|
||
}
|
||
} else if (startKey > endKey) {
|
||
// 倒序拖动
|
||
if (sortKey >= endKey && sortKey < startKey) {
|
||
++realKey
|
||
sortKey = excludeFix(++sortKey, false)
|
||
} else if (sortKey === startKey) {
|
||
realKey = endRealKey
|
||
sortKey = endKey
|
||
}
|
||
}
|
||
|
||
if (item.sortKey != sortKey) {
|
||
item.translateX = (sortKey % basedata.columns) * 100 + '%'
|
||
item.translateY = Math.floor(sortKey / basedata.columns) * 100 + '%'
|
||
item.sortKey = sortKey
|
||
item.realKey = realKey
|
||
}
|
||
return item
|
||
})
|
||
}
|
||
|
||
var triggerCustomEvent = function(list, type, instance) {
|
||
if (!instance) return
|
||
var _list = [],
|
||
listData = [];
|
||
|
||
list.forEach(function(item) {
|
||
_list[item.sortKey] = item
|
||
})
|
||
_list.forEach(function(item) {
|
||
listData.push(item.data)
|
||
})
|
||
|
||
// 编译到小程序 funcName作为参数传递导致事件不执行
|
||
switch(type) {
|
||
case 'change':
|
||
instance.callMethod('change', {data: listData})
|
||
break
|
||
case 'sortEnd':
|
||
instance.callMethod('sortEnd', {data: listData})
|
||
break
|
||
}
|
||
}
|
||
|
||
var listObserver = function(newVal, oldVal, ownerInstance, instance) {
|
||
var state = ownerInstance.getState()
|
||
state.itemsInstance = ownerInstance.selectAllComponents('.tn-drag__item')
|
||
|
||
state.list = newVal || []
|
||
|
||
state.list.forEach(function(item, index) {
|
||
var itemInstance = state.itemsInstance[index]
|
||
if (item && itemInstance) {
|
||
itemInstance.setStyle({
|
||
'transform': 'translate3d('+ item.translateX + ',' + item.translateY +', 0)'
|
||
})
|
||
if (item.fixed) itemInstance.addClass('tn-drag__fixed')
|
||
}
|
||
})
|
||
}
|
||
|
||
var baseDataObserver = function(newVal, oldVal, ownerInstance, instance) {
|
||
var state = ownerInstance.getState()
|
||
state.basedata = newVal
|
||
}
|
||
|
||
var longPress = function(event, ownerInstance) {
|
||
var instance = event.instance
|
||
var dataset = instance.getDataset()
|
||
var state = ownerInstance.getState()
|
||
|
||
edit = bool(dataset.edit)
|
||
if (!edit) return
|
||
if (!state.basedata || state.basedata === 'undefined') {
|
||
state.basedata = JSON.parse(dataset.basedata)
|
||
}
|
||
var basedata = state.basedata
|
||
var touches = event.changedTouches[0]
|
||
if (!touches) return
|
||
|
||
state.current = +dataset.index
|
||
|
||
// 初始项是固定项则返回
|
||
var item = state.list[state.current]
|
||
if (item && item.fixed) return
|
||
|
||
// 如果已经在 drag 中则返回, 防止多指触发 drag 动作, touchstart 事件中有效果
|
||
if (state.dragging) return
|
||
|
||
ownerInstance.callMethod("drag", {
|
||
dragging: true
|
||
})
|
||
|
||
// 计算X, Y轴初始位移,使item中心移动到点击处,单列的时候X轴初始不做位移
|
||
state.translateX = basedata.columns === 1 ? 0 : touches.pageX - (basedata.itemWidth / 2 + basedata.left)
|
||
state.translateY = touches.pageY - (basedata.itemHeight / 2 + basedata.top)
|
||
state.touchId = touches.identifier
|
||
|
||
instance.setStyle({
|
||
'transform': 'translate3d(' + state.translateX + 'px,' + state.translateY +'px, 0)'
|
||
})
|
||
state.itemsInstance.forEach(function(item, index) {
|
||
item.removeClass("tn-drag__transition").removeClass("tn-drag__current")
|
||
item.addClass(index === state.current ? "tn-drag__current" : "tn-drag__transition")
|
||
})
|
||
|
||
ownerInstance.callMethod("vibrate")
|
||
state.dragging = true
|
||
}
|
||
|
||
var touchStart = function(event, ownerInstance) {
|
||
var instance = event.instance
|
||
var dataset = instance.getDataset()
|
||
edit = bool(dataset.edit)
|
||
}
|
||
|
||
var touchMove = function(event, ownerInstance) {
|
||
var instance = event.instance
|
||
var dataset = instance.getDataset()
|
||
var state = ownerInstance.getState()
|
||
var basedata = state.basedata
|
||
|
||
if (!state.dragging || !edit) return
|
||
var touches = event.changedTouches[0]
|
||
if (!touches) return
|
||
|
||
// 如果不是同一个触发点则返回
|
||
if (state.touchId !== touches.identifier) return
|
||
|
||
// 计算X,Y轴位移, 单列时候X轴初始不做位移
|
||
var translateX = basedata.columns === 1 ? 0 : touches.pageX - (basedata.itemWidth / 2 + basedata.left)
|
||
var translateY = touches.pageY - (basedata.itemHeight / 2 + basedata.top)
|
||
|
||
// 到顶到低自动滑动
|
||
if (touches.clientY > basedata.windowHeight - basedata.itemHeight - basedata.realBottomSize) {
|
||
// 当前触摸点pageY + item高度 - (屏幕高度 - 底部固定区域高度)
|
||
ownerInstance.callMethod('pageScroll', {
|
||
scrollTop: touches.pageY + basedata.itemHeight - (basedata.windowHeight - basedata.realBottomSize)
|
||
})
|
||
} else if (touches.clientY < basedata.itemHeight + basedata.realTopSize) {
|
||
// 当前触摸点pageY - item高度 - 顶部固定区域高
|
||
ownerInstance.callMethod('pageScroll', {
|
||
scrollTop: touches.pageY - basedata.itemHeight - basedata.realTopSize
|
||
})
|
||
}
|
||
|
||
// 设置当前激活元素的偏移量
|
||
instance.setStyle({
|
||
'transform': 'translate3d('+ translateX + 'px,' + translateY + 'px, 0)'
|
||
})
|
||
|
||
var startKey = state.list[state.current].sortKey
|
||
var currentX = Math.round(translateX / basedata.itemWidth)
|
||
var currentY = Math.round(translateY / basedata.itemHeight)
|
||
var endKey = currentX + basedata.columns * currentY
|
||
|
||
// 目标项时固定项则返回
|
||
var item = state.list[endKey]
|
||
if (item && item.fixed) return
|
||
|
||
// X轴或者Y轴超出范围则返回
|
||
if (isOutRange(currentX, basedata.columns, currentY, basedata.rows, endKey, state.list.length)) return
|
||
|
||
// 防止拖拽过程中发生乱序问题
|
||
if (startKey === endKey || startKey === state.preStartKey) return
|
||
state.preStartKey = startKey
|
||
|
||
var list = sortCore(startKey, endKey, state)
|
||
state.itemsInstance.forEach(function(itemInstance, index) {
|
||
var item = list[index]
|
||
if (index !== state.current) {
|
||
itemInstance.setStyle({
|
||
'transform': 'translate3d('+ item.translateX + ',' + item.translateY +', 0)'
|
||
})
|
||
}
|
||
})
|
||
|
||
// ownerInstance.callMethod('vibrate')
|
||
ownerInstance.callMethod('listDataChange', {
|
||
data: list
|
||
})
|
||
triggerCustomEvent(list, "change", ownerInstance)
|
||
}
|
||
|
||
var touchEnd = function(event, ownerInstance) {
|
||
var instance = event.instance
|
||
var dataset = instance.getDataset()
|
||
var state = ownerInstance.getState()
|
||
var basedata = state.basedata
|
||
|
||
if (!state.dragging || !edit) return
|
||
triggerCustomEvent(state.list, "sortEnd", ownerInstance)
|
||
|
||
instance.addClass('tn-drag__transition')
|
||
instance.setStyle({
|
||
'transform': 'translate3d('+ state.list[state.current].translateX + ',' + state.list[state.current].translateY + ', 0)'
|
||
})
|
||
state.itemsInstance.forEach(function(item, index) {
|
||
item.removeClass('tn-drag__transition')
|
||
})
|
||
|
||
state.preStartKey = -1
|
||
state.dragging = false
|
||
ownerInstance.callMethod('drag', {
|
||
dragging: false
|
||
})
|
||
state.current = -1
|
||
state.translateX = 0
|
||
state.translateY = 0
|
||
}
|
||
|
||
module.exports = {
|
||
longPress: longPress,
|
||
touchStart: touchStart,
|
||
touchMove: touchMove,
|
||
touchEnd: touchEnd,
|
||
baseDataObserver: baseDataObserver,
|
||
listObserver: listObserver
|
||
} |