var isOutRange = function(x1, y1, x2, y2, x3, y3) { return x1 < 0 || x1 >= y1 || x2 < 0 || x2 >= y2 || x3 < 0 || x3 >= y3 }; var isEdit = false; function bool(str) { return str === 'true' || str == true ? true : false } var sortCore = function(sKey, eKey, st) { var _ = st.basedata; var excludeFix = function(cKey, type) { // fixed 元素位置不会变化, 这里直接用 cKey(sortKey) 获取, 更加快捷 if (st.list[cKey].fixed) { var _cKey = type ? --cKey : ++cKey; return excludeFix(cKey, type); } return cKey; } // 先获取到 endKey 对应的 realKey, 防止下面排序过程中该 realKey 被修改 var endRealKey = -1; st.list.forEach(function(item) { if (item.sortKey === eKey) endRealKey = item.realKey; }); return st.list.map(function(item) { if (item.fixed) return item; var cKey = item.sortKey; var rKey = item.realKey; if (sKey < eKey) { // 正序拖动 if (cKey > sKey && cKey <= eKey) { --rKey; cKey = excludeFix(--cKey, true); } else if (cKey === sKey) { rKey = endRealKey; cKey = eKey; } } else if (sKey > eKey) { // 倒序拖动 if (cKey >= eKey && cKey < sKey) { ++rKey cKey = excludeFix(++cKey, false); } else if (cKey === sKey) { rKey = endRealKey; cKey = eKey; } } if (item.sortKey !== cKey) { item.tranX = (cKey % _.columns) * 100 + "%"; item.tranY = Math.floor(cKey / _.columns) * 100 + "%"; item.sortKey = cKey; item.realKey = rKey; } return item; }); } var triggerCustomEvent = function(list, type, ins) { if (!ins) return; var _list = [], listData = []; list.forEach(function(item) { _list[item.sortKey] = item; }); _list.forEach(function(item) { listData.push(item.data); }); //编译到小程序 funcName作为参数传递导致事件不执行 if(type=="change"){ ins.callMethod("change", {listData: listData}); }else{ ins.callMethod("sort_end", {listData: listData}); } } var longPress = function(event, ownerInstance) { var ins = event.instance; var dataset = ins.getDataset() isEdit = bool(dataset.edit) if (!isEdit) return; var st = ownerInstance.getState(); if (!st.basedata || st.basedata == 'undefined') { st.basedata = JSON.parse(dataset.basedata) } var _ = st.basedata; var sTouch = event.changedTouches[0]; if (!sTouch) return; st.cur = +dataset.index; // 初始项是固定项则返回 var item = st.list[st.cur]; if (item && item.fixed) return; // 如果已经在 drag 中则返回, 防止多指触发 drag 动作, touchstart 事件中有效果 if (st.dragging) return; // #ifdef MP-WEIXIN ownerInstance.callMethod("drag", { dragging: true }); // #endif // 计算X,Y轴初始位移, 使 item 中心移动到点击处, 单列时候X轴初始不做位移 st.tranX = _.columns === 1 ? 0 : sTouch.pageX - (_.itemWidth / 2 + _.wrapLeft); st.tranY = sTouch.pageY - (_.itemHeight / 2 + _.wrapTop); st.sId = sTouch.identifier; ins.setStyle({ 'transform': 'translate3d(' + st.tranX + 'px, ' + st.tranY + 'px, 0)' }); st.itemsInstance.forEach(function(item, index) { item.removeClass("tui-drag__transition").removeClass("tui-drag__current"); item.addClass(index == st.cur ? "tui-drag__current" : "tui-drag__transition"); }) ownerInstance.callMethod("vibrate"); st.dragging = true; }; var touchStart = function(event, ownerInstance) { var ins = event.instance; var dataset = ins.getDataset() isEdit = bool(dataset.edit) } var touchMove = function(event, ownerInstance) { var ins = event.instance; var st = ownerInstance.getState(); var _ = st.basedata; if (!st.dragging || !isEdit) return; var mTouch = event.changedTouches[0]; if (!mTouch) return; // 如果不是同一个触发点则返回 if (st.sId !== mTouch.identifier) return; // 计算X,Y轴位移, 单列时候X轴初始不做位移 var tranX = _.columns === 1 ? 0 : mTouch.pageX - (_.itemWidth / 2 + _.wrapLeft); var tranY = mTouch.pageY - (_.itemHeight / 2 + _.wrapTop); // 到顶到底自动滑动 if (mTouch.clientY > _.windowHeight - _.itemHeight - _.realBottomSize) { // 当前触摸点pageY + item高度 - (屏幕高度 - 底部固定区域高度) ownerInstance.callMethod("pageScroll", { scrollTop: mTouch.pageY + _.itemHeight - (_.windowHeight - _.realBottomSize) }); } else if (mTouch.clientY < _.itemHeight + _.realTopSize) { // 当前触摸点pageY - item高度 - 顶部固定区域高度 ownerInstance.callMethod("pageScroll", { scrollTop: mTouch.pageY - _.itemHeight - _.realTopSize }); } // 设置当前激活元素偏移量 ins.setStyle({ 'transform': 'translate3d(' + tranX + 'px, ' + tranY + 'px, 0)' }) var startKey = st.list[st.cur].sortKey; var curX = Math.round(tranX / _.itemWidth); var curY = Math.round(tranY / _.itemHeight); var endKey = curX + _.columns * curY; // 目标项是固定项则返回 var item = st.list[endKey]; if (item && item.fixed) return; // X轴或Y轴超出范围则返回 if (isOutRange(curX, _.columns, curY, _.rows, endKey, st.list.length)) return; // 防止拖拽过程中发生乱序问题 if (startKey === endKey || startKey === st.preStartKey) return; st.preStartKey = startKey; var list = sortCore(startKey, endKey, st); st.itemsInstance.forEach(function(itemIns, index) { var item = list[index]; if (index !== st.cur) { itemIns.setStyle({ 'transform': 'translate3d(' + item.tranX + ',' + item.tranY + ', 0)' }); } }); ownerInstance.callMethod("vibrate"); ownerInstance.callMethod("listChange", { list: list }); triggerCustomEvent(list, "change", ownerInstance); } var touchEnd = function(event, ownerInstance) { var ins = event.instance; var st = ownerInstance.getState(); if (!st.dragging || !isEdit) return; triggerCustomEvent(st.list, "sort_end", ownerInstance); ins.addClass("tui-drag__transition"); ins.setStyle({ 'transform': 'translate3d(' + st.list[st.cur].tranX + ',' + st.list[st.cur].tranY + ', 0)' }); st.itemsInstance.forEach(function(item, index) { item.removeClass("tui-drag__transition"); }) st.preStartKey = -1; st.dragging = false; // #ifdef MP-WEIXIN ownerInstance.callMethod("drag", { dragging: false }); // #endif st.cur = -1; st.tranX = 0; st.tranY = 0; } var baseDataObserver = function(newVal, oldVal, ownerInstance, ins) { var st = ownerInstance.getState(); st.basedata = newVal; } var listObserver = function(newVal, oldVal, ownerInstance, ins) { var st = ownerInstance.getState(); st.itemsInstance = ownerInstance.selectAllComponents('.tui-drag__item'); st.list = newVal || []; st.list.forEach(function(item, index) { var itemIns = st.itemsInstance[index]; if (item && itemIns) { itemIns.setStyle({ 'transform': 'translate3d(' + item.tranX + ',' + item.tranY + ', 0)' }); if (item.fixed) itemIns.addClass("tui-drag__fixed"); } }) } module.exports = { longPress: longPress, touchStart: touchStart, touchMove: touchMove, touchEnd: touchEnd, baseDataObserver: baseDataObserver, listObserver: listObserver }