方正 7 rokov pred
rodič
commit
17a57a05ed
3 zmenil súbory, kde vykonal 226 pridanie a 29 odobranie
  1. 110 12
      app/src/App.js
  2. 43 7
      app/src/Dragger.js
  3. 73 10
      app/src/GridItem.js

+ 110 - 12
app/src/App.js

@@ -4,44 +4,142 @@ import GridItem from './GridItem'
 
 import './style.css'
 
+
+const MapLayoutTostate = (layout) => {
+    console.log('进来了', layout)
+    return layout
+}
+
 class DraggerLayout extends React.Component {
+    constructor(props) {
+        super(props)
+        this.onDrag = this.onDrag.bind(this)
+        this.onDragStart = this.onDragStart.bind(this)
+        this.onDragEnd = this.onDragEnd.bind(this)
+    }
+
     static PropTypes = {
         /**外部属性 */
         layout: PropTypes.array,
         col: PropTypes.number,
         width: PropTypes.number,
+        /**每个元素的最小高度 */
         rowHeight: PropTypes.number,
         padding: PropTypes.number,
     }
 
+    state = {
+        GridXMoving: 0,
+        GridYMoving: 0,
+        wMoving: 0,
+        hMoving: 0,
+        placeholderShow: false,
+        placeholderMoving: false,
+        layout: MapLayoutTostate(this.props.layout)
+    }
+
+    onDragStart(bundles) {
+        const { GridX, GridY, w, h } = bundles
+        console.log(bundles)
+        this.setState({
+            GridXMoving: GridX,
+            GridYMoving: GridY,
+            wMoving: w,
+            hMoving: h,
+            placeholderShow: true,
+            placeholderMoving: true
+        })
+    }
+
+    onDrag(cor) {
+        this.setState({
+            GridXMoving: cor.GridX,
+            GridYMoving: cor.GridY,
+        })
+    }
+
+    onDragEnd() {
+        console.log(this.state)
+        this.setState({
+            placeholderShow: false
+        })
+    }
+    placeholder() {
+        if (!this.state.placeholderShow) return null
+        const { col, width, padding, rowHeight } = this.props
+        const { GridXMoving, GridYMoving, wMoving, hMoving, placeholderMoving } = this.state
+
+        return (
+            <GridItem
+                col={col}
+                containerWidth={width}
+                containerPadding={padding}
+                rowHeight={rowHeight}
+                GridX={GridXMoving}
+                GridY={GridYMoving}
+                w={wMoving}
+                h={hMoving}
+                style={{ background: '#a31' }}
+                isUserMove={!placeholderMoving}
+            >
+            </GridItem >
+        )
+    }
+    componentDidMount() {
+
+    }
+
+    getGridItem(child, index) {
+        const { layout } = this.state
+        const { col, width, padding, rowHeight } = this.props
+        return (
+            <GridItem
+                col={col}
+                containerWidth={width}
+                containerPadding={padding}
+                rowHeight={rowHeight}
+                GridX={layout[index].GridX}
+                GridY={layout[index].GridY}
+                w={layout[index].w}
+                h={layout[index].h}
+                onDrag={this.onDrag}
+                onDragStart={this.onDragStart}
+                onDragEnd={this.onDragEnd}
+            >
+                {child}
+            </GridItem >
+        )
+    }
 
     render() {
-        const { col, width } = this.props
+        const { layout, col, width, padding, rowHeight } = this.props
         return (
             <div
                 className='DraggerLayout'
                 style={{ position: 'absolute', left: 100, width: 500, height: 500, border: '1px solid black' }}
             >
                 {React.Children.map(this.props.children,
-                    (child) =>
-                        <GridItem
-                            col={col}
-                            containerWidth={width}
-                            containerPadding={padding}
-                        >
-                            {child}
-                        </GridItem >
+                    (child, index) => this.getGridItem(child, index)
                 )}
+                {this.placeholder()}
             </div>
         )
     }
 }
 
 export const LayoutDemo = () => {
+    const layout = [{
+        GridX: 3, GridY: 4, w: 3, h: 2
+    }, {
+        GridX: 1, GridY: 3, w: 3, h: 3
+    }, {
+        GridX: 2, GridY: 5, w: 3, h: 3
+    }]
     return (
-        <DraggerLayout>
-            <p>asdasd</p>
-            <p>asdasd</p>
+        <DraggerLayout layout={layout}>
+            <p>absolute</p>
+            <p>black</p>
+            <p>children</p>
         </DraggerLayout>
     )
 }

+ 43 - 7
app/src/Dragger.js

@@ -12,6 +12,12 @@ export default class Dragger extends React.Component {
     }
 
     static propTypes = {
+        /**
+         * 给予元素一个x,y的初始位置,单位是px
+         */
+        x: PropTypes.number,
+        y: PropTypes.number,
+
         /**
          * 拖动范围限制
          * 如果不规定范围,那么子元素就可以随意拖动不受限制
@@ -48,12 +54,18 @@ export default class Dragger extends React.Component {
          */
         hasDraggerHandle: PropTypes.bool,
 
+        /**
+         * 是否由用户移动
+         * 可能是系统移动
+         */
+        isUserMove: PropTypes.bool,
+
         /**
          * 生命周期回掉
          */
-        onDragStart:PropTypes.func,
-        onMove:PropTypes.func,
-        onDragEnd:PropTypes.func
+        onDragStart: PropTypes.func,
+        onMove: PropTypes.func,
+        onDragEnd: PropTypes.func
     }
     /** props end */
 
@@ -63,8 +75,9 @@ export default class Dragger extends React.Component {
     static defaultProps = {
         allowX: true,
         allowY: true,
-        hasDraggerHandle: false
-    };
+        hasDraggerHandle: false,
+        isUserMove: true
+    }
 
     state = {
         /** x轴位移,单位是px */
@@ -139,7 +152,7 @@ export default class Dragger extends React.Component {
         deltaY = this.props.allowY ? deltaY : 0
 
         /**移动时回掉 */
-        if(this.props.onMove)this.props.onMove(event,deltaX,deltaY)
+        if (this.props.onMove) this.props.onMove(event, deltaX, deltaY)
 
         this.setState({
             x: deltaX,
@@ -180,6 +193,8 @@ export default class Dragger extends React.Component {
             this.self = event.currentTarget
         }
 
+        this.props.onDragStart(this.state.x,this.state.y)
+
         this.setState({
             originX: event.clientX,
             originY: event.clientY,
@@ -196,12 +211,33 @@ export default class Dragger extends React.Component {
         doc.removeEventListener('mousemove', this.move)
         doc.removeEventListener('mouseup', this.onDragEnd)
 
+        this.props.onDragEnd()
+    }
+
+    componentDidMount() {
+        /** 
+         * 这个函数只会调用一次 
+         * 这个只是一个临时的解决方案,因为这样会使得元素进行两次刷新
+        */
+        if (typeof this.props.x === 'number' &&
+            typeof this.props.y === 'number') {
+            this.setState({
+                x: this.props.x,
+                y: this.props.y
+            })
+        }
     }
 
     render() {
-        const { x, y } = this.state
+        let { x, y } = this.state
         const { bounds, style, className, others } = this.props
 
+        if (!this.props.isUserMove) {
+            /**当外部设置其x,y初始属性的时候,我们在这里设置元素的初始位移 */
+            x = this.props.x
+            y = this.props.y
+        }
+
         /**主要是为了让用户定义自己的className去修改css */
         let fixedClassName = typeof className === 'undefined' ? '' : className + ' '
         return (

+ 73 - 10
app/src/GridItem.js

@@ -7,6 +7,8 @@ export default class GridItem extends Component {
     constructor(props) {
         super(props)
         this.onDrag = this.onDrag.bind(this)
+        this.onDragStart = this.onDragStart.bind(this)
+        this.onDragEnd = this.onDragEnd.bind(this)
         this.calGridXY = this.calGridXY.bind(this)
         this.calColWidth = this.calColWidth.bind(this)
     }
@@ -16,39 +18,100 @@ export default class GridItem extends Component {
         /**外部容器属性 */
         col: PropTypes.number,
         containerWidth: PropTypes.number,
-        containerPadding: PropTypes.number,
+        containerPadding: PropTypes.array,
 
         /**子元素的属性 */
-        margin: PropTypes.number,
+        margin: PropTypes.array,
+        GridX: PropTypes.number,
+        GridY: PropTypes.number,
+        rowHeight: PropTypes.number,
+
+        /**子元素的宽高 */
+        w: PropTypes.number,
+        h: PropTypes.number,
+
+        /**生命周期回掉函数 */
+        onDragStart: PropTypes.func,
+        onDragEnd: PropTypes.func
+
     }
 
     static defaultProps = {
         col: 12,
-        containerWidth: 500
+        containerWidth: 500,
+        containerPadding: [0, 0],
+        margin: [10, 10],
+        rowHeight: 30,
+        w: 100,
+        h: 100
     }
 
     /** 计算容器的每一个格子多大 */
     calColWidth() {
-        return this.props.containerWidth / this.props.col
+        const { containerWidth, col, containerPadding, margin } = this.props
+        return (containerWidth - containerPadding[0] * 2 - margin[0] * (col - 1)) / col
     }
 
     /**转化,计算网格的x,y值 */
     calGridXY(x, y) {
-        let GridX = Math.round(x / this.calColWidth())
-        let GridY = Math.round(y / this.calColWidth())
-        console.log(GridX, GridY)
+        const { margin } = this.props
+        let GridX = Math.round(x / (this.calColWidth() + margin[0]))
+        let GridY = Math.round(y / (this.props.rowHeight + margin[1]))
+        return { GridX, GridY }
+    }
+
+    /**给予一个grid的位置,算出元素具体的在容器中位置在哪里,单位是px */
+    calGridItemPosition(GridX, GridY) {
+        const { margin, col } = this.props
+        if (GridX > col - 1) GridX = col - 1
+        if (GridX < 0) GridX = 0
+
+        let x = Math.round(GridX * this.calColWidth() + margin[0] * GridX)
+        let y = Math.round(GridY * this.props.rowHeight + margin[1] * GridY)
+        return {
+            x: x,
+            y: y
+        }
     }
 
+    /**宽和高计算成为px */
+    calWHtoPx(w, h) {
+        const wPx = w * this.calColWidth()
+        const hPx = h * this.props.rowHeight
+
+        return { wPx, hPx }
+    }
+
+    onDragStart(x, y) {
+        console.log(x,y)
+        const { w, h } = this.props
+        const { GridX, GridY } = this.calGridXY(x, y)
+        this.props.onDragStart({
+            event, GridX, GridY, w, h
+        })
+    }
     onDrag(event, x, y) {
-        this.calGridXY(x, y)
+        const cor = this.calGridXY(x, y)
+        this.props.onDrag(cor)
+    }
+
+    onDragEnd() {
+        if (this.props.onDragEnd) this.props.onDragEnd()
     }
 
     render() {
+        const { x, y } = this.calGridItemPosition(this.props.GridX, this.props.GridY)
+        const { w, h, margin, style ,bounds } = this.props
+        const { wPx, hPx } = this.calWHtoPx(w, h)
         return (
             <Dragger
-                bounds='parent'
-                style={{ position: 'absolute', border: '1px solid black' }}
+                style={{ ...style, width: wPx, height: hPx, margin: margin[0], position: 'absolute', border: '1px solid black' }}
+                onDragStart={this.onDragStart}
                 onMove={this.onDrag}
+                onDragEnd={this.onDragEnd}
+                x={x}
+                y={y}
+                isUserMove={this.props.isUserMove}
             >
                 <div>
                     {React.Children.map(this.props.children, (child) => child)}