index.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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. Object.defineProperty(exports, "__esModule", { value: true });
  21. var React = require("react");
  22. var utils_1 = require("../utils");
  23. /// <reference path="react.d.ts" />
  24. var doc = document;
  25. var Dragger = /** @class */ (function (_super) {
  26. __extends(Dragger, _super);
  27. function Dragger(props) {
  28. var _this = _super.call(this, props) || this;
  29. _this.state = {
  30. /** x轴位移,单位是px */
  31. x: 0,
  32. /** y轴位移,单位是px */
  33. y: 0,
  34. /**鼠标点击元素的原始位置,单位是px */
  35. originX: 0,
  36. originY: 0,
  37. isUserMove: true,
  38. /**已经移动的位移,单位是px */
  39. lastX: 0,
  40. lastY: 0,
  41. /**堆叠的层级 */
  42. zIndex: 1
  43. };
  44. _this.move = _this.move.bind(_this);
  45. _this.onDragEnd = _this.onDragEnd.bind(_this);
  46. _this.parent = null;
  47. _this.self = null;
  48. return _this;
  49. }
  50. Dragger.prototype.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 = event.touches[0].clientX - this.state.originX + lastX;
  62. deltaY = event.touches[0].clientY - this.state.originY + lastY;
  63. }
  64. var bounds = this.props.bounds;
  65. if (bounds) {
  66. /**
  67. * 如果用户指定一个边界,那么在这里处理
  68. */
  69. var NewBounds = typeof bounds !== 'string' ? utils_1.parseBounds(bounds) : bounds;
  70. /**
  71. * 网格式移动范围设定,永远移动 n 的倍数
  72. * 注意:设定移动范围的时候,一定要在判断bounds之前,否则会造成bounds不对齐
  73. */
  74. var grid = this.props.grid;
  75. if (Array.isArray(grid) && grid.length === 2) {
  76. deltaX = Math.round(deltaX / grid[0]) * grid[0];
  77. deltaY = Math.round(deltaY / grid[1]) * grid[1];
  78. }
  79. if (this.props.bounds === 'parent') {
  80. NewBounds = {
  81. left: utils_1.int(this.parent.style.paddingLeft) + utils_1.int(this.self.style.marginLeft) - this.self.offsetLeft,
  82. top: utils_1.int(this.parent.style.paddingTop) + utils_1.int(this.self.style.marginTop) - this.self.offsetTop,
  83. right: utils_1.innerWidth(this.parent) - utils_1.outerWidth(this.self) - this.self.offsetLeft +
  84. utils_1.int(this.parent.style.paddingRight) - utils_1.int(this.self.style.marginRight),
  85. bottom: utils_1.innerHeight(this.parent) - utils_1.outerHeight(this.self) - this.self.offsetTop +
  86. utils_1.int(this.parent.style.paddingBottom) - utils_1.int(this.self.style.marginBottom)
  87. };
  88. }
  89. /**
  90. * 保证不超出右边界和底部
  91. * keep element right and bot can not cross the bounds
  92. */
  93. if (NewBounds !== 'parent')
  94. deltaX = Math.min(deltaX, NewBounds.right);
  95. if (NewBounds !== 'parent')
  96. deltaY = Math.min(deltaY, NewBounds.bottom);
  97. /**
  98. * 保证不超出左边和上边
  99. * keep element left and top can not cross the bounds
  100. */
  101. if (NewBounds !== 'parent')
  102. deltaX = Math.max(deltaX, NewBounds.left);
  103. if (NewBounds !== 'parent')
  104. deltaY = Math.max(deltaY, NewBounds.top);
  105. }
  106. /**如果设置了x,y限制 */
  107. deltaX = this.props.allowX ? deltaX : 0;
  108. deltaY = this.props.allowY ? deltaY : 0;
  109. /**移动时回调,用于外部控制 */
  110. if (this.props.onMove)
  111. this.props.onMove(event, deltaX, deltaY);
  112. this.setState({
  113. x: deltaX,
  114. y: deltaY
  115. });
  116. };
  117. Dragger.prototype.onDragStart = function (event) {
  118. /** 保证用户在移动元素的时候不会选择到元素内部的东西 */
  119. doc.body.style.userSelect = 'none';
  120. // if (this.props.hasDraggerHandle) {
  121. // if (event.target.className !== 'handle') return
  122. // }
  123. /**
  124. * 把监听事件的回掉函数,绑定在document上
  125. * 当设置边界的时候,用户鼠标会离开元素的范围
  126. * 绑定在document上可以使得其依旧能够监听
  127. * 如果绑定在元素上,则鼠标离开元素,就不会再被监听了
  128. */
  129. if (event.type.indexOf('mouse') >= 0) {
  130. doc.addEventListener('mousemove', this.move);
  131. doc.addEventListener('mouseup', this.onDragEnd);
  132. }
  133. else {
  134. doc.addEventListener('touchmove', this.move);
  135. doc.addEventListener('touchend', this.onDragEnd);
  136. }
  137. if (this.props.bounds === 'parent' &&
  138. /**为了让 这段代码不会重复执行 */
  139. (typeof this.parent === 'undefined' || this.parent === null)) {
  140. /**
  141. * 在这里我们将父节点缓存下来,保证当用户鼠标离开拖拽区域时,我们仍然能获取到父节点
  142. * what we do here is
  143. * making sure that we still can retrieve our parent when user's mouse left this node.
  144. */
  145. this.parent = event.currentTarget.offsetParent; //todo
  146. /**
  147. * 我们自己
  148. * ourself
  149. */
  150. this.self = event.currentTarget;
  151. }
  152. this.props.onDragStart && this.props.onDragStart(this.state.x, this.state.y);
  153. var originX, originY;
  154. if (event.type.indexOf('mouse') >= 0) {
  155. originX = event.clientX;
  156. originY = event.clientY;
  157. }
  158. else {
  159. originX = event.touches[0].clientX;
  160. originY = event.touches[0].clientY;
  161. }
  162. this.setState({
  163. originX: originX,
  164. originY: originY,
  165. lastX: this.state.x,
  166. lastY: this.state.y,
  167. zIndex: 10
  168. });
  169. };
  170. Dragger.prototype.onDragEnd = function (event) {
  171. /** 取消用户选择限制,用户可以重新选择 */
  172. doc.body.style.userSelect = '';
  173. this.parent = null;
  174. this.self = null;
  175. if (event.type.indexOf('mouse') >= 0) {
  176. doc.removeEventListener('mousemove', this.move);
  177. doc.removeEventListener('mouseup', this.onDragEnd);
  178. }
  179. else {
  180. doc.removeEventListener('touchmove', this.move);
  181. doc.removeEventListener('touchend', this.onDragEnd);
  182. }
  183. this.setState({
  184. zIndex: 1
  185. });
  186. this.props.onDragEnd && this.props.onDragEnd(event);
  187. };
  188. Dragger.prototype.componentDidMount = function () {
  189. /**
  190. * 这个函数只会调用一次
  191. * 这个只是一个临时的解决方案,因为这样会使得元素进行两次刷新
  192. */
  193. if (typeof this.props.x === 'number' &&
  194. typeof this.props.y === 'number') {
  195. this.setState({
  196. x: this.props.x,
  197. y: this.props.y
  198. });
  199. }
  200. };
  201. Dragger.prototype.componentWillReceiveProps = function (nextProps) {
  202. /**
  203. * 外部props 改变的时候更新元素的内部位置
  204. * 这个api设计其实很不好
  205. * 以后可能会修改掉
  206. */
  207. var isUserMove = nextProps.isUserMove;
  208. if (!isUserMove) {
  209. if (typeof nextProps.x === 'number' &&
  210. typeof nextProps.y === 'number') {
  211. this.setState({
  212. x: nextProps.x,
  213. y: nextProps.y,
  214. lastX: nextProps.x,
  215. lastY: nextProps.y
  216. });
  217. }
  218. }
  219. };
  220. Dragger.prototype.render = function () {
  221. var _a = this.state, x = _a.x, y = _a.y, zIndex = _a.zIndex;
  222. var _b = this.props, style = _b.style, className = _b.className;
  223. if (!this.props.isUserMove) {
  224. /**当外部设置其props的x,y初始属性的时候,我们在这里设置元素的初始位移 */
  225. x = this.props.x ? this.props.x : 0;
  226. y = this.props.y ? this.props.y : 0;
  227. }
  228. /**主要是为了让用户定义自己的className去修改css */
  229. var fixedClassName = typeof className === 'undefined' ? '' : className + ' ';
  230. return (React.createElement("div", { className: fixedClassName + "WrapDragger", style: __assign({}, style, { zIndex: zIndex, touchAction: 'none!important', transform: "translate(" + x + "px," + y + "px)" }), onMouseDown: this.onDragStart.bind(this), onTouchStart: this.onDragStart.bind(this), onTouchEnd: this.onDragEnd.bind(this), onMouseUp: this.onDragEnd.bind(this) }, React.Children.only(this.props.children)));
  231. };
  232. /**
  233. * 初始变量设置
  234. */
  235. Dragger.defaultProps = {
  236. allowX: true,
  237. allowY: true,
  238. isUserMove: true
  239. };
  240. return Dragger;
  241. }(React.Component));
  242. exports.Dragger = Dragger;