index.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. var __extends = (this && this.__extends) || (function () {
  2. var extendStatics = Object.setPrototypeOf ||
  3. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  4. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  5. return function (d, b) {
  6. extendStatics(d, b);
  7. function __() { this.constructor = d; }
  8. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  9. };
  10. })();
  11. var __assign = (this && this.__assign) || Object.assign || function(t) {
  12. for (var s, i = 1, n = arguments.length; i < n; i++) {
  13. s = arguments[i];
  14. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
  15. t[p] = s[p];
  16. }
  17. return t;
  18. };
  19. import * as React from "react";
  20. import { int, innerHeight, innerWidth, outerHeight, outerWidth, parseBounds } from '../utils';
  21. var doc = document;
  22. var Dragger = /** @class */ (function (_super) {
  23. __extends(Dragger, _super);
  24. function Dragger(props) {
  25. var _this = _super.call(this, props) || this;
  26. _this.state = {
  27. /** x轴位移,单位是px */
  28. x: 0,
  29. /** y轴位移,单位是px */
  30. y: 0,
  31. /**鼠标点击元素的原始位置,单位是px */
  32. originX: 0,
  33. originY: 0,
  34. isUserMove: true,
  35. /**已经移动的位移,单位是px */
  36. lastX: 0,
  37. lastY: 0,
  38. /**堆叠的层级 */
  39. zIndex: 1,
  40. w: 0,
  41. h: 0,
  42. lastW: 0,
  43. lastH: 0
  44. };
  45. _this.onResizeStart = function (event) {
  46. /** 保证用户在移动元素的时候不会选择到元素内部的东西 */
  47. doc.body.style.userSelect = 'none';
  48. doc.addEventListener('mouseup', _this.onResizeEnd);
  49. doc.addEventListener('mousemove', _this.onResizing);
  50. var originX, originY;
  51. originX = event.clientX;
  52. originY = event.clientY;
  53. _this.props.onResizeStart && _this.props.onResizeStart(event, _this.state.w, _this.state.h);
  54. _this.setState({
  55. originX: originX,
  56. originY: originY,
  57. zIndex: 2,
  58. lastW: _this.state.w,
  59. lastH: _this.state.h
  60. });
  61. event.stopPropagation();
  62. };
  63. _this.onResizing = function (event) {
  64. /* event.client - this.state.origin 表示的是移动的距离,
  65. * elX表示的是原来已经有的位移
  66. */
  67. var deltaX, deltaY;
  68. if (event.type.indexOf('mouse') >= 0) {
  69. deltaX = event.clientX - _this.state.originX;
  70. deltaY = event.clientY - _this.state.originY;
  71. }
  72. else {
  73. deltaX = event.touches[0].clientX - _this.state.originX;
  74. deltaY = event.touches[0].clientY - _this.state.originY;
  75. }
  76. /**移动时回调,用于外部控制 */
  77. _this.props.onResizing && _this.props.onResizing(event, _this.state.w, _this.state.h);
  78. _this.setState({
  79. w: deltaX + _this.state.lastW,
  80. h: deltaY + _this.state.lastH
  81. });
  82. };
  83. _this.onResizeEnd = function (event) {
  84. doc.body.style.userSelect = '';
  85. doc.removeEventListener('mousemove', _this.onResizing);
  86. doc.removeEventListener('mouseup', _this.onResizeEnd);
  87. _this.props.onResizeEnd && _this.props.onResizeEnd(event, _this.state.w, _this.state.h);
  88. };
  89. _this.move = _this.move.bind(_this);
  90. _this.onDragEnd = _this.onDragEnd.bind(_this);
  91. _this.parent = null;
  92. _this.self = null;
  93. return _this;
  94. }
  95. Dragger.prototype.move = function (event) {
  96. var _a = this.state, lastX = _a.lastX, lastY = _a.lastY;
  97. /* event.client - this.state.origin 表示的是移动的距离,
  98. * elX表示的是原来已经有的位移
  99. */
  100. var deltaX, deltaY;
  101. if (event.type.indexOf('mouse') >= 0) {
  102. deltaX = event.clientX - this.state.originX + lastX;
  103. deltaY = event.clientY - this.state.originY + lastY;
  104. }
  105. else {
  106. deltaX = event.touches[0].clientX - this.state.originX + lastX;
  107. deltaY = event.touches[0].clientY - this.state.originY + lastY;
  108. }
  109. var bounds = this.props.bounds;
  110. if (bounds) {
  111. /**
  112. * 如果用户指定一个边界,那么在这里处理
  113. */
  114. var NewBounds = typeof bounds !== 'string' ? parseBounds(bounds) : bounds;
  115. /**
  116. * 网格式移动范围设定,永远移动 n 的倍数
  117. * 注意:设定移动范围的时候,一定要在判断bounds之前,否则会造成bounds不对齐
  118. */
  119. var grid = this.props.grid;
  120. if (Array.isArray(grid) && grid.length === 2) {
  121. deltaX = Math.round(deltaX / grid[0]) * grid[0];
  122. deltaY = Math.round(deltaY / grid[1]) * grid[1];
  123. }
  124. if (this.props.bounds === 'parent') {
  125. NewBounds = {
  126. left: int(this.parent.style.paddingLeft) + int(this.self.style.marginLeft) - this.self.offsetLeft,
  127. top: int(this.parent.style.paddingTop) + int(this.self.style.marginTop) - this.self.offsetTop,
  128. right: innerWidth(this.parent) - outerWidth(this.self) - this.self.offsetLeft +
  129. int(this.parent.style.paddingRight) - int(this.self.style.marginRight),
  130. bottom: innerHeight(this.parent) - outerHeight(this.self) - this.self.offsetTop +
  131. int(this.parent.style.paddingBottom) - int(this.self.style.marginBottom)
  132. };
  133. }
  134. /**
  135. * 保证不超出右边界和底部
  136. * keep element right and bot can not cross the bounds
  137. */
  138. if (NewBounds !== 'parent')
  139. deltaX = Math.min(deltaX, NewBounds.right);
  140. if (NewBounds !== 'parent')
  141. deltaY = Math.min(deltaY, NewBounds.bottom);
  142. /**
  143. * 保证不超出左边和上边
  144. * keep element left and top can not cross the bounds
  145. */
  146. if (NewBounds !== 'parent')
  147. deltaX = Math.max(deltaX, NewBounds.left);
  148. if (NewBounds !== 'parent')
  149. deltaY = Math.max(deltaY, NewBounds.top);
  150. }
  151. /**如果设置了x,y限制 */
  152. deltaX = this.props.allowX ? deltaX : 0;
  153. deltaY = this.props.allowY ? deltaY : 0;
  154. /**移动时回调,用于外部控制 */
  155. if (this.props.onMove)
  156. this.props.onMove(event, deltaX, deltaY);
  157. this.setState({
  158. x: deltaX,
  159. y: deltaY
  160. });
  161. };
  162. Dragger.prototype.onDragStart = function (event) {
  163. /** 保证用户在移动元素的时候不会选择到元素内部的东西 */
  164. doc.body.style.userSelect = 'none';
  165. // if (this.props.hasDraggerHandle) {
  166. // if (event.target.className !== 'handle') return
  167. // }
  168. /**
  169. * 把监听事件的回掉函数,绑定在document上
  170. * 当设置边界的时候,用户鼠标会离开元素的范围
  171. * 绑定在document上可以使得其依旧能够监听
  172. * 如果绑定在元素上,则鼠标离开元素,就不会再被监听了
  173. */
  174. if (event.type.indexOf('mouse') >= 0) {
  175. doc.addEventListener('mousemove', this.move);
  176. doc.addEventListener('mouseup', this.onDragEnd);
  177. }
  178. else {
  179. doc.addEventListener('touchmove', this.move);
  180. doc.addEventListener('touchend', this.onDragEnd);
  181. }
  182. if (this.props.bounds === 'parent' &&
  183. /**为了让 这段代码不会重复执行 */
  184. (typeof this.parent === 'undefined' || this.parent === null)) {
  185. /**
  186. * 在这里我们将父节点缓存下来,保证当用户鼠标离开拖拽区域时,我们仍然能获取到父节点
  187. * what we do here is
  188. * making sure that we still can retrieve our parent when user's mouse left this node.
  189. */
  190. this.parent = event.currentTarget.offsetParent; //todo
  191. /**
  192. * 我们自己
  193. * ourself
  194. */
  195. this.self = event.currentTarget;
  196. }
  197. this.props.onDragStart && this.props.onDragStart(this.state.x, this.state.y);
  198. var originX, originY;
  199. if (event.type.indexOf('mouse') >= 0) {
  200. originX = event.clientX;
  201. originY = event.clientY;
  202. }
  203. else {
  204. originX = event.touches[0].clientX;
  205. originY = event.touches[0].clientY;
  206. }
  207. this.setState({
  208. originX: originX,
  209. originY: originY,
  210. lastX: this.state.x,
  211. lastY: this.state.y,
  212. zIndex: 10
  213. });
  214. };
  215. Dragger.prototype.onDragEnd = function (event) {
  216. /** 取消用户选择限制,用户可以重新选择 */
  217. doc.body.style.userSelect = '';
  218. this.parent = null;
  219. this.self = null;
  220. if (event.type.indexOf('mouse') >= 0) {
  221. doc.removeEventListener('mousemove', this.move);
  222. doc.removeEventListener('mouseup', this.onDragEnd);
  223. }
  224. else {
  225. doc.removeEventListener('touchmove', this.move);
  226. doc.removeEventListener('touchend', this.onDragEnd);
  227. }
  228. this.setState({
  229. zIndex: 1
  230. });
  231. this.props.onDragEnd && this.props.onDragEnd(event, this.state.x, this.state.y);
  232. };
  233. Dragger.prototype.componentDidMount = function () {
  234. /**
  235. * 这个函数只会调用一次
  236. * 这个只是一个临时的解决方案,因为这样会使得元素进行两次刷新
  237. */
  238. if (typeof this.props.x === 'number' &&
  239. typeof this.props.y === 'number') {
  240. this.setState({
  241. x: this.props.x,
  242. y: this.props.y
  243. });
  244. }
  245. };
  246. Dragger.prototype.componentWillReceiveProps = function (nextProps) {
  247. /**
  248. * 外部props 改变的时候更新元素的内部位置
  249. * 这个api设计其实很不好
  250. * 以后可能会修改掉
  251. */
  252. var isUserMove = nextProps.isUserMove;
  253. if (!isUserMove) {
  254. if (typeof nextProps.x === 'number' &&
  255. typeof nextProps.y === 'number') {
  256. this.setState({
  257. x: nextProps.x,
  258. y: nextProps.y,
  259. lastX: nextProps.x,
  260. lastY: nextProps.y,
  261. w: nextProps.w,
  262. h: nextProps.h
  263. });
  264. }
  265. }
  266. };
  267. Dragger.prototype.render = function () {
  268. var _a = this.state, x = _a.x, y = _a.y, w = _a.w, h = _a.h;
  269. var _b = this.props, style = _b.style, className = _b.className;
  270. if (!this.props.isUserMove) {
  271. /**当外部设置其props的x,y初始属性的时候,我们在这里设置元素的初始位移 */
  272. x = this.props.x ? this.props.x : 0;
  273. y = this.props.y ? this.props.y : 0;
  274. if (style) {
  275. w = style.width ? style.width : w;
  276. h = style.height ? style.height : h;
  277. console.log(style);
  278. }
  279. }
  280. if (style) {
  281. w = w === 0 ? style.width : w;
  282. h = h === 0 ? style.height : h;
  283. }
  284. /**主要是为了让用户定义自己的className去修改css */
  285. var fixedClassName = typeof className === 'undefined' ? '' : className + ' ';
  286. return (React.createElement("div", { className: fixedClassName + "WrapDragger", style: __assign({}, style, { touchAction: 'none!important', transform: "translate(" + x + "px," + y + "px)", width: w, height: h }), onMouseDown: this.onDragStart.bind(this), onTouchStart: this.onDragStart.bind(this), onTouchEnd: this.onDragEnd.bind(this), onMouseUp: this.onDragEnd.bind(this) },
  287. React.Children.only(this.props.children),
  288. React.createElement("span", { onMouseDown: this.onResizeStart,
  289. // onTouchStart={this.onDragStart.bind(this)}
  290. // onTouchEnd={this.onDragEnd.bind(this)}
  291. onMouseUp: this.onResizeEnd, style: {
  292. position: 'absolute',
  293. width: 10, height: 10, right: 2, bottom: 2, cursor: 'se-resize',
  294. borderRight: '2px solid rgba(15,15,15,0.2)',
  295. borderBottom: '2px solid rgba(15,15,15,0.2)'
  296. } })));
  297. };
  298. /**
  299. * 初始变量设置
  300. */
  301. Dragger.defaultProps = {
  302. allowX: true,
  303. allowY: true,
  304. isUserMove: true
  305. };
  306. return Dragger;
  307. }(React.Component));
  308. export { Dragger };