gridItem.tsx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. import * as React from "react";
  2. import { Dragger } from './dragger/index'
  3. import { checkInContainer } from './util/correction';
  4. import { Bound } from './utils';
  5. export interface GridItemProps {
  6. /**外部容器属性 */
  7. col: number,
  8. containerWidth: number,
  9. containerPadding: [number, number],
  10. /**子元素的属性 */
  11. margin?: [number, number],
  12. GridX: number,
  13. GridY: number,
  14. rowHeight: number,
  15. /**子元素的宽高 */
  16. w: number,
  17. h: number,
  18. /**生命周期回掉函数 */
  19. onDragStart?: (event: GridItemEvent) => void,
  20. onDragEnd?: (event: GridItemEvent) => void,
  21. onDrag?: (event: GridItemEvent) => void
  22. onResizeStart?: (event: GridItemEvent) => void
  23. onResizing?: (event: GridItemEvent) => void
  24. onResizeEnd?: (event: GridItemEvent) => void
  25. isUserMove: Boolean
  26. UniqueKey?: string | number
  27. static?: Boolean
  28. style?: React.CSSProperties
  29. bounds?: Bound | 'parent'
  30. dragType: 'drag' | 'resize'
  31. handle?: Boolean
  32. canDrag?: Boolean
  33. canResize?: Boolean
  34. }
  35. export interface GridItemEvent {
  36. event: any
  37. GridX: number
  38. GridY: number
  39. w: number
  40. h: number
  41. UniqueKey: string | number
  42. }
  43. const checkWidthHeight = (GridX: number, w: number, h: number, col: number) => {
  44. var newW = w;
  45. var newH = h;
  46. if (GridX + w > col - 1) newW = col - GridX //右边界
  47. if (w < 1) newW = 1;
  48. if (h < 1) newH = 1;
  49. return {
  50. w: newW, h: newH
  51. }
  52. }
  53. export default class GridItem extends React.Component<GridItemProps, {}> {
  54. constructor(props: GridItemProps) {
  55. super(props)
  56. this.onDrag = this.onDrag.bind(this)
  57. this.onDragStart = this.onDragStart.bind(this)
  58. this.onDragEnd = this.onDragEnd.bind(this)
  59. this.calGridXY = this.calGridXY.bind(this)
  60. this.calColWidth = this.calColWidth.bind(this)
  61. }
  62. static defaultProps = {
  63. col: 12,
  64. containerWidth: 500,
  65. containerPadding: [0, 0],
  66. margin: [10, 10],
  67. rowHeight: 30,
  68. w: 1,
  69. h: 1
  70. }
  71. /** 计算容器的每一个格子多大 */
  72. calColWidth() {
  73. const { containerWidth, col, containerPadding, margin } = this.props;
  74. if (margin) {
  75. return (containerWidth - containerPadding[0] * 2 - margin[0] * (col + 1)) / col
  76. }
  77. return (containerWidth - containerPadding[0] * 2 - 0 * (col + 1)) / col
  78. }
  79. /**转化,计算网格的GridX,GridY值 */
  80. calGridXY(x: number, y: number) {
  81. const { margin, containerWidth, col, w, rowHeight } = this.props
  82. /**坐标转换成格子的时候,无须计算margin */
  83. let GridX = Math.round(x / containerWidth * col)
  84. let GridY = Math.round(y / (rowHeight + (margin ? margin[1] : 0)))
  85. // /**防止元素出container */
  86. return checkInContainer(GridX, GridY, col, w)
  87. }
  88. /**给予一个grid的位置,算出元素具体的在容器中位置在哪里,单位是px */
  89. calGridItemPosition(GridX: number, GridY: number) {
  90. var { margin, rowHeight } = this.props
  91. if (!margin) margin = [0, 0];
  92. let x = Math.round(GridX * this.calColWidth() + (GridX + 1) * margin[0])
  93. let y = Math.round(GridY * rowHeight + margin[1] * (GridY + 1))
  94. return {
  95. x: x,
  96. y: y
  97. }
  98. }
  99. shouldComponentUpdate(props: GridItemProps, state: any) {
  100. return this.props.GridX !== props.GridX ||
  101. this.props.GridY !== props.GridY ||
  102. this.props.isUserMove !== props.isUserMove ||
  103. this.props.w !== props.w ||
  104. this.props.h !== props.h
  105. }
  106. /**宽和高计算成为px */
  107. calWHtoPx(w: number, h: number) {
  108. var { margin } = this.props
  109. if (!margin) margin = [0, 0];
  110. const wPx = Math.round(w * this.calColWidth() + (w - 1) * margin[0])
  111. const hPx = Math.round(h * this.props.rowHeight + (h - 1) * margin[1])
  112. return { wPx, hPx }
  113. }
  114. calPxToWH(wPx: number, hPx: number) {
  115. const calWidth = this.calColWidth();
  116. const w = Math.round((wPx - calWidth * 0.5) / calWidth)
  117. const h = Math.round((hPx - this.props.rowHeight * 0.5) / this.props.rowHeight)
  118. return checkWidthHeight(this.props.GridX, w, h, this.props.col)
  119. }
  120. onDragStart(x: number, y: number) {
  121. const { w, h, UniqueKey } = this.props;
  122. if (this.props.static) return;
  123. const { GridX, GridY } = this.calGridXY(x, y)
  124. this.props.onDragStart && this.props.onDragStart({
  125. event, GridX, GridY, w, h, UniqueKey: UniqueKey + ''
  126. })
  127. }
  128. onDrag(event: any, x: number, y: number) {
  129. if (this.props.static) return;
  130. const { GridX, GridY } = this.calGridXY(x, y)
  131. const { w, h, UniqueKey } = this.props
  132. this.props.onDrag && this.props.onDrag({ GridX, GridY, w, h, UniqueKey: UniqueKey + '', event })
  133. }
  134. onDragEnd(event: any, x: number, y: number) {
  135. if (this.props.static) return;
  136. const { GridX, GridY } = this.calGridXY(x, y);
  137. const { w, h, UniqueKey } = this.props;
  138. if (this.props.onDragEnd) this.props.onDragEnd({ GridX, GridY, w, h, UniqueKey: UniqueKey + '', event });
  139. }
  140. onResizeStart = (event: any, wPx: number, hPx: number) => {
  141. const { GridX, GridY, UniqueKey, w, h } = this.props;
  142. this.props.onResizeStart && this.props.onResizeStart({ GridX, GridY, w, h, UniqueKey: UniqueKey + '', event })
  143. }
  144. onResizing = (event: any, wPx: number, hPx: number) => {
  145. var { w, h } = this.calPxToWH(wPx, hPx);
  146. const { GridX, GridY, UniqueKey } = this.props;
  147. this.props.onResizing && this.props.onResizing({ GridX, GridY, w, h, UniqueKey: UniqueKey + '', event })
  148. }
  149. onResizeEnd = (event: any, wPx: number, hPx: number) => {
  150. var { w, h } = this.calPxToWH(wPx, hPx);
  151. const { GridX, GridY, UniqueKey } = this.props;
  152. this.props.onResizeEnd && this.props.onResizeEnd({ GridX, GridY, w, h, UniqueKey: UniqueKey + '', event })
  153. }
  154. render() {
  155. const { w, h, style, bounds, GridX, GridY, handle, canDrag, canResize } = this.props
  156. const { x, y } = this.calGridItemPosition(GridX, GridY)
  157. const { wPx, hPx } = this.calWHtoPx(w, h);
  158. return (
  159. <Dragger
  160. style={{
  161. ...style,
  162. width: wPx,
  163. height: hPx,
  164. position: 'absolute',
  165. transition: this.props.isUserMove ? '' : 'all .2s ease-out',
  166. zIndex: this.props.isUserMove ? (this.props.dragType === 'drag' ? 10 : 2) : 2
  167. }}
  168. onDragStart={this.onDragStart}
  169. onMove={this.onDrag}
  170. onDragEnd={this.onDragEnd}
  171. onResizeStart={this.onResizeStart}
  172. onResizing={this.onResizing}
  173. onResizeEnd={this.onResizeEnd}
  174. x={x}
  175. y={y}
  176. w={wPx}
  177. h={hPx}
  178. isUserMove={this.props.isUserMove}
  179. bounds={bounds}
  180. handle={handle}
  181. canDrag={canDrag}
  182. canResize={canResize}
  183. >
  184. <div style={{ height: '100%', width: "100%" }}>
  185. {React.Children.map(this.props.children, (child) => child)}
  186. </div>
  187. </Dragger>
  188. )
  189. }
  190. }