GridItem.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import React from 'react'
  2. import PropTypes from 'prop-types'
  3. import Dragger from './Dragger'
  4. export const checkInContainer = (GridX, GridY, col, w) => {
  5. /**防止元素出container */
  6. if (GridX + w > col - 1) GridX = col - w //右边界
  7. if (GridX < 0) GridX = 0//左边界
  8. if (GridY < 0) GridY = 0//上边界
  9. return { GridX, GridY }
  10. }
  11. export default class GridItem extends React.Component {
  12. constructor(props) {
  13. super(props)
  14. this.onDrag = this.onDrag.bind(this)
  15. this.onDragStart = this.onDragStart.bind(this)
  16. this.onDragEnd = this.onDragEnd.bind(this)
  17. this.calGridXY = this.calGridXY.bind(this)
  18. this.calColWidth = this.calColWidth.bind(this)
  19. }
  20. static propTypes = {
  21. /**外部容器属性 */
  22. col: PropTypes.number,
  23. containerWidth: PropTypes.number,
  24. containerPadding: PropTypes.array,
  25. /**子元素的属性 */
  26. margin: PropTypes.array,
  27. GridX: PropTypes.number,
  28. GridY: PropTypes.number,
  29. rowHeight: PropTypes.number,
  30. /**子元素的宽高 */
  31. w: PropTypes.number,
  32. h: PropTypes.number,
  33. /**生命周期回掉函数 */
  34. onDragStart: PropTypes.func,
  35. onDragEnd: PropTypes.func
  36. }
  37. static defaultProps = {
  38. col: 12,
  39. containerWidth: 500,
  40. containerPadding: [0, 0],
  41. margin: [10, 10],
  42. rowHeight: 30,
  43. w: 1,
  44. h: 1
  45. }
  46. /** 计算容器的每一个格子多大 */
  47. calColWidth() {
  48. const { containerWidth, col, containerPadding, margin } = this.props;
  49. return (containerWidth - containerPadding[0] * 2 - margin[0] * (col + 1)) / col
  50. }
  51. /**转化,计算网格的GridX,GridY值 */
  52. calGridXY(x, y) {
  53. const { margin, containerWidth, col, w } = this.props
  54. /**坐标转换成格子的时候,无须计算margin */
  55. let GridX = Math.round(x / containerWidth * col)
  56. let GridY = Math.round(y / (this.props.rowHeight + margin[1]))
  57. // /**防止元素出container */
  58. return checkInContainer(GridX, GridY, col, w)
  59. }
  60. /**给予一个grid的位置,算出元素具体的在容器中位置在哪里,单位是px */
  61. calGridItemPosition(GridX, GridY) {
  62. const { w, margin, col, containerWidth } = this.props
  63. let x = Math.round(GridX * this.calColWidth() + (GridX + 1) * margin[0])
  64. let y = Math.round(GridY * this.props.rowHeight + margin[1] * (GridY + 1))
  65. return {
  66. x: x,
  67. y: y
  68. }
  69. }
  70. shouldComponentUpdate(props, state) {
  71. return this.props.GridX !== props.GridX ||
  72. this.props.GridY !== props.GridY||
  73. this.props.isUserMove !== props.isUserMove
  74. }
  75. /**宽和高计算成为px */
  76. calWHtoPx(w, h) {
  77. const { margin, containerPadding, containerWidth, col } = this.props
  78. const wPx = Math.round(w * this.calColWidth() + (w - 1) * margin[0])
  79. const hPx = Math.round(h * this.props.rowHeight + (h - 1) * margin[1])
  80. return { wPx, hPx }
  81. }
  82. onDragStart(x, y) {
  83. const { w, h, UniqueKey } = this.props;
  84. if (this.props.static) return;
  85. const { GridX, GridY } = this.calGridXY(x, y)
  86. this.props.onDragStart({
  87. event, GridX, GridY, w, h, UniqueKey
  88. })
  89. }
  90. onDrag(event, x, y) {
  91. if (this.props.static) return;
  92. const { GridX, GridY } = this.calGridXY(x, y)
  93. const { w, h, col, UniqueKey } = this.props
  94. this.props.onDrag({ GridX, GridY, w, h }, UniqueKey)
  95. }
  96. onDragEnd() {
  97. if (this.props.static) return;
  98. if (this.props.onDragEnd) this.props.onDragEnd(this.props.UniqueKey)
  99. }
  100. render() {
  101. const { w, h, margin, style, bounds, GridX, GridY } = this.props
  102. const { x, y } = this.calGridItemPosition(this.props.GridX, this.props.GridY)
  103. const { wPx, hPx } = this.calWHtoPx(w, h);
  104. return (
  105. <Dragger
  106. style={{
  107. ...style, width: wPx, height: hPx, position: 'absolute',
  108. transition: this.props.isUserMove ? '' : 'all .2s'
  109. }}
  110. onDragStart={this.onDragStart}
  111. onMove={this.onDrag}
  112. onDragEnd={this.onDragEnd}
  113. x={x}
  114. y={y}
  115. isUserMove={this.props.isUserMove}
  116. >
  117. <div style={{ width: wPx, height: hPx }}>
  118. {React.Children.map(this.props.children, (child) => child)}
  119. </div>
  120. </Dragger>
  121. )
  122. }
  123. }