123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- // 判断是否出界
- 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
- }
|