drag.wxs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. var classPrefix = '';
  2. var startIndex = 0;
  3. var endIndex = 0;
  4. var dragCollisionList = [];
  5. var isOutRange = function (x1, y1, x2, y2, x3, y3) {
  6. return x1 < 0 || x1 >= y1 || x2 < 0 || x2 >= y2 || x3 < 0 || x3 >= y3;
  7. };
  8. var sortCore = function (sKey, eKey, st) {
  9. var _ = st.dragBaseData;
  10. var excludeFix = function (cKey, type) {
  11. if (st.list[cKey].fixed) {
  12. // fixed 元素位置不会变化, 这里直接用 cKey(sortKey) 获取, 更加快捷
  13. type ? --cKey : ++cKey;
  14. return excludeFix(cKey, type);
  15. }
  16. return cKey;
  17. };
  18. // 先获取到 endKey 对应的 realKey, 防止下面排序过程中该 realKey 被修改
  19. var endRealKey = -1;
  20. st.list.forEach(function (item) {
  21. if (item.sortKey === eKey) endRealKey = item.realKey;
  22. });
  23. return st.list.map(function (item) {
  24. if (item.fixed) return item;
  25. var cKey = item.sortKey;
  26. var rKey = item.realKey;
  27. if (sKey < eKey) {
  28. // 正序拖动
  29. if (cKey > sKey && cKey <= eKey) {
  30. --rKey;
  31. cKey = excludeFix(--cKey, true);
  32. } else if (cKey === sKey) {
  33. rKey = endRealKey;
  34. cKey = eKey;
  35. }
  36. } else if (sKey > eKey) {
  37. // 倒序拖动
  38. if (cKey >= eKey && cKey < sKey) {
  39. ++rKey;
  40. cKey = excludeFix(++cKey, false);
  41. } else if (cKey === sKey) {
  42. rKey = endRealKey;
  43. cKey = eKey;
  44. }
  45. }
  46. if (item.sortKey !== cKey) {
  47. item.tranX = (cKey % _.columns) * 100 + '%';
  48. item.tranY = Math.floor(cKey / _.columns) * 100 + '%';
  49. item.sortKey = cKey;
  50. item.realKey = rKey;
  51. }
  52. return item;
  53. });
  54. };
  55. var triggerCustomEvent = function (list, type, ins) {
  56. var _list = [],
  57. listData = [];
  58. list.forEach(function (item) {
  59. _list[item.sortKey] = item;
  60. });
  61. _list.forEach(function (item) {
  62. if (!item.extraNode) {
  63. listData.push(item.data);
  64. }
  65. });
  66. ins.triggerEvent(type, { listData: listData });
  67. };
  68. var longPress = function (event, ownerInstance) {
  69. var ins = event.instance;
  70. var st = ownerInstance.getState();
  71. var _ = st.dragBaseData;
  72. var sTouch = event.changedTouches[0];
  73. if (!sTouch) return;
  74. st.cur = ins.getDataset().index;
  75. longPressIndex = st.cur;
  76. // 初始项是固定项则返回
  77. var item = st.list[st.cur];
  78. if (item && item.fixed) return;
  79. // 如果已经在 drag 中则返回, 防止多指触发 drag 动作, touchstart 事件中有效果
  80. if (st.dragging) return;
  81. st.dragging = true;
  82. ownerInstance.callMethod('dragStatusChange', { dragging: true });
  83. // 计算X,Y轴初始位移, 使 item 中心移动到点击处, 单列时候X轴初始不做位移
  84. st.tranX = _.columns === 1 ? 0 : sTouch.pageX - (_.itemWidth / 2 + _.wrapLeft);
  85. st.tranY = sTouch.pageY - (_.itemHeight / 2 + _.wrapTop);
  86. st.sId = sTouch.identifier;
  87. ins.setStyle({
  88. transform: 'translate3d(' + st.tranX + 'px, ' + st.tranY + 'px, 0)',
  89. });
  90. st.itemsInstance.forEach(function (item, index) {
  91. item.removeClass(classPrefix + '__drag--tran').removeClass(classPrefix + '__drag--cur');
  92. item.addClass(index === st.cur ? classPrefix + '__drag--cur' : classPrefix + '__drag--tran');
  93. });
  94. ownerInstance.callMethod('dragVibrate', { vibrateType: 'longPress' });
  95. };
  96. var touchMove = function (event, ownerInstance) {
  97. var ins = event.instance;
  98. var st = ownerInstance.getState();
  99. var _ = st.dragBaseData;
  100. var mTouch = event.changedTouches[0];
  101. if (!mTouch) return;
  102. if (!st.dragging) return;
  103. // 如果不是同一个触发点则返回
  104. if (st.sId !== mTouch.identifier) return;
  105. // 计算X,Y轴位移, 单列时候X轴初始不做位移
  106. var tranX = _.columns === 1 ? 0 : mTouch.pageX - (_.itemWidth / 2 + _.wrapLeft);
  107. var tranY = mTouch.pageY - (_.itemHeight / 2 + _.wrapTop);
  108. // 到顶到底自动滑动
  109. if (mTouch.clientY > _.windowHeight - _.itemHeight - _.realBottomSize) {
  110. // 当前触摸点pageY + item高度 - (屏幕高度 - 底部固定区域高度)
  111. ownerInstance.callMethod('pageScroll', {
  112. scrollTop: mTouch.pageY + _.itemHeight - (_.windowHeight - _.realBottomSize),
  113. });
  114. } else if (mTouch.clientY < _.itemHeight + _.realTopSize) {
  115. // 当前触摸点pageY - item高度 - 顶部固定区域高度
  116. ownerInstance.callMethod('pageScroll', {
  117. scrollTop: mTouch.pageY - _.itemHeight - _.realTopSize,
  118. });
  119. }
  120. // 设置当前激活元素偏移量
  121. ins.setStyle({
  122. transform: 'translate3d(' + tranX + 'px, ' + tranY + 'px, 0)',
  123. });
  124. var startKey = st.list[st.cur].sortKey;
  125. var curX = Math.round(tranX / _.itemWidth);
  126. var curY = Math.round(tranY / _.itemHeight);
  127. var endKey = curX + _.columns * curY;
  128. // 目标项是固定项则返回
  129. var item = st.list[endKey];
  130. if (item && item.fixed) return;
  131. // X轴或Y轴超出范围则返回
  132. if (isOutRange(curX, _.columns, curY, _.rows, endKey, st.list.length)) return;
  133. // 防止拖拽过程中发生乱序问题
  134. if (startKey === endKey || startKey === st.preStartKey) return;
  135. st.preStartKey = startKey;
  136. dragCollisionList = sortCore(startKey, endKey, st);
  137. startIndex = startKey;
  138. endIndex = endKey;
  139. st.itemsInstance.forEach(function (itemIns, index) {
  140. var item = dragCollisionList[index];
  141. if (index !== st.cur) {
  142. itemIns.setStyle({
  143. transform: 'translate3d(' + item.tranX + ',' + item.tranY + ', 0)',
  144. });
  145. }
  146. });
  147. ownerInstance.callMethod('dragVibrate', { vibrateType: 'touchMove' });
  148. ownerInstance.callMethod('dragCollision', {
  149. dragCollisionList: dragCollisionList,
  150. startIndex: startIndex,
  151. endIndex: endIndex,
  152. });
  153. triggerCustomEvent(dragCollisionList, 'change', ownerInstance);
  154. };
  155. var touchEnd = function (event, ownerInstance) {
  156. var ins = event.instance;
  157. var st = ownerInstance.getState();
  158. if (!st.dragging) return;
  159. triggerCustomEvent(st.list, 'sortend', ownerInstance);
  160. ins.addClass(classPrefix + '__drag--tran');
  161. ins.setStyle({
  162. transform: 'translate3d(' + st.list[st.cur].tranX + ',' + st.list[st.cur].tranY + ', 0)',
  163. });
  164. st.preStartKey = -1;
  165. st.dragging = false;
  166. ownerInstance.callMethod('dragStatusChange', { dragging: false });
  167. ownerInstance.callMethod('dragEnd', {
  168. dragCollisionList: dragCollisionList,
  169. startIndex: startIndex,
  170. endIndex: endIndex,
  171. });
  172. st.cur = -1;
  173. st.tranX = 0;
  174. st.tranY = 0;
  175. };
  176. var baseDataObserver = function (newVal, oldVal, ownerInstance, ins) {
  177. var st = ownerInstance.getState();
  178. st.dragBaseData = newVal;
  179. classPrefix = newVal.classPrefix;
  180. };
  181. var listObserver = function (newVal, oldVal, ownerInstance, ins) {
  182. var st = ownerInstance.getState();
  183. st.itemsInstance = ownerInstance.selectAllComponents('.' + classPrefix + '__drag-item');
  184. st.list = newVal || [];
  185. st.list.forEach(function (item, index) {
  186. var itemIns = st.itemsInstance[index];
  187. if (item && itemIns) {
  188. itemIns.removeClass(classPrefix + '__drag--tran');
  189. itemIns.setStyle({
  190. transform: 'translate3d(' + item.tranX + ',' + item.tranY + ', 0)',
  191. });
  192. if (item.fixed) itemIns.addClass(classPrefix + '__drag--fixed');
  193. }
  194. });
  195. dragCollisionList = [];
  196. };
  197. module.exports = {
  198. longPress: longPress,
  199. touchMove: touchMove,
  200. touchEnd: touchEnd,
  201. baseDataObserver: baseDataObserver,
  202. listObserver: listObserver,
  203. };