dragact.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. import * as React from "react";
  2. import GridItem, { GridItemEvent } from './GridItem'
  3. import { compactLayout } from './util/compact';
  4. import { getMaxContainerHeight } from './util/sort';
  5. import { layoutCheck } from './util/collison';
  6. import { correctLayout } from './util/correction';
  7. import { stringJoin } from './utils';
  8. import { layoutItemForkey, syncLayout } from './util/initiate';
  9. import { DragactProps, DragactState, DragactLayoutItem } from "./dragact-type";
  10. import './style.css';
  11. export class Dragact extends React.Component<DragactProps, DragactState> {
  12. constructor(props: DragactProps) {
  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. const layout = props.layout;
  18. this.state = {
  19. GridXMoving: 0,
  20. GridYMoving: 0,
  21. wMoving: 0,
  22. hMoving: 0,
  23. placeholderShow: false,
  24. placeholderMoving: false,
  25. layout: layout,
  26. containerHeight: 500,
  27. dragType: 'drag',
  28. mapLayout: undefined
  29. }
  30. }
  31. onResizeStart = (layoutItem: GridItemEvent) => {
  32. const { GridX, GridY, w, h } = layoutItem
  33. if (this.state.mapLayout) {
  34. const newlayout = syncLayout(this.state.mapLayout, layoutItem)
  35. this.setState({
  36. GridXMoving: GridX,
  37. GridYMoving: GridY,
  38. wMoving: w,
  39. hMoving: h,
  40. placeholderShow: true,
  41. placeholderMoving: true,
  42. mapLayout: newlayout,
  43. dragType: 'resize'
  44. })
  45. }
  46. this.props.onDragStart && this.props.onDragStart(layoutItem);
  47. }
  48. onResizing = (layoutItem: GridItemEvent) => {
  49. const newLayout = layoutCheck(this.state.layout, layoutItem, layoutItem.UniqueKey + '', layoutItem.UniqueKey + '', 0);
  50. const { compacted, mapLayout } = compactLayout(newLayout, layoutItem, this.state.mapLayout)
  51. this.setState({
  52. layout: compacted,
  53. wMoving: layoutItem.w,
  54. hMoving: layoutItem.h,
  55. mapLayout: mapLayout,
  56. containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1], this.state.containerHeight)
  57. })
  58. }
  59. onResizeEnd = (layoutItem: GridItemEvent) => {
  60. const { compacted, mapLayout } = compactLayout(this.state.layout, undefined, this.state.mapLayout)
  61. this.setState({
  62. placeholderShow: false,
  63. layout: compacted,
  64. mapLayout: mapLayout,
  65. containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1], this.state.containerHeight)
  66. })
  67. this.props.onDragEnd && this.props.onDragEnd(layoutItem);
  68. }
  69. onDragStart(bundles: GridItemEvent) {
  70. const { GridX, GridY, w, h } = bundles
  71. if (this.state.mapLayout) {
  72. this.setState({
  73. GridXMoving: GridX,
  74. GridYMoving: GridY,
  75. wMoving: w,
  76. hMoving: h,
  77. placeholderShow: true,
  78. placeholderMoving: true,
  79. mapLayout: syncLayout(this.state.mapLayout, bundles),
  80. dragType: 'drag'
  81. })
  82. }
  83. this.props.onDragStart && this.props.onDragStart(bundles);
  84. }
  85. onDrag(layoutItem: GridItemEvent) {
  86. const { GridY, UniqueKey } = layoutItem;
  87. const moving = GridY - this.state.GridYMoving;
  88. const newLayout = layoutCheck(this.state.layout, layoutItem, UniqueKey + '', UniqueKey + ''/*用户移动方块的key */, moving);
  89. const { compacted, mapLayout } = compactLayout(newLayout, layoutItem, this.state.mapLayout);
  90. this.setState({
  91. GridXMoving: layoutItem.GridX,
  92. GridYMoving: layoutItem.GridY,
  93. layout: compacted,
  94. mapLayout: mapLayout,
  95. containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1], this.state.containerHeight)
  96. })
  97. this.props.onDrag && this.props.onDrag(layoutItem);
  98. }
  99. onDragEnd(layoutItem: GridItemEvent) {
  100. const { compacted, mapLayout } = compactLayout(this.state.layout, undefined, this.state.mapLayout)
  101. this.setState({
  102. placeholderShow: false,
  103. layout: compacted,
  104. mapLayout: mapLayout,
  105. containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1], this.state.containerHeight)
  106. })
  107. this.props.onDragEnd && this.props.onDragEnd(layoutItem);
  108. }
  109. renderPlaceholder() {
  110. if (!this.state.placeholderShow) return null
  111. var { col, padding, rowHeight, margin, placeholder, width } = this.props
  112. const { GridXMoving, GridYMoving, wMoving, hMoving, placeholderMoving, dragType } = this.state
  113. if (!placeholder) return null;
  114. if (!padding) padding = 0;
  115. return (
  116. <GridItem
  117. margin={margin}
  118. col={col}
  119. containerWidth={width}
  120. containerPadding={[padding, padding]}
  121. rowHeight={rowHeight}
  122. GridX={GridXMoving}
  123. GridY={GridYMoving}
  124. w={wMoving}
  125. h={hMoving}
  126. style={{ background: 'rgba(15,15,15,0.3)', zIndex: dragType === 'drag' ? 1 : 10, transition: ' all .15s ease-out' }}
  127. isUserMove={!placeholderMoving}
  128. dragType={dragType}
  129. canDrag={false}
  130. canResize={false}
  131. >
  132. {(p: any, resizerProps: any) => <div {...p} />}
  133. </GridItem>
  134. )
  135. }
  136. componentWillReceiveProps(nextProps: any) {
  137. if (this.props.layout.length > nextProps.layout.length) { //remove
  138. const mapLayoutCopy = { ...this.state.mapLayout };
  139. nextProps.layout.forEach((child: any) => {
  140. if ((mapLayoutCopy as any)[child.key + ''] !== void 666) delete (mapLayoutCopy as any)[child.key + ''];
  141. })
  142. for (const key in mapLayoutCopy) {
  143. const newLayout = this.state.layout.filter((child) => {
  144. if (child.key + '' !== key + '') return child
  145. })
  146. const { compacted, mapLayout } = compactLayout(newLayout, undefined, this.state.mapLayout);
  147. this.setState({
  148. containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1], this.state.containerHeight),
  149. layout: compacted,
  150. mapLayout
  151. })
  152. }
  153. } else if (this.props.layout.length < nextProps.layout.length) {//add
  154. var item;
  155. for (const idx in nextProps.layout) {
  156. const i = nextProps.layout[idx];
  157. if (this.state.mapLayout && !this.state.mapLayout[i.key + '']) {
  158. item = i;
  159. break;
  160. }
  161. }
  162. if (item !== void 666) {
  163. const dataSet = { ...item, isUserMove: false, key: item.key + '' };
  164. var newLayout = [...this.state.layout, dataSet]
  165. const { compacted, mapLayout } = compactLayout(newLayout, undefined, this.state.mapLayout);
  166. this.setState({
  167. containerHeight: getMaxContainerHeight(compacted,
  168. this.props.rowHeight,
  169. this.props.margin[1],
  170. this.state.containerHeight,
  171. false),
  172. layout: compacted,
  173. mapLayout
  174. })
  175. }
  176. } else {
  177. this.recalculateLayout(nextProps.layout, nextProps.col);
  178. }
  179. }
  180. recalculateLayout = (layout: DragactLayoutItem[], col: number) => {
  181. const corrected = correctLayout(layout, col)
  182. const { compacted, mapLayout } = compactLayout(corrected, undefined, undefined);
  183. this.setState({
  184. layout: compacted,
  185. mapLayout: mapLayout,
  186. containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1], this.state.containerHeight, false)
  187. })
  188. }
  189. componentDidMount() {
  190. setTimeout(() => {
  191. this.recalculateLayout(this.state.layout, this.props.col)
  192. }, 1);
  193. }
  194. getGridItem(child: any, index: number) {
  195. const { dragType, mapLayout } = this.state;
  196. var { col, padding, rowHeight, margin, width } = this.props;
  197. if (mapLayout) {
  198. const renderItem = layoutItemForkey(mapLayout, child.key + '');
  199. if (!padding) padding = 0;
  200. return (
  201. <GridItem
  202. {...renderItem}
  203. margin={margin}
  204. col={col}
  205. containerWidth={width}
  206. containerPadding={[padding, padding]}
  207. rowHeight={rowHeight}
  208. onDrag={this.onDrag}
  209. onDragStart={this.onDragStart}
  210. onDragEnd={this.onDragEnd}
  211. isUserMove={renderItem.isUserMove !== void 666 ? renderItem.isUserMove : false}
  212. UniqueKey={child.key}
  213. onResizing={this.onResizing}
  214. onResizeStart={this.onResizeStart}
  215. onResizeEnd={this.onResizeEnd}
  216. dragType={dragType}
  217. key={child.key}
  218. >
  219. {(GridItemProvided, dragHandle, resizeHandle) => this.props.children(child, {
  220. isDragging: renderItem.isUserMove !== void 666 ? renderItem.isUserMove : false,
  221. props: GridItemProvided,
  222. dragHandle,
  223. resizeHandle
  224. })}
  225. </GridItem >
  226. )
  227. }
  228. }
  229. render() {
  230. const {
  231. className,
  232. layout,
  233. style,
  234. width
  235. } = this.props;
  236. const { containerHeight } = this.state;
  237. return (
  238. <div
  239. className={stringJoin('DraggerLayout', className + '')}
  240. style={{
  241. ...style,
  242. left: 100,
  243. width: width,
  244. height: containerHeight,
  245. zIndex: 1
  246. }}
  247. >
  248. {layout.map((item, index) => {
  249. return this.getGridItem(item, index)
  250. })}
  251. {this.renderPlaceholder()}
  252. </div>
  253. )
  254. }
  255. //api
  256. getLayout() {
  257. return this.state.layout;
  258. }
  259. //api
  260. deleteItem(key: any) {
  261. }
  262. }