drag.wxs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. var scrollTop = {}; //滚动条位置
  2. // 排序列表
  3. var sortList={};
  4. var isMove = false; //是否可拖动 长按事件控制切换这个状态
  5. var touchTimer = false; //长按事件定时器
  6. // 当页面有多个当前组件时,guid用来识别当前的列表的。因为一个页面内多个组件的wxs作用域相同。
  7. function setScrollTop(tmpGuid) {
  8. if (typeof scrollTop[tmpGuid] == "undefined") {
  9. scrollTop[tmpGuid] = 0;
  10. }
  11. }
  12. function scroll(event, instance) {
  13. var dataView = instance.selectComponent('#dataView');
  14. var viewData = dataView.getDataset();
  15. setScrollTop(viewData.guid)
  16. scrollTop[viewData.guid] = event.detail.scrollTop;
  17. }
  18. function initVar(state, instance) {
  19. var dataView = instance.selectComponent('#dataView');
  20. var viewData = dataView.getDataset();
  21. // 读取配置项
  22. // 获取scroll-view id
  23. config = All_Config[viewData.guid];
  24. setScrollTop(config.guid);
  25. state.initscrollTop = scrollTop[config.guid];
  26. }
  27. function getRowSort(findId,instance){
  28. for (var i = 0; i < sortList[config.guid].length; i++) {
  29. if(sortList[config.guid][i].id==findId){
  30. currentRowView = sortList[config.guid][i].rowView;
  31. return sortList[config.guid][i].lastSort;
  32. }
  33. }
  34. }
  35. var shadowRowBoxView=null;
  36. var shadowRowView = null;
  37. var currentRowView=null;
  38. var rowSort=0;
  39. var sorting = false;
  40. function touchstart(event, instance) {
  41. if(sorting){
  42. return ;
  43. }
  44. sorting = true;
  45. // 兼容setTimeout
  46. if(typeof setTimeout ==="undefined" && typeof instance.setTimeout !== 'undefined'){
  47. setTimeout = instance.setTimeout;
  48. clearTimeout = instance.clearTimeout;
  49. }
  50. isMove = false;
  51. var rowData = event.instance.getDataset();
  52. var state = instance.getState();
  53. if (event.touches.length == 1) {
  54. state.point = event.touches[0];
  55. state.islongTap = true;
  56. state.rowData = rowData;
  57. //读取数据
  58. initVar(state, instance);
  59. }
  60. var rowStyle = event.instance.getComputedStyle(['height']);
  61. config.rowHeight = parseFloat(rowStyle.height); //获取行高
  62. // 计算shadowRow.style.top
  63. rowSort = getRowSort(rowData.id,instance);
  64. var shadowRowTop = rowSort * config.rowHeight;
  65. shadowRowTop = shadowRowTop - scrollTop[config.guid];
  66. // 加载shadowRow数据
  67. instance.callMethod("loadShadowRow", {
  68. rowSort: rowSort
  69. });
  70. state.shadowRowTop = shadowRowTop;
  71. // 设置shadowRow初始位置
  72. shadowRowBoxView = instance.selectComponent('#shadowRowBox');
  73. shadowRowBoxView.setStyle({
  74. 'top': shadowRowTop + 'px'
  75. })
  76. shadowRowView = instance.selectComponent('#shadowRow')
  77. //长按事件
  78. if (config.longTouch) {
  79. touchTimer && clearTimeout(touchTimer);
  80. touchTimer = setTimeout(function() {
  81. longpress(event, instance);
  82. }, config.longTouchTime)
  83. }
  84. }
  85. function longpress(event, instance) {
  86. if (config.longTouch) {
  87. isMove = true;
  88. moveRow(instance, 0)
  89. }
  90. }
  91. function touchmove(event, instance) {
  92. var state = instance.getState();
  93. var rowData = event.instance.getDataset();
  94. var movePoint = event.touches[0];
  95. var initPoint = state.point;
  96. var moveY = movePoint.pageY - initPoint.pageY;
  97. if (config.longTouch) {
  98. if (Math.abs(moveY) > 10) {
  99. clearTimeout(touchTimer);
  100. }
  101. if (!isMove) {
  102. return;
  103. }
  104. }
  105. moveRow(instance, moveY);
  106. //阻止滚动页面
  107. if (event.preventDefault) {
  108. event.preventDefault();
  109. }
  110. return false;
  111. }
  112. function touchend(event, instance) {
  113. if (config.longTouch) {
  114. clearTimeout(touchTimer);
  115. }
  116. if (lastCommand != "stop") {
  117. lastCommand = "stop";
  118. config.autoScroll && instance.callMethod("pageScroll", {
  119. 'guid': config.guid,
  120. 'command': "stop"
  121. });
  122. }
  123. var state = instance.getState();
  124. // 把隐藏的行重新显示
  125. resetRowStyle(instance,state.rowData.id)
  126. // 隐藏ShadowRow
  127. resetShadowRowStyle(instance,state.offset)
  128. if (typeof state.offset !== "undefined" && rowSort != state.offset && state.offset != null) {
  129. var sortArray=[];
  130. for (var i = 0; i < sortList[config.guid].length; i++) {
  131. sortList[config.guid][i].lastSort = sortList[config.guid][i].newSort;
  132. sortArray.push(sortList[config.guid][i].newSort);
  133. sortList[config.guid][i].rowView.removeClass('ani');
  134. }
  135. instance.callMethod("sort", {
  136. index: rowSort,
  137. offset: state.offset,
  138. sortArray:sortArray
  139. });
  140. } else {
  141. sorting = false;
  142. triggerFeedbackGenerator(instance); //震动反馈
  143. return false;
  144. }
  145. state.offset = null;
  146. oldOffset = null;
  147. sorting = false;
  148. triggerFeedbackGenerator(instance); //震动反馈
  149. return false;
  150. }
  151. // 重置列表行
  152. function resetRowStyle(instance,id) {
  153. currentRowView.removeClass('hide');
  154. }
  155. // 重置拖拽行
  156. function resetShadowRowStyle(instance,offset) {
  157. shadowRowBoxView.removeClass('show');
  158. shadowRowBoxView.addClass('hide');
  159. shadowRowBoxView.setStyle({});
  160. }
  161. var lastCommand = '';
  162. // move Row
  163. function moveRow(instance, moveY) {
  164. var state = instance.getState();
  165. // 显示shadowRowBox
  166. shadowRowBoxView.removeClass('hide');
  167. shadowRowBoxView.hasClass('show') || shadowRowBoxView.addClass('show');
  168. // 移动shadowRowBox里面的shadowRow
  169. shadowRowView.setStyle({
  170. 'transform': 'translate3d(0,' + moveY + 'px,10px)',
  171. '-webkit-transform': 'translate3d(0,' + moveY + 'px,10px)'
  172. });
  173. // 隐藏列表对应行
  174. currentRowView.hasClass('hide') || currentRowView.addClass('hide');
  175. currentRowView.removeClass('ani')
  176. var listClientY = state.shadowRowTop + moveY + config.rowHeight/2;
  177. var tmpscrollListTop = scrollTop[config.guid];
  178. // 拖拽至边缘滚动视图 距离顶部距离1.5行高触发上滚动 下滚动同理
  179. var callMethodData = {
  180. guid: config.guid,
  181. command: listClientY < config.ListHeight * 0.2 ? "up" : listClientY > config.ListHeight - (config.ListHeight * 0.2) ? "down" :
  182. "stop",
  183. scrollTop: tmpscrollListTop,
  184. }
  185. // 把滚动指令发给逻辑层
  186. if (lastCommand != callMethodData.command) {
  187. lastCommand = callMethodData.command;
  188. config.autoScroll && instance.callMethod("pageScroll", callMethodData);
  189. }
  190. var moveOffset = moveY + scrollTop[config.guid] - state.initscrollTop;
  191. var offset = calcOffset(rowSort, moveOffset);
  192. if (offset <= 2 || offset >= config.listLength - 2) {
  193. callMethodData.command = 'stop';
  194. }
  195. // 为减少卡顿,微信小程序端,在滚动视图期间不进行列表位置交换
  196. if (config.autoScroll && (!config.isAppH5) && callMethodData.command != 'stop') {
  197. return;
  198. }
  199. oldOffset = oldOffset == null ? rowSort : oldOffset;
  200. if (offset < 0 || offset >= config.listLength) {
  201. return;
  202. }
  203. if (offset == oldOffset) {
  204. return;
  205. }
  206. oldOffset = offset;
  207. state.offset = offset;
  208. //触发change事件 并交换列表位置
  209. instance.callMethod("change", {
  210. index: rowSort,
  211. moveTo: state.offset
  212. });
  213. for (var i = 0; i < sortList[config.guid].length; i++) {
  214. var sort = sortList[config.guid][i].lastSort;
  215. var newSort = sortList[config.guid][i].newSort;
  216. if ((sort >= offset && sort <= rowSort) || (sort <= offset && sort >= rowSort)) {
  217. if(sort == rowSort) {
  218. newSort = offset;
  219. }else{
  220. newSort = sort < rowSort ? sort+1 : sort-1;
  221. }
  222. }else{
  223. newSort = sort;
  224. }
  225. if(sortList[config.guid][i].newSort == newSort){
  226. continue;
  227. }
  228. sortList[config.guid][i].newSort = newSort;
  229. var translateY = (sortList[config.guid][i].newSort-sortList[config.guid][i].sort) * 100;
  230. sortList[config.guid][i].rowView.hasClass('ani') || sortList[config.guid][i].rowView.addClass('ani');
  231. sortList[config.guid][i].rowView.setStyle({
  232. 'transform': 'translate3d(0,' + translateY + '%,0)',
  233. '-webkit-transform': 'translate3d(0,' + translateY + '%,0)'
  234. });
  235. }
  236. triggerFeedbackGenerator(instance); //震动反馈
  237. }
  238. //计算偏移index
  239. var oldOffset = null;
  240. function calcOffset(initSort, moveY) {
  241. var offset = initSort + parseInt(moveY / config.rowHeight); //偏移 行高的倍数
  242. var rest = moveY % config.rowHeight;
  243. if (rest > 0) {
  244. offset = offset + (rest / config.rowHeight >= 0.6 ? 1 : 0);
  245. if (offset < oldOffset) {
  246. offset = rest / config.rowHeight <= 0.4 ? offset : oldOffset;
  247. }
  248. } else
  249. {
  250. offset = offset + (rest / config.rowHeight <= -0.6 ? -1 : 0);
  251. if (offset > oldOffset) {
  252. offset = rest / config.rowHeight >= -0.4 ? offset : oldOffset;
  253. }
  254. }
  255. return offset;
  256. }
  257. //触感反馈
  258. //wxs 不支持条件编译,所以用此方法判断
  259. var isiOSAPP = typeof plus != "undefined" && plus.os.name == 'iOS';
  260. var UISelectionFeedbackGenerator;
  261. var impact
  262. if (isiOSAPP) {
  263. UISelectionFeedbackGenerator = plus.ios.importClass("UISelectionFeedbackGenerator");
  264. impact = new UISelectionFeedbackGenerator();
  265. impact.init();
  266. }
  267. function triggerFeedbackGenerator(instance) {
  268. if (!config.feedbackGenerator) {
  269. //关闭触感反馈
  270. return;
  271. }
  272. if (isiOSAPP) {
  273. //异步,避免与点击事件冲突
  274. setTimeout(function(){
  275. impact.selectionChanged();
  276. },0)
  277. } else {
  278. if (typeof plus != "undefined") {
  279. plus.device.vibrate(12)
  280. } else {
  281. instance.callMethod("vibrate");
  282. }
  283. }
  284. }
  285. var All_Config={};
  286. var config = {};
  287. function receiveData(e,state, instance){
  288. var data = JSON.parse(e);
  289. var tmp_config = {};
  290. var hasGuid = false;
  291. var sortArray=[];
  292. for(var i=0;i<data.length;i++){
  293. var arr = data[i];
  294. switch (arr[0]){
  295. case "sortArray":
  296. sortArray = arr[1];
  297. break;
  298. default:
  299. if(arr[0]=='guid'){
  300. hasGuid = true;
  301. }
  302. tmp_config[arr[0]] = arr[1];
  303. break;
  304. }
  305. }
  306. if(!hasGuid){
  307. return;
  308. }
  309. var isUpdateList = false;
  310. if(typeof All_Config[tmp_config.guid] == "undefined" ||typeof All_Config[tmp_config.guid].lastInitTime == "undefined" || All_Config[tmp_config.guid].lastInitTime!=tmp_config.lastInitTime){
  311. isUpdateList = true;
  312. }
  313. All_Config[tmp_config.guid] = tmp_config;
  314. if(isUpdateList){
  315. updateSortList(tmp_config.guid, instance,sortArray);
  316. }
  317. }
  318. // 更新guid对应的排序列表
  319. function updateSortList(guid, instance,sortArray) {
  320. sortList[guid]=[];
  321. var pageSortList = instance.selectAllComponents('.hm-row');
  322. for (var i = 0; i < pageSortList.length; i++){
  323. var tmp_row = {id:pageSortList[i].getDataset().id,sort:i,lastSort:parseInt(pageSortList[i].getDataset().sort),newSort:i,rowView:pageSortList[i]};
  324. if(sortArray.length>0){
  325. tmp_row.lastSort = sortArray[i];
  326. tmp_row.newSort = tmp_row.lastSort;
  327. }
  328. sortList[guid].push(tmp_row);
  329. var translateY = (tmp_row.lastSort-tmp_row.sort) * 100;
  330. tmp_row.rowView.setStyle({
  331. 'transform': 'translate3d(0,' + translateY + '%,0)',
  332. '-webkit-transform': 'translate3d(0,' + translateY + '%,0)'
  333. });
  334. }
  335. }
  336. // 输出
  337. module.exports = {
  338. receiveData:receiveData,
  339. scroll: scroll,
  340. longpress: longpress,
  341. touchstart: touchstart,
  342. touchmove: touchmove,
  343. touchend: touchend
  344. }