index.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. "use strict";
  2. var __extends = (this && this.__extends) || (function () {
  3. var extendStatics = Object.setPrototypeOf ||
  4. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  5. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  6. return function (d, b) {
  7. extendStatics(d, b);
  8. function __() { this.constructor = d; }
  9. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  10. };
  11. })();
  12. var __assign = (this && this.__assign) || Object.assign || function(t) {
  13. for (var s, i = 1, n = arguments.length; i < n; i++) {
  14. s = arguments[i];
  15. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
  16. t[p] = s[p];
  17. }
  18. return t;
  19. };
  20. exports.__esModule = true;
  21. var React = require("react");
  22. var utils_1 = require("../utils");
  23. var doc = null;
  24. var Dragger = /** @class */ (function (_super) {
  25. __extends(Dragger, _super);
  26. function Dragger(props) {
  27. var _this = _super.call(this, props) || this;
  28. _this.mQue = 0;
  29. _this._ismounted = false;
  30. _this.state = {
  31. /** x轴位移,单位是px */
  32. x: _this.props.x || 0,
  33. /** y轴位移,单位是px */
  34. y: _this.props.y || 0,
  35. /**鼠标点击元素的原始位置,单位是px */
  36. originX: 0,
  37. originY: 0,
  38. isUserMove: true,
  39. /**已经移动的位移,单位是px */
  40. lastX: 0,
  41. lastY: 0,
  42. /**堆叠的层级 */
  43. zIndex: 1,
  44. w: _this.props.w || 0,
  45. h: _this.props.h || 0,
  46. lastW: 0,
  47. lastH: 0,
  48. originalEvent: null
  49. };
  50. _this.move = function (event) {
  51. var _a = _this.state, lastX = _a.lastX, lastY = _a.lastY;
  52. /* event.client - this.state.origin 表示的是移动的距离,
  53. * elX表示的是原来已经有的位移
  54. */
  55. var deltaX, deltaY;
  56. if (event.type.indexOf('mouse') >= 0) {
  57. deltaX = event.clientX - _this.state.originX + lastX;
  58. deltaY = event.clientY - _this.state.originY + lastY;
  59. }
  60. else {
  61. deltaX =
  62. event.touches[0].clientX -
  63. _this.state.originX +
  64. lastX;
  65. deltaY =
  66. event.touches[0].clientY -
  67. _this.state.originY +
  68. lastY;
  69. }
  70. var bounds = _this.props.bounds;
  71. if (bounds) {
  72. /**
  73. * 如果用户指定一个边界,那么在这里处理
  74. */
  75. var NewBounds = typeof bounds !== 'string' ? utils_1.parseBounds(bounds) : bounds;
  76. /**
  77. * 网格式移动范围设定,永远移动 n 的倍数
  78. * 注意:设定移动范围的时候,一定要在判断bounds之前,否则会造成bounds不对齐
  79. */
  80. var grid = _this.props.grid;
  81. if (Array.isArray(grid) && grid.length === 2) {
  82. deltaX = Math.round(deltaX / grid[0]) * grid[0];
  83. deltaY = Math.round(deltaY / grid[1]) * grid[1];
  84. }
  85. if (_this.props.bounds === 'parent') {
  86. NewBounds = {
  87. left: utils_1.int(_this.parent.style.paddingLeft) +
  88. utils_1.int(_this.self.style.marginLeft) -
  89. _this.self.offsetLeft,
  90. top: utils_1.int(_this.parent.style.paddingTop) +
  91. utils_1.int(_this.self.style.marginTop) -
  92. _this.self.offsetTop,
  93. right: utils_1.innerWidth(_this.parent) -
  94. utils_1.outerWidth(_this.self) -
  95. _this.self.offsetLeft +
  96. utils_1.int(_this.parent.style.paddingRight) -
  97. utils_1.int(_this.self.style.marginRight),
  98. bottom: utils_1.innerHeight(_this.parent) -
  99. utils_1.outerHeight(_this.self) -
  100. _this.self.offsetTop +
  101. utils_1.int(_this.parent.style.paddingBottom) -
  102. utils_1.int(_this.self.style.marginBottom)
  103. };
  104. }
  105. /**
  106. * 保证不超出右边界和底部
  107. * keep element right and bot can not cross the bounds
  108. */
  109. if (NewBounds !== 'parent')
  110. deltaX = Math.min(deltaX, NewBounds.right);
  111. if (NewBounds !== 'parent')
  112. deltaY = Math.min(deltaY, NewBounds.bottom);
  113. /**
  114. * 保证不超出左边和上边
  115. * keep element left and top can not cross the bounds
  116. */
  117. if (NewBounds !== 'parent')
  118. deltaX = Math.max(deltaX, NewBounds.left);
  119. if (NewBounds !== 'parent')
  120. deltaY = Math.max(deltaY, NewBounds.top);
  121. }
  122. /**如果设置了x,y限制 */
  123. deltaX = _this.props.allowX ? deltaX : 0;
  124. deltaY = _this.props.allowY ? deltaY : 0;
  125. /**
  126. * 调整手感
  127. * 无论是向上移动还是向下移动,全部都是根据重力中心
  128. * */
  129. var height = _this.Ref.getClientRects()[0].height;
  130. var upNdown = _this.state.y - deltaY;
  131. var fixY = deltaY + (upNdown >= 0 ? 0 : height / 2);
  132. /**移动时回调,用于外部控制 */
  133. if (_this.props.onMove)
  134. _this.props.onMove(event, deltaX, fixY);
  135. _this.setState({
  136. x: deltaX,
  137. y: deltaY
  138. });
  139. };
  140. _this.moveDebounce = function (event) {
  141. var _a = _this.state, lastX = _a.lastX, lastY = _a.lastY;
  142. /* event.client - this.state.origin 表示的是移动的距离,
  143. * elX表示的是原来已经有的位移
  144. */
  145. var deltaX, deltaY;
  146. if (event.type.indexOf('mouse') >= 0) {
  147. deltaX = event.clientX - _this.state.originX + lastX;
  148. deltaY = event.clientY - _this.state.originY + lastY;
  149. }
  150. else {
  151. deltaX =
  152. event.touches[0].clientX -
  153. _this.state.originX +
  154. lastX;
  155. deltaY =
  156. event.touches[0].clientY -
  157. _this.state.originY +
  158. lastY;
  159. }
  160. /*
  161. * Remove Debounce event listeners and add legitimate ones
  162. * after 10 pixels motion
  163. */
  164. if ((Math.abs(deltaX) + Math.abs(deltaY)) > 10) {
  165. // Remove debounce event listeners
  166. if (event.type.indexOf('mouse') >= 0) {
  167. doc.removeEventListener('mousemove', _this.moveDebounce);
  168. doc.removeEventListener('mouseup', _this.onDragEndDebounce);
  169. }
  170. else {
  171. doc.removeEventListener('touchmove', _this.moveDebounce);
  172. doc.removeEventListener('touchend', _this.onDragEndDebounce);
  173. }
  174. // Initiate real dragStart with original event
  175. _this.onDragStart(_this.state.originalEvent);
  176. // Trigger real movement with current event");
  177. _this.move(event);
  178. }
  179. };
  180. // Saves initial state and event, but add event listeners for debounce only
  181. _this.onDragStartDebounce = function (event) {
  182. var originX, originY;
  183. if (event.type.indexOf('mouse') >= 0) {
  184. originX = event.clientX;
  185. originY = event.clientY;
  186. }
  187. else {
  188. originX = event.touches[0].clientX;
  189. originY = event.touches[0].clientY;
  190. }
  191. event.persist();
  192. _this.setState({
  193. originalEvent: event,
  194. originX: originX,
  195. originY: originY,
  196. lastX: _this.state.x,
  197. lastY: _this.state.y,
  198. zIndex: 10
  199. });
  200. // Add event listeners at the end to prevent firing them before
  201. // having the original event saved into state
  202. if (event.type.indexOf('mouse') >= 0) {
  203. doc.addEventListener('mousemove', _this.moveDebounce);
  204. doc.addEventListener('mouseup', _this.onDragEndDebounce);
  205. }
  206. else {
  207. doc.addEventListener('touchmove', _this.moveDebounce);
  208. doc.addEventListener('touchend', _this.onDragEndDebounce);
  209. }
  210. };
  211. // Cleans debounce events
  212. _this.onDragEndDebounce = function (event) {
  213. /** 取消用户选择限制,用户可以重新选择 */
  214. doc.body.style.userSelect = '';
  215. _this.parent = null;
  216. _this.self = null;
  217. if (event.type.indexOf('mouse') >= 0) {
  218. // Remove debounce event listeners");
  219. doc.removeEventListener('mousemove', _this.moveDebounce);
  220. doc.removeEventListener('mouseup', _this.onDragEndDebounce);
  221. }
  222. else {
  223. doc.removeEventListener('touchmove', _this.moveDebounce);
  224. doc.removeEventListener('touchend', _this.onDragEndDebounce);
  225. }
  226. _this.setState({
  227. originalEvent: null
  228. });
  229. };
  230. _this.onDragStart = function (event) {
  231. /** 保证用户在移动元素的时候不会选择到元素内部的东西 */
  232. doc.body.style.userSelect = 'none';
  233. // if (event.target.id !== 'dragact-handle') return
  234. /**
  235. * 把监听事件的回掉函数,绑定在document上
  236. * 当设置边界的时候,用户鼠标会离开元素的范围
  237. * 绑定在document上可以使得其依旧能够监听
  238. * 如果绑定在元素上,则鼠标离开元素,就不会再被监听了
  239. */
  240. if (event.type.indexOf('mouse') >= 0) {
  241. doc.addEventListener('mousemove', _this.move);
  242. doc.addEventListener('mouseup', _this.onDragEnd);
  243. }
  244. else {
  245. doc.addEventListener('touchmove', _this.move);
  246. doc.addEventListener('touchend', _this.onDragEnd);
  247. }
  248. if (_this.props.bounds === 'parent' &&
  249. /**为了让 这段代码不会重复执行 */
  250. (typeof _this.parent === 'undefined' || _this.parent === null)) {
  251. /**
  252. * 在这里我们将父节点缓存下来,保证当用户鼠标离开拖拽区域时,我们仍然能获取到父节点
  253. * what we do here is
  254. * making sure that we still can retrieve our parent when user's mouse left this node.
  255. */
  256. _this.parent = event.currentTarget.offsetParent; //todo
  257. /**
  258. * 我们自己
  259. * ourself
  260. */
  261. _this.self = event.currentTarget;
  262. }
  263. _this.props.onDragStart &&
  264. _this.props.onDragStart(_this.state.x, _this.state.y);
  265. var originX, originY;
  266. if (event.type.indexOf('mouse') >= 0) {
  267. originX = event.clientX;
  268. originY = event.clientY;
  269. }
  270. else {
  271. originX = event.touches[0].clientX;
  272. originY = event.touches[0].clientY;
  273. }
  274. _this.setState({
  275. originX: originX,
  276. originY: originY,
  277. lastX: _this.state.x,
  278. lastY: _this.state.y,
  279. zIndex: 10
  280. });
  281. };
  282. _this.onDragEnd = function (event) {
  283. /** 取消用户选择限制,用户可以重新选择 */
  284. doc.body.style.userSelect = '';
  285. _this.parent = null;
  286. _this.self = null;
  287. if (event.type.indexOf('mouse') >= 0) {
  288. doc.removeEventListener('mousemove', _this.move);
  289. doc.removeEventListener('mouseup', _this.onDragEnd);
  290. }
  291. else {
  292. doc.removeEventListener('touchmove', _this.move);
  293. doc.removeEventListener('touchend', _this.onDragEnd);
  294. }
  295. if (_this._ismounted) {
  296. _this.setState({
  297. zIndex: 1
  298. });
  299. }
  300. _this.props.onDragEnd &&
  301. _this.props.onDragEnd(event, _this.state.x, _this.state.y);
  302. };
  303. _this.onResizeStart = function (event) {
  304. /** 保证用户在移动元素的时候不会选择到元素内部的东西 */
  305. doc.body.style.userSelect = 'none';
  306. doc.addEventListener('mouseup', _this.onResizeEnd);
  307. doc.addEventListener('mousemove', _this.onResizing);
  308. var originX, originY;
  309. originX = event.clientX;
  310. originY = event.clientY;
  311. _this.props.onResizeStart &&
  312. _this.props.onResizeStart(event, _this.state.w, _this.state.h);
  313. _this.setState({
  314. originX: originX,
  315. originY: originY,
  316. zIndex: 2,
  317. lastW: _this.state.w,
  318. lastH: _this.state.h
  319. });
  320. event.stopPropagation();
  321. };
  322. _this.onResizing = function (event) {
  323. /* event.client - this.state.origin 表示的是移动的距离,
  324. * elX表示的是原来已经有的位移
  325. */
  326. var deltaX, deltaY;
  327. if (event.type.indexOf('mouse') >= 0) {
  328. deltaX = event.clientX - _this.state.originX;
  329. deltaY = event.clientY - _this.state.originY;
  330. }
  331. else {
  332. deltaX =
  333. event.touches[0].clientX - _this.state.originX;
  334. deltaY =
  335. event.touches[0].clientY - _this.state.originY;
  336. }
  337. /**移动时回调,用于外部控制 */
  338. _this.props.onResizing &&
  339. _this.props.onResizing(event, _this.state.w, _this.state.h);
  340. _this.setState({
  341. w: deltaX + _this.state.lastW,
  342. h: deltaY + _this.state.lastH
  343. });
  344. };
  345. _this.onResizeEnd = function (event) {
  346. doc.body.style.userSelect = '';
  347. doc.removeEventListener('mousemove', _this.onResizing);
  348. doc.removeEventListener('mouseup', _this.onResizeEnd);
  349. _this.props.onResizeEnd &&
  350. _this.props.onResizeEnd(event, _this.state.w, _this.state.h);
  351. };
  352. _this.movePerFrame = function (delt) {
  353. _this.setState({
  354. y: _this.state.y + delt
  355. });
  356. _this.mQue++;
  357. if (_this.mQue >= 10) {
  358. _this.mQue = 0;
  359. return;
  360. }
  361. requestAnimationFrame(function () { return _this.movePerFrame(delt); });
  362. };
  363. _this.mixin = function () {
  364. var dragMix = {
  365. onMouseDown: _this.onDragStartDebounce,
  366. onTouchStart: _this.onDragStartDebounce,
  367. onTouchEnd: _this.onDragEndDebounce,
  368. onMouseUp: _this.onDragEndDebounce
  369. };
  370. var resizeMix = {
  371. onMouseDown: _this.onResizeStart,
  372. onMouseUp: _this.onResizeEnd
  373. };
  374. return {
  375. dragMix: dragMix,
  376. resizeMix: resizeMix
  377. };
  378. };
  379. // this.move = this.move.bind(this)
  380. // this.onDragEnd = this.onDragEnd.bind(this)
  381. _this.parent = null;
  382. _this.self = null;
  383. return _this;
  384. }
  385. Dragger.prototype.componentDidMount = function () {
  386. doc = typeof document === 'undefined' ? {} : document;
  387. this._ismounted = true;
  388. };
  389. Dragger.prototype.componentWillUnmount = function () {
  390. this._ismounted = false;
  391. };
  392. Dragger.prototype.componentWillReceiveProps = function (nextProps) {
  393. /**
  394. * 外部props 改变的时候更新元素的内部位置
  395. * 这个api设计其实很不好
  396. * 以后可能会修改掉
  397. */
  398. var isUserMove = nextProps.isUserMove;
  399. if (!isUserMove) {
  400. if (typeof nextProps.x === 'number' &&
  401. typeof nextProps.y === 'number') {
  402. this.setState({
  403. y: nextProps.y,
  404. x: nextProps.x,
  405. lastX: nextProps.x,
  406. lastY: nextProps.y,
  407. w: nextProps.w,
  408. h: nextProps.h
  409. });
  410. }
  411. }
  412. };
  413. Dragger.prototype.render = function () {
  414. var _this = this;
  415. var _a = this.state, x = _a.x, y = _a.y, w = _a.w, h = _a.h;
  416. var style = this.props.style;
  417. if (!this.props.isUserMove) {
  418. /**当外部设置其props的x,y初始属性的时候,我们在这里设置元素的初始位移 */
  419. x = this.props.x ? this.props.x : 0;
  420. y = this.props.y ? this.props.y : 0;
  421. if (style) {
  422. w = style.width ? style.width : w;
  423. h = style.height ? style.height : h;
  424. }
  425. }
  426. if (style) {
  427. //使得初始化的时候,不会有从0-1缩放动画
  428. w = w === 0 ? style.width : w;
  429. h = h === 0 ? style.height : h;
  430. }
  431. var _b = this.mixin(), dragMix = _b.dragMix, resizeMix = _b.resizeMix;
  432. var provided = {
  433. style: __assign({}, style, { touchAction: 'none!important', transform: "translate3d(" + x + "px," + y + "px,0px)", width: w, height: h }),
  434. ref: function (node) { return (_this.Ref = node); }
  435. };
  436. return this.props.children(provided, dragMix, resizeMix);
  437. };
  438. /**
  439. * 初始变量设置
  440. */
  441. Dragger.defaultProps = {
  442. allowX: true,
  443. allowY: true,
  444. isUserMove: true
  445. };
  446. return Dragger;
  447. }(React.Component));
  448. exports.Dragger = Dragger;