base.js 17 KB

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