App.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import React from 'react'
  2. import PropTypes from 'prop-types'
  3. import './style.css'
  4. const int = (number) => {
  5. if (number === '') {
  6. return 0
  7. }
  8. return parseInt(number, 10)
  9. }
  10. const outerWidth = (node) => {
  11. let width = node.clientWidth;
  12. const computedStyle = node.style
  13. width += int(computedStyle.borderLeftWidth);
  14. width += int(computedStyle.borderRightWidth);
  15. return width;
  16. }
  17. const innerHeight = (node) => {
  18. let height = node.clientHeight;
  19. const computedStyle = node.ownerDocument.defaultView.getComputedStyle(node);
  20. height -= int(computedStyle.paddingTop);
  21. height -= int(computedStyle.paddingBottom);
  22. return height;
  23. }
  24. const outerHeight = (node) => {
  25. let height = node.clientHeight;
  26. const computedStyle = node.ownerDocument.defaultView.getComputedStyle(node);
  27. height += int(computedStyle.borderTopWidth);
  28. height += int(computedStyle.borderBottomWidth);
  29. return height;
  30. }
  31. class Drager extends React.Component {
  32. constructor(...props) {
  33. super(...props)
  34. this.move = this.move.bind(this)
  35. this.ondragend = this.ondragend.bind(this)
  36. }
  37. static propTypes = {
  38. bounds: PropTypes.string
  39. }
  40. state = {
  41. x: null,
  42. y: null,
  43. originX: 0,
  44. elX: 0,
  45. originY: 0,
  46. elY: 0
  47. }
  48. componentDidMount() {
  49. }
  50. move(some) {
  51. let { elX, elY } = this.state
  52. /* some.client - this.state.origin 表示的是移动的距离,
  53. * elX表示的是原来已经有的位移
  54. */
  55. let deltaX = some.clientX - this.state.originX + elX
  56. let deltaY = some.clientY - this.state.originY + elY
  57. if (this.props.bounds === 'parent') {
  58. const bounds = {
  59. left: int(this.parent.style.paddingLeft) + int(this.self.style.marginLeft) - this.self.offsetLeft,
  60. top: int(this.parent.style.paddingTop) + int(this.self.style.marginTop) - this.self.offsetTop,
  61. right: this.parent.clientWidth - outerWidth(this.self) - this.self.offsetLeft +
  62. int(this.parent.style.paddingRight) - int(this.self.style.marginRight),
  63. bottom: innerHeight(this.parent) - outerHeight(this.self) - this.self.offsetTop +
  64. int(this.parent.style.paddingBottom) - int(this.self.style.marginBottom)
  65. }
  66. console.log(bounds.right)
  67. deltaX = Math.min(deltaX, bounds.right)
  68. deltaY = Math.min(deltaY, bounds.bottom)
  69. deltaX = Math.max(deltaX, bounds.left)
  70. deltaY = Math.max(deltaY, bounds.top)
  71. }
  72. this.setState({
  73. x: deltaX,
  74. y: deltaY
  75. })
  76. }
  77. ondrag(some) {
  78. document.addEventListener('mousemove', this.move)
  79. document.addEventListener('mouseup', this.ondragend)
  80. if (this.props.bounds === 'parent' && typeof this.parent === 'undefined') {
  81. /**
  82. * 在这里我们将父节点缓存下来,保证当用户鼠标离开拖拽区域时,我们仍然能获取到父节点
  83. * what we do here is
  84. * making sure that we still can retrieve our parent when user's mouse left this node.
  85. */
  86. this.parent = some.target.offsetParent
  87. /**
  88. * 我们自己
  89. * ourself
  90. */
  91. this.self = some.target
  92. }
  93. this.setState({
  94. originX: some.clientX,
  95. originY: some.clientY,
  96. elX: this.state.x,
  97. elY: this.state.y
  98. })
  99. }
  100. ondragend(some) {
  101. console.log('脱离了')
  102. document.removeEventListener('mousemove', this.move)
  103. document.removeEventListener('mouseup', this.ondragend)
  104. }
  105. render() {
  106. const { x, y } = this.state
  107. return (
  108. <div className='shit'
  109. style={{ userSelect: 'none', margin: 10, touchAction: 'none', border: '2px solid black', padding: 10, transform: `translate(${x}px,${y}px)` }}
  110. onMouseDown={this.ondrag.bind(this)}
  111. onMouseUp={this.ondragend.bind(this)}
  112. >
  113. {React.cloneElement(React.Children.only(this.props.children), {})}
  114. </div>
  115. )
  116. }
  117. }
  118. export default class tmpFather extends React.Component {
  119. render() {
  120. return (
  121. <div
  122. className='shitWrap'
  123. style={{ left: 100, height: 300, width: 300, border: '1px solid black', position: 'absolute' }}
  124. ref={(node) => this.node = node}
  125. >
  126. <Drager
  127. bounds='parent'
  128. >
  129. <div>
  130. <p>asdasdad</p>
  131. <p>asdasdad</p>
  132. </div>
  133. </Drager>
  134. </div>
  135. )
  136. }
  137. }