Z F 7 лет назад
Родитель
Сommit
8c083cf442

+ 33 - 87
src/SortableList/index.tsx

@@ -1,106 +1,52 @@
 import * as React from 'react';
-import { DragactList } from '../lib/dragactList';
-import { Dnd } from '../lib/dragger/dragapi';
-// import { GridItemEvent } from '../lib/GridItem';
-
-// const Words = [
-//     { content: 'You can do anything, but not everything.', img: 'http://pic.sc.chinaz.com/files/pic/pic9/201303/xpic10472.jpg' },
-//     { content: 'Those who dare to fail miserably can achieve greatly.', img: 'https://img00.deviantart.net/1163/i/2013/059/d/7/irish_views_by_ssquared_photography-d5wjnsk.jpg' },
-//     { content: 'You miss 100 percent of the shots you never take.', img: 'http://www.landsendhotel.co.uk/uploads/gallery/gallery/coastal_scenery_seascapes_6.jpg' },
-//     { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-//     { content: 'I’d rather live with a good question than a bad answer.', img: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQVa26cLzh6PYUwY4LMpwbHyDHFmWi_w2JuqDzeOdm1IIEbBZO0Vg' }
-// ]
-
-
-// const Cell = (props: any) => {
-//     const item = props.item;
-//     return (
-//         <div className='layout-Cell'>
-//             <img src={item.img} style={{ width: 45, height: 45 }} draggable={false} alt='card'></img>
-//             <div style={{ paddingLeft: 12, color: '#595959' }}>{item.content}</div>
-//         </div>
-//     )
-// }
-
-
-
-// const checkIn = (point: any, rect: ClientRect) => {
-//     const { clientX, clientY } = point;
-//     var In = false;
-//     if (clientX <= rect.left + rect.width && clientX > rect.left) {
-//         if (clientY <= rect.top + rect.height && clientY > rect.top) {
-//             // console.log(point);
-//             In = true;
-//         }
-//     }
-
-
-//     In ? console.log('进来') : ''
-
-// }
-
-// export class SortableList extends React.Component<{}, {}> {
-//     one: DragactList | null;
-//     two: DragactList | null;
-
-
-//     onDrag = (e: GridItemEvent) => {
+import { DragactList } from '../lib/dragactList/dragactList';
+
+
+const Words = [
+    { content: 'You can do anything, but not everything.', img: 'http://pic.sc.chinaz.com/files/pic/pic9/201303/xpic10472.jpg' },
+    { content: 'Those who dare to fail miserably can achieve greatly.', img: 'https://img00.deviantart.net/1163/i/2013/059/d/7/irish_views_by_ssquared_photography-d5wjnsk.jpg' },
+    { content: 'You miss 100 percent of the shots you never take.', img: 'http://www.landsendhotel.co.uk/uploads/gallery/gallery/coastal_scenery_seascapes_6.jpg' },
+    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
+    { content: 'I’d rather live with a good question than a bad answer.', img: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQVa26cLzh6PYUwY4LMpwbHyDHFmWi_w2JuqDzeOdm1IIEbBZO0Vg' }
+]
+
+
+const Cell = (props: any) => {
+    const item = props.item;
+    return (
+        <div className='layout-Cell' style={{ width: 400, height: 50 }}>
+            <img src={item.img} style={{ width: 45, height: 45 }} draggable={false} alt='card'></img>
+            <div style={{ paddingLeft: 12, color: '#595959' }}>{item.content}</div>
+        </div>
+    )
+}
 
-//         const ref = this.one && this.one.getReact();
-//         if (ref) {
-//             checkIn({ clientX: e.event.clientX, clientY: e.event.clientY }, ref)
-//         }
 
-//     }
 
-//     render() {
-//         return (
-//             <div style={{ display: 'flex', justifyContent: 'center' }}>
-//                 <div style={{ display: 'flex', justifyContent: 'space-between' }}>
-//                     <h1 style={{ textAlign: 'center' }}>Sorted Table Demo</h1>
-//                     <DragactList width={400} rowHeight={60} margin={[2, 2]} onDrag={this.onDrag} className='normal-layout' ref={node => this.one = node}>
-//                         {Words.map((el, index) => {
-//                             return <Cell item={el} key={index} data-set={{ GridX: 0, GridY: 0, w: 1, h: 1, canResize: false }} />
-//                         })}
-//                     </DragactList>
-//                     <DragactList width={400} rowHeight={60} margin={[2, 2]} className='normal-layout' ref={node => this.two = node}>
-//                         {Words.map((el, index) => {
-//                             return <Cell item={el} key={index} data-set={{ GridX: 0, GridY: 0, w: 1, h: 1, canResize: false }} />
-//                         })}
-//                     </DragactList>
-//                 </div>
-//             </div>
-//         )
-//     }
 
-// }
 
 export class SortableList extends React.Component<{}, {}> {
     one: DragactList | null;
     two: DragactList | null;
-    state = {
-        hidden: 100
-    }
 
-    onDrag = (e: any) => {
-        console.log(e.nativeEvent)
-        this.setState({
-            hidden: 70
-        })
-    }
-    onDragEnd = () => {
-        this.setState({
-            hidden: 100
-        })
-    }
 
     render() {
         return (
             <div style={{ display: 'flex', justifyContent: 'center' }}>
-                <Dnd><div>asdasd</div></Dnd>
-
+                <div>
+                    <h1 style={{ textAlign: 'center' }}>Sorted Table Demo</h1>
+                    <DragactList width={400} rowHeight={60} margin={[50, 5]} className='normal-layout' ref={node => this.one = node}>
+                        {Words.map((el, index) => {
+                            return <Cell item={el} key={index} data-set={{ y: index }} />
+                        })}
+                        {Words.map((el, index) => {
+                            return <Cell item={el} key={index + 100} data-set={{ y: index }} />
+                        })}
+                    </DragactList>
+                </div>
             </div>
         )
     }
+
 }
 

+ 0 - 369
src/lib/dragactList.tsx

@@ -1,369 +0,0 @@
-import * as React from "react";
-import GridItem, { GridItemEvent } from './GridItem'
-import { compactLayout } from './util/compact';
-import { getMaxContainerHeight } from './util/sort';
-import { layoutCheck } from './util/collison';
-import { correctLayout } from './util/correction';
-import { getDataSet, stringJoin } from './utils';
-import { layoutItemForkey, syncLayout } from './util/initiate';
-
-import './style.css';
-
-
-export interface DragactLayoutItem {
-    GridX: number
-    GridY: number
-    static?: Boolean
-    w: number
-    h: number
-    isUserMove?: Boolean
-    key?: number | string
-    handle?: Boolean
-    canDrag?: Boolean
-    canResize?: Boolean
-}
-
-export interface DragactProps {
-    /** 
-     * 容器的宽度
-    */
-    width: number,
-
-    /**容器内每个元素的最小高度 */
-    rowHeight: number,
-    /**
-     * 容器内部的padding
-     */
-    padding?: number,
-
-    children: any[] | any
-
-
-    // 
-    // interface GridItemEvent {
-    //     event: any //浏览器拖动事件
-    //     GridX: number //在布局中的x格子  
-    //     GridY: number //在布局中的y格子  
-    //     w: number //元素的宽度
-    //     h: number //元素的高度
-    //     UniqueKey: string | number //元素的唯一key
-    // }
-
-    /**
-     * 拖动开始的回调
-     */
-    onDragStart?: (event: GridItemEvent) => void
-
-    /**
-     * 拖动中的回调
-     */
-    onDrag?: (event: GridItemEvent) => void
-
-    /**
-     * 拖动结束的回调
-     */
-    onDragEnd?: (event: GridItemEvent) => void
-
-    /**
-     * 每个元素的margin,第一个参数是左右,第二个参数是上下
-     */
-    margin: [number, number]
-
-    /** 
-     * layout的名字
-    */
-    className: number | string
-}
-
-export interface mapLayout {
-    [key: string]: DragactLayoutItem
-}
-
-interface DragactState {
-    GridXMoving: number
-    GridYMoving: number
-    wMoving: number
-    hMoving: number
-    placeholderShow: Boolean
-    placeholderMoving: Boolean
-    layout: DragactLayoutItem[]
-    containerHeight: number
-    dragType: 'drag' | 'resize'
-    mapLayout: mapLayout | undefined
-    col: number
-
-}
-
-export class DragactList extends React.Component<DragactProps, DragactState> {
-    dragact: HTMLDivElement | null
-
-    constructor(props: DragactProps) {
-        super(props)
-        this.onDrag = this.onDrag.bind(this)
-        this.onDragStart = this.onDragStart.bind(this)
-        this.onDragEnd = this.onDragEnd.bind(this)
-
-
-        const layout = getDataSet(props.children);
-
-        this.state = {
-            GridXMoving: 0,
-            GridYMoving: 0,
-            wMoving: 0,
-            hMoving: 0,
-            placeholderShow: false,
-            placeholderMoving: false,
-            layout: layout,
-            containerHeight: 500,
-            dragType: 'drag',
-            mapLayout: undefined,
-            col: 1
-        }
-    }
-    onResizeStart = (layoutItem: GridItemEvent) => {
-        const { GridX, GridY, w, h } = layoutItem
-        const sync = syncLayout(this.state.layout, layoutItem);
-        this.setState({
-            GridXMoving: GridX,
-            GridYMoving: GridY,
-            wMoving: w,
-            hMoving: h,
-            placeholderShow: true,
-            placeholderMoving: true,
-            layout: sync,
-            dragType: 'resize'
-        })
-    }
-
-    onResizing = (layoutItem: GridItemEvent) => {
-
-        const newLayout = layoutCheck(this.state.layout, layoutItem, layoutItem.UniqueKey, layoutItem.UniqueKey, 0);
-
-        const { compacted, mapLayout } = compactLayout(newLayout, layoutItem)
-
-        this.setState({
-            layout: compacted,
-            wMoving: layoutItem.w,
-            hMoving: layoutItem.h,
-            mapLayout: mapLayout,
-            containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1])
-        })
-    }
-
-    onResizeEnd = (layoutItem: GridItemEvent) => {
-        const { compacted, mapLayout } = compactLayout(this.state.layout, undefined)
-        this.setState({
-            placeholderShow: false,
-            layout: compacted,
-            mapLayout: mapLayout,
-            containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1])
-        })
-        this.props.onDragEnd && this.props.onDragEnd(layoutItem);
-    }
-
-    onDragStart(bundles: GridItemEvent) {
-        const { GridX, GridY, w, h } = bundles
-
-        const newlayout = syncLayout(this.state.layout, bundles)
-
-        this.setState({
-            GridXMoving: GridX,
-            GridYMoving: GridY,
-            wMoving: w,
-            hMoving: h,
-            placeholderShow: true,
-            placeholderMoving: true,
-            layout: newlayout,
-            dragType: 'drag'
-        })
-        this.props.onDragStart && this.props.onDragStart(bundles)
-    }
-
-    onDrag(layoutItem: GridItemEvent) {
-        const { GridY, UniqueKey } = layoutItem
-        const moving = GridY - this.state.GridYMoving
-
-        const newLayout = layoutCheck(this.state.layout, layoutItem, UniqueKey, UniqueKey/*用户移动方块的key */, moving)
-        const { compacted, mapLayout } = compactLayout(newLayout, layoutItem)
-
-        this.setState({
-            GridXMoving: layoutItem.GridX,
-            GridYMoving: layoutItem.GridY,
-            layout: compacted,
-            mapLayout: mapLayout,
-            containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1])
-        })
-        this.props.onDrag && this.props.onDrag(layoutItem);
-    }
-
-    onDragEnd(layoutItem: GridItemEvent) {
-
-        const { compacted, mapLayout } = compactLayout(this.state.layout, undefined)
-
-        this.setState({
-            placeholderShow: false,
-            layout: compacted,
-            mapLayout: mapLayout,
-            containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1])
-        })
-
-        this.props.onDragEnd && this.props.onDragEnd(layoutItem);
-    }
-    renderPlaceholder() {
-        if (!this.state.placeholderShow) return null
-        var { width, padding, rowHeight, margin } = this.props
-        const { GridXMoving, GridYMoving, wMoving, hMoving, placeholderMoving, dragType, col } = this.state
-
-        if (!padding) padding = 0;
-        return (
-            <GridItem
-                margin={margin}
-                col={col}
-                containerWidth={width}
-                containerPadding={[padding, padding]}
-                rowHeight={rowHeight}
-                GridX={GridXMoving}
-                GridY={GridYMoving}
-                w={wMoving}
-                h={hMoving}
-                style={{ background: 'rgba(15,15,15,0.3)', zIndex: dragType === 'drag' ? 1 : 10, transition: ' all .15s' }}
-                isUserMove={!placeholderMoving}
-                dragType={dragType}
-                canDrag={false}
-                canResize={false}
-            />
-        )
-    }
-
-    componentWillReceiveProps(nextProps: any) {
-        if (this.props.children.length > nextProps.children.length) { //remove
-            const mapLayoutCopy = { ...this.state.mapLayout };
-            nextProps.children.forEach((child: any) => {
-                if ((mapLayoutCopy as any)[child.key] !== void 666) delete (mapLayoutCopy as any)[child.key];
-            })
-            for (const key in mapLayoutCopy) {
-                const newLayout = this.state.layout.filter((child) => {
-                    if (child.key !== key) return child
-                })
-                const { compacted, mapLayout } = compactLayout(newLayout, undefined);
-                this.setState({
-                    containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1]),
-                    layout: compacted,
-                    mapLayout
-                })
-            }
-        }
-
-        if (this.props.children.length < nextProps.children.length) { //add
-            var item;
-            for (const idx in nextProps.children) {
-                const i = nextProps.children[idx];
-                if (this.state.mapLayout && !this.state.mapLayout[i.key]) {
-                    item = i;
-                    break;
-                }
-            }
-            if (item !== void 666) {
-                const dataSet = { ...item.props['data-set'], isUserMove: false, key: item.key };
-                var newLayout = [...this.state.layout, dataSet]
-                newLayout = correctLayout(newLayout, this.state.col)
-                const { compacted, mapLayout } = compactLayout(newLayout, undefined);
-                console.log(mapLayout)
-                // console.log(layout)
-                this.setState({
-                    containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1]),
-                    layout: compacted,
-                    mapLayout
-                })
-            }
-        }
-
-    }
-
-
-    componentDidMount() {
-
-        setTimeout(() => {
-            let layout = correctLayout(this.state.layout, this.state.col)
-            const { compacted, mapLayout } = compactLayout(layout, undefined);
-            this.setState({
-                layout: compacted,
-                mapLayout: mapLayout,
-                containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1])
-            })
-        }, 1);
-    }
-
-    getGridItem(child: any, index: number) {
-        const { dragType, mapLayout, col } = this.state
-        var { width, padding, rowHeight, margin } = this.props;
-        if (mapLayout) {
-            const renderItem = layoutItemForkey(mapLayout, child.key);
-            if (!padding) padding = 0;
-            return (
-                <GridItem
-                    margin={margin}
-                    col={col}
-                    containerWidth={width}
-                    containerPadding={[padding, padding]}
-                    rowHeight={rowHeight}
-                    GridX={renderItem.GridX}
-                    GridY={renderItem.GridY}
-                    w={renderItem.w}
-                    h={renderItem.h}
-                    onDrag={this.onDrag}
-                    onDragStart={this.onDragStart}
-                    onDragEnd={this.onDragEnd}
-                    isUserMove={renderItem.isUserMove !== void 666 ? renderItem.isUserMove : false}
-                    UniqueKey={child.key}
-                    static={renderItem.static}
-                    onResizing={this.onResizing}
-                    onResizeStart={this.onResizeStart}
-                    onResizeEnd={this.onResizeEnd}
-                    dragType={dragType}
-                    handle={renderItem.handle}
-                    canDrag={renderItem.canDrag}
-                    canResize={renderItem.canResize}
-                >
-                    {child}
-                </GridItem >
-            )
-        }
-    }
-
-    render() {
-        const { width, className } = this.props;
-        const { containerHeight } = this.state;
-
-        return (
-            <div
-                className={stringJoin('DraggerLayout', className + '')}
-                style={{ left: 100, width: width, height: containerHeight, zIndex: 1 }}
-                ref={node => this.dragact = node}
-            >
-                {React.Children.map(this.props.children,
-                    (child, index) => this.getGridItem(child, index)
-                )}
-                {this.renderPlaceholder()}
-            </div>
-        )
-    }
-
-    //api
-    getLayout() {
-        return this.state.layout;
-    }
-
-    getReact = () => {
-        if (this.dragact) {
-            return this.dragact.getClientRects()[0];
-        }
-    }
-
-    //api
-    deleteItem(key: any) {
-
-
-
-    }
-}

+ 485 - 0
src/lib/dragactList/dragactList.tsx

@@ -0,0 +1,485 @@
+import * as React from "react";
+import { GridItemEvent } from '../GridItem'
+// import { compactLayout } from '../util/compact';
+// import { getMaxContainerHeight } from '../util/sort';
+// import { layoutCheck } from '../util/collison';
+
+import { stringJoin } from '../utils';
+// import { syncLayout } from '../util/initiate';
+
+import './index.css';
+import { Dragger } from "../dragger/index";
+
+
+export interface DragactLayoutItem {
+    GridX: number
+    GridY: number
+    static?: Boolean
+    w: number
+    h: number
+    isUserMove?: Boolean
+    key?: number | string
+    handle?: Boolean
+    canDrag?: Boolean
+    canResize?: Boolean
+}
+
+export interface DragactProps {
+    /** 
+     * 容器的宽度
+    */
+    width: number,
+
+    /**容器内每个元素的最小高度 */
+    rowHeight: number,
+    /**
+     * 容器内部的padding
+     */
+    padding?: number,
+
+    children: any[] | any
+
+
+    // 
+    // interface GridItemEvent {
+    //     event: any //浏览器拖动事件
+    //     GridX: number //在布局中的x格子  
+    //     GridY: number //在布局中的y格子  
+    //     w: number //元素的宽度
+    //     h: number //元素的高度
+    //     UniqueKey: string | number //元素的唯一key
+    // }
+
+    /**
+     * 拖动开始的回调
+     */
+    onDragStart?: (event: GridItemEvent) => void
+
+    /**
+     * 拖动中的回调
+     */
+    onDrag?: (event: GridItemEvent) => void
+
+    /**
+     * 拖动结束的回调
+     */
+    onDragEnd?: (event: GridItemEvent) => void
+
+    /**
+     * 每个元素的margin,第一个参数是左右,第二个参数是上下
+     */
+    margin: [number, number]
+
+    /** 
+     * layout的名字
+    */
+    className: number | string
+}
+
+export interface mapLayout {
+    [key: string]: DragactLayoutItem
+}
+
+interface DragactState {
+    GridXMoving: number
+    GridYMoving: number
+    wMoving: number
+    hMoving: number
+    placeholderShow: Boolean
+    placeholderMoving: Boolean
+    layout: any;
+    containerHeight: number
+    dragType: 'drag' | 'resize'
+    mapLayout: mapLayout | undefined
+    col: number
+
+}
+
+
+export class Column extends React.Component<{}, {}>{
+
+
+    render() {
+        return this.props.children
+    }
+}
+
+interface ListItemEvent {
+    key: any,
+    x: number,
+    y: number
+}
+
+interface ListCellProps {
+    x: number
+    y: number
+    isUserMove: Boolean
+    style: React.CSSProperties
+    onDragStart: (e: ListItemEvent) => void
+    onDrag: (e: ListItemEvent) => void
+    onDragEnd: (e: ListItemEvent) => void
+    margin: [number, number]
+    rowHeight: number
+    width: number
+    col: number
+    UniqueKey: number
+}
+
+const checkInContainer = (GridX: number, GridY: number) => {
+
+    /**防止元素出container */
+    // if (GridY < 0) GridY = 0//上边界
+    return { GridX, GridY }
+}
+
+
+export class ListCell extends React.Component<ListCellProps, {}>{
+
+    calGridXY(x: number, y: number) {
+        const { margin, width, col, rowHeight } = this.props
+        const containerWidth = width * col + margin[0];
+
+        /**坐标转换成格子的时候,无须计算margin */
+        let GridX = Math.round(x / containerWidth * col)
+        let GridY = Math.round(y / (rowHeight + (margin ? margin[1] : 0)))
+
+        // /**防止元素出container */
+        return checkInContainer(GridX, GridY)
+    }
+
+    onDragStart = (x: number, y: number) => {
+        const { GridX, GridY } = this.calGridXY(x, y);
+        const { UniqueKey } = this.props;
+
+        this.props.onDragStart({ key: UniqueKey, x: GridX, y: GridY });
+    }
+    onDrag = (event: any, x: number, y: number) => {
+        const { GridX, GridY } = this.calGridXY(x, y);
+        const { UniqueKey } = this.props;
+
+        this.props.onDrag({ key: UniqueKey, x: GridX, y: GridY });
+    }
+
+    onDragEnd = (event: any, x: number, y: number) => {
+        const { GridX, GridY } = this.calGridXY(x, y);
+        const { UniqueKey } = this.props;
+        this.props.onDragEnd({ key: UniqueKey, x: GridX, y: GridY });
+    }
+
+
+    render() {
+        const { x, y, isUserMove, width, style, rowHeight } = this.props;
+
+        return (
+            <Dragger
+                x={x * width}
+                y={y * rowHeight}
+                style={{ ...style, width: width, transition: this.props.isUserMove ? '' : 'all .2s', }}
+                isUserMove={isUserMove}
+                onDragStart={this.onDragStart}
+                onMove={this.onDrag}
+                canResize={false}
+                onDragEnd={this.onDragEnd}
+            >
+                {this.props.children}
+            </Dragger>
+        )
+    }
+
+}
+
+export const collision = (a: number, b: number) => {
+    if (a + 1 === b) {
+        return 1
+    }
+    if (a + 1 <= b) return -1
+    if (a >= b + 1) return -1
+    return 2
+}
+
+
+const swapList = (list: any, movingItem: any, firstKey: any) => {
+    var moving: any = [];
+    var newList = list.map((oldItem: any) => {
+        if (oldItem.key !== movingItem.key) {
+            const num = collision(oldItem.y, movingItem.y)
+            if (num > 0) {
+                console.log('痛', oldItem.y, movingItem.y)
+                var offset = movingItem.y - 1
+                if (oldItem.y < movingItem.y) {
+                    offset = movingItem.y + 2
+                }
+                // if (oldItem.y == movingItem.y) {
+                //     offset = oldItem.y
+                // }
+                moving.push({ ...oldItem, y: offset })
+
+                return { ...oldItem, y: offset }
+            }
+            return { ...oldItem }
+        } else if (oldItem.key === firstKey) {
+
+            /**永远保持用户移动的块是 isUserMove === true */
+            return { ...oldItem, ...movingItem }
+        }
+        return { ...oldItem }
+    })
+
+
+    for (const i in moving) {
+
+        newList = swapList(newList, moving[i], firstKey);
+    }
+    return newList;
+}
+
+/**获取layout中,item第一个碰撞到的物体 */
+export const getFirstCollison = (layout: any, item: any) => {
+    for (let i = 0, length = layout.length; i < length; i++) {
+        if (collision(layout[i].y, item.y) > 0) {
+            return layout[i]
+        }
+    }
+    return null
+}
+
+const compactCell = (partialList: any, cell: any) => {
+
+
+    if (partialList.length === 0) {
+        return { ...cell, y: 0 }
+    }
+    var newCell = { ...cell };
+    /**
+     * 类似一个递归调用
+     */
+    while (true) {
+
+        let FirstCollison = getFirstCollison(partialList, newCell)
+        if (FirstCollison) {
+
+            /**第一次发生碰撞时,就可以返回了 */
+            return { ...newCell, y: FirstCollison.y + 1 }
+        }
+        newCell.y--
+
+        if (newCell.y < 0) return { ...newCell, y: 0 }/**碰到边界的时候,返回 */
+    }
+
+}
+
+
+export const compactList = (list: any, movingItem: any) => {
+    const sort = list.sort((a: any, b: any) => {
+        if (a.y > b.y) return 1
+        return 0
+    })
+    // console.log('sor',sort)
+    console.log(sort)
+    const needCompact = Array(list.length)
+    const after: any = [];
+    for (const i in sort) {
+        const finished = compactCell(after, sort[i]);
+
+        if (movingItem) {
+            if (movingItem.key === finished.key) {
+                finished.y = movingItem.y;
+                finished.isUserMove = true
+            } else
+                finished.isUserMove = false
+        }
+        else
+            finished.isUserMove = false
+
+        after.push(finished);
+        needCompact[(i as any)] = finished;
+    }
+
+
+    return needCompact;
+}
+
+
+export class DragactList extends React.Component<DragactProps, DragactState> {
+    dragact: HTMLDivElement | null
+
+    constructor(props: DragactProps) {
+        super(props)
+        // const layout = getDataSet(props.children);
+
+
+        const layout = props.children.map((child: any) => {
+            return child.map((el: any) => {
+                return { ...el.props['data-set'], key: el.key, isUserMove: false };
+            })
+        })
+        // console.log(layout)
+        // console.log(layout);
+
+        this.state = {
+            GridXMoving: 0,
+            GridYMoving: 0,
+            wMoving: 0,
+            hMoving: 0,
+            placeholderShow: false,
+            placeholderMoving: false,
+            layout: layout,
+            containerHeight: 500,
+            dragType: 'drag',
+            mapLayout: undefined,
+            col: 3
+        }
+    }
+
+    componentWillReceiveProps(nextProps: any) {
+        // if (this.props.children.length > nextProps.children.length) { //remove
+        //     const mapLayoutCopy = { ...this.state.mapLayout };
+        //     nextProps.children.forEach((child: any) => {
+        //         if ((mapLayoutCopy as any)[child.key] !== void 666) delete (mapLayoutCopy as any)[child.key];
+        //     })
+        //     for (const key in mapLayoutCopy) {
+        //         const newLayout = this.state.layout.filter((child) => {
+        //             if (child.key !== key) return child
+        //         })
+        //         const { compacted, mapLayout } = compactLayout(newLayout, undefined);
+        //         this.setState({
+        //             containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1]),
+        //             layout: compacted,
+        //             mapLayout
+        //         })
+        //     }
+        // }
+
+        // if (this.props.children.length < nextProps.children.length) { //add
+        //     var item;
+        //     for (const idx in nextProps.children) {
+        //         const i = nextProps.children[idx];
+        //         if (this.state.mapLayout && !this.state.mapLayout[i.key]) {
+        //             item = i;
+        //             break;
+        //         }
+        //     }
+        //     if (item !== void 666) {
+        //         const dataSet = { ...item.props['data-set'], isUserMove: false, key: item.key };
+        //         var newLayout = [...this.state.layout, dataSet]
+        //         newLayout = correctLayout(newLayout, this.state.col)
+        //         const { compacted, mapLayout } = compactLayout(newLayout, undefined);
+        //         console.log(mapLayout)
+        //         // console.log(layout)
+        //         this.setState({
+        //             containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1]),
+        //             layout: compacted,
+        //             mapLayout
+        //         })
+        //     }
+        // }
+
+    }
+
+
+    componentDidMount() {
+
+        // setTimeout(() => {
+        //     let layout = correctLayout(this.state.layout, this.state.col)
+        //     const { compacted, mapLayout } = compactLayout(layout, undefined);
+        //     this.setState({
+        //         layout: compacted,
+        //         mapLayout: mapLayout,
+        //         containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1])
+        //     })
+        // }, 1);
+    }
+
+
+    onDragStart = (e: ListItemEvent) => {
+        const { key, x } = e;
+
+
+        for (const idx in this.state.layout[x]) {
+            if (this.state.layout[x][idx].key === key) {
+
+                this.state.layout[x][idx].isUserMove = true;
+                break;
+            }
+        }
+        this.setState({
+            layout: this.state.layout
+        })
+        console.log(this.state.layout)
+    }
+
+    onDrag = (e: ListItemEvent) => {
+        const { key, x, y } = e;
+
+        console.log(y)
+        const newList = swapList(this.state.layout[x], { y, key }, key)
+        // const compacted = compactList(newList, { y, key });
+        this.state.layout[x] = newList;
+        // console.log(compacted);
+        this.setState({
+            layout: [...this.state.layout]
+        })
+
+    }
+
+    onDragEnd = (e: ListItemEvent) => {
+        const { x } = e;
+        const compacted = compactList(this.state.layout[x], undefined);
+        this.state.layout[x] = compacted;
+        console.log(compacted);
+        this.setState({
+            layout: [...this.state.layout]
+        })
+    }
+
+    renderList = () => {
+        return this.props.children.map((child: any, index: number) => <div className='list-oneof' key={index}>{this.renderColumn(child, index)}</div>)
+    }
+    renderColumn = (child: any, index: number) => {
+        // const column = this.state.layout[index];
+
+        const { width, margin, rowHeight } = this.props;
+
+        return child.map((c: any, idx: any) => {
+            const key = c.key;
+            var renderItem: any;
+            for (const i in this.state.layout[index]) {
+                if (this.state.layout[index][i].key === key) {
+                    renderItem = this.state.layout[index][i];
+                }
+            }
+
+            return <ListCell
+                margin={margin}
+                rowHeight={rowHeight}
+                width={width}
+                col={this.props.children.length}
+                x={index}
+                y={renderItem.y}
+                style={{ position: 'absolute' }}
+                key={idx}
+                UniqueKey={key}
+                isUserMove={renderItem.isUserMove}
+                onDragStart={this.onDragStart}
+                onDrag={this.onDrag}
+                onDragEnd={this.onDragEnd}
+            >
+                {c}
+            </ListCell>
+        })
+    }
+
+    render() {
+        const { width, className, children } = this.props;
+        const numberOfCol = children.length;
+
+        return (
+            <div
+                className={stringJoin('DraggerLayout', className + '')}
+                style={{ left: 100, width: width * numberOfCol, height: '', zIndex: 1 }}
+            >
+                {this.renderList()}
+            </div>
+        )
+    }
+}

+ 19 - 0
src/lib/dragactList/index.css

@@ -0,0 +1,19 @@
+/* .shit:hover{
+    width: 100px;
+    height: 100px;
+} */
+
+.WrapDragger {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.DraggerLayout {
+    -webkit-transition: all .15s;
+    transition: all .15s;
+}
+
+body {
+    background: white;
+}

+ 0 - 348
src/lib/dragger/dragapi.tsx

@@ -1,348 +0,0 @@
-import * as React from "react";
-import { int, innerHeight, innerWidth, outerHeight, outerWidth, parseBounds, Bound } from '../utils'
-
-
-const doc = document
-
-
-
-interface DraggerProps {
-
-    className?: string;
-
-    /**
-    * 给予元素一个x,y的初始位置,单位是px
-    */
-    x?: number,
-    y?: number,
-
-    /** 
-     * 拖动范围限制
-     * 如果不规定范围,那么子元素就可以随意拖动不受限制
-     * 1.可以提供自定义的范围限制
-     * 2.也可以提供父类为边框的范围限制(string === parent)
-     */
-    bounds?: Bound | 'parent',
-
-    /**
-         * 以网格的方式移动,每次移动并不是平滑的移动
-         * [20,30],鼠标x轴方向移动了20 px ,y方向移动了30 px,整个子元素才会移动
-         */
-    grid?: [number, number],
-
-
-    /**只允许移动x轴 */
-    /**只允许移动y轴 */
-    allowX?: Boolean,
-    allowY?: Boolean,
-
-
-    /**
-    * 是否由用户移动
-    * 可能是通过外部props改变
-    */
-    isUserMove?: Boolean,
-
-    /**
-     * 生命周期回调
-     */
-    onDragStart?: (x: number, y: number) => void,
-    onMove?: (event: MouseEvent | TouchEvent, x: number, y: number) => void,
-    onDragEnd?: (event: MouseEvent | TouchEvent, x: number, y: number) => void,
-
-    onResizeStart?: (event: any, x: number, y: number) => void,
-    onResizing?: (event: MouseEvent | TouchEvent, x: number, y: number) => void
-    onResizeEnd?: (event: MouseEvent | TouchEvent, x: number, y: number) => void
-
-    style?: React.CSSProperties,
-
-    w?: number,
-    h?: number,
-
-    handle?: Boolean;
-
-    canDrag?: Boolean;
-
-    canResize?: Boolean;
-}
-
-export class Dnd extends React.Component<DraggerProps, {}> {
-    parent: any;
-    self: any;
-
-    constructor(props: DraggerProps) {
-        super(props)
-        // this.move = this.move.bind(this)
-        // this.onDragEnd = this.onDragEnd.bind(this)
-        this.parent = null;
-        this.self = null;
-    }
-    /**
-     * 初始变量设置
-     */
-    static defaultProps = {
-        allowX: true,
-        allowY: true,
-        isUserMove: true
-    }
-
-    state = {
-        /** x轴位移,单位是px */
-        x: 0,
-
-        /** y轴位移,单位是px */
-        y: 0,
-
-        /**鼠标点击元素的原始位置,单位是px */
-        originX: 0,
-        originY: 0,
-
-        isUserMove: true,
-
-        /**已经移动的位移,单位是px */
-        lastX: 0,
-        lastY: 0,
-
-        /**堆叠的层级 */
-        zIndex: 1,
-
-        w: 0,
-        h: 0,
-
-        lastW: 0,
-        lastH: 0
-    }
-
-
-
-    move = (event: any) => {
-
-        let { lastX, lastY } = this.state
-        /*  event.client - this.state.origin 表示的是移动的距离,
-        *   elX表示的是原来已经有的位移
-        */
-
-
-        let deltaX, deltaY;
-        deltaX = event.clientX - this.state.originX + lastX
-        deltaY = event.clientY - this.state.originY + lastY
-
-        const { bounds } = this.props
-        if (bounds) {
-            /**
-            * 如果用户指定一个边界,那么在这里处理
-            */
-            let NewBounds = typeof bounds !== 'string' ? parseBounds(bounds) : bounds;
-
-            /**
-             * 网格式移动范围设定,永远移动 n 的倍数
-             * 注意:设定移动范围的时候,一定要在判断bounds之前,否则会造成bounds不对齐
-             */
-            const { grid } = this.props
-            if (Array.isArray(grid) && grid.length === 2) {
-                deltaX = Math.round(deltaX / grid[0]) * grid[0]
-                deltaY = Math.round(deltaY / grid[1]) * grid[1]
-            }
-
-            if (this.props.bounds === 'parent') {
-                NewBounds = {
-                    left: int(this.parent.style.paddingLeft) + int(this.self.style.marginLeft) - this.self.offsetLeft,
-                    top: int(this.parent.style.paddingTop) + int(this.self.style.marginTop) - this.self.offsetTop,
-                    right: innerWidth(this.parent) - outerWidth(this.self) - this.self.offsetLeft +
-                        int(this.parent.style.paddingRight) - int(this.self.style.marginRight),
-                    bottom: innerHeight(this.parent) - outerHeight(this.self) - this.self.offsetTop +
-                        int(this.parent.style.paddingBottom) - int(this.self.style.marginBottom)
-                }
-            }
-
-            /**
-             * 保证不超出右边界和底部
-             * keep element right and bot can not cross the bounds
-             */
-            if (NewBounds !== 'parent') deltaX = Math.min(deltaX, NewBounds.right)
-            if (NewBounds !== 'parent') deltaY = Math.min(deltaY, NewBounds.bottom)
-
-
-            /**
-             * 保证不超出左边和上边
-             * keep element left and top can not cross the bounds
-             */
-            if (NewBounds !== 'parent') deltaX = Math.max(deltaX, NewBounds.left)
-            if (NewBounds !== 'parent') deltaY = Math.max(deltaY, NewBounds.top)
-        }
-
-
-        /**如果设置了x,y限制 */
-        deltaX = this.props.allowX ? deltaX : 0
-        deltaY = this.props.allowY ? deltaY : 0
-
-        /**移动时回调,用于外部控制 */
-        if (this.props.onMove) this.props.onMove(event, deltaX, deltaY)
-
-
-        console.log(deltaX, deltaY)
-        this.setState({
-            x: deltaX,
-            y: deltaY
-        })
-    }
-
-    onDragStart = (event: any) => {
-        /** 保证用户在移动元素的时候不会选择到元素内部的东西 */
-        doc.body.style.userSelect = 'none'
-
-        if (this.props.handle) {
-            if (event.target.id !== 'dragact-handle') return
-        }
-
-        doc.addEventListener('mousemove', this.move);
-        doc.addEventListener('mouseup', this.onDragEnd);
-
-        // /**
-        //  * 把监听事件的回掉函数,绑定在document上
-        //  * 当设置边界的时候,用户鼠标会离开元素的范围
-        //  * 绑定在document上可以使得其依旧能够监听
-        //  * 如果绑定在元素上,则鼠标离开元素,就不会再被监听了
-        //  */
-        // if (event.type.indexOf('mouse') >= 0) {
-        //     doc.addEventListener('mousemove', this.move);
-        //     doc.addEventListener('mouseup', this.onDragEnd);
-        // } else {
-        //     doc.addEventListener('touchmove', this.move)
-        //     doc.addEventListener('touchend', this.onDragEnd)
-        // }
-
-        // if (this.props.bounds === 'parent' &&
-        //     /**为了让 这段代码不会重复执行 */
-        //     (typeof this.parent === 'undefined' || this.parent === null)) {
-        //     /**
-        //      * 在这里我们将父节点缓存下来,保证当用户鼠标离开拖拽区域时,我们仍然能获取到父节点
-        //      * what we do here is 
-        //      * making sure that we still can retrieve our parent when user's mouse left this node.
-        //      */
-
-        //     this.parent = (event as any).currentTarget.offsetParent //todo
-
-        //     /**
-        //      * 我们自己
-        //      * ourself
-        //      */
-        //     this.self = event.currentTarget
-        // }
-
-        // this.props.onDragStart && this.props.onDragStart(this.state.x, this.state.y)
-
-
-        let originX, originY;
-        originX = (event).nativeEvent.clientX
-        originY = (event).nativeEvent.clientY
-
-        this.setState({
-            originX: originX,
-            originY: originY,
-            lastX: this.state.x,
-            lastY: this.state.y,
-            zIndex: 10
-        })
-    }
-
-    onDragEnd = (event: any) => {
-        /** 取消用户选择限制,用户可以重新选择 */
-        doc.body.style.userSelect = ''
-        this.parent = null
-        this.self = null
-
-        this.setState({
-            zIndex: 1
-        })
-
-        this.props.onDragEnd && this.props.onDragEnd(event, this.state.x, this.state.y)
-    }
-
-
-    componentDidMount() {
-        /** 
-         * 这个函数只会调用一次 
-         * 这个只是一个临时的解决方案,因为这样会使得元素进行两次刷新
-        */
-        if (typeof this.props.x === 'number' &&
-            typeof this.props.y === 'number') {
-            this.setState({
-                x: this.props.x,
-                y: this.props.y
-            })
-        }
-    }
-
-    componentWillReceiveProps(nextProps: DraggerProps) {
-        /**
-         * 外部props 改变的时候更新元素的内部位置
-         * 这个api设计其实很不好
-         * 以后可能会修改掉
-         */
-        const { isUserMove } = nextProps
-        if (!isUserMove) {
-
-            if (typeof nextProps.x === 'number' &&
-                typeof nextProps.y === 'number') {
-                this.setState({
-                    x: nextProps.x,
-                    y: nextProps.y,
-                    lastX: nextProps.x,
-                    lastY: nextProps.y,
-                    w: nextProps.w,
-                    h: nextProps.h
-                })
-            }
-        }
-    }
-
-    mixin = () => {
-        var dragMix = {
-            onDragStart: this.onDragStart,
-        }
-
-        var resizeMix = {}
-
-        return {
-            dragMix, resizeMix
-        };
-    }
-
-    render() {
-        var { x, y } = this.state
-        var { style, className } = this.props
-        // if (!this.props.isUserMove) {
-        //     /**当外部设置其props的x,y初始属性的时候,我们在这里设置元素的初始位移 */
-        //     x = this.props.x ? this.props.x : 0;
-        //     y = this.props.y ? this.props.y : 0;
-        //     if (style) {
-        //         w = style.width ? style.width : w;
-        //         h = style.height ? style.height : h;
-        //     }
-        // }
-        // if (style) {
-        //     //使得初始化的时候,不会有从0-1缩放动画
-        //     w = w === 0 ? style.width : w;
-        //     h = h === 0 ? style.height : h;
-        // }
-        const { dragMix } = this.mixin();
-
-        // console.log(x,y)
-        /**主要是为了让用户定义自己的className去修改css */
-        const fixedClassName = typeof className === 'undefined' ? '' : className + ' '
-        return (
-            <div className={`${fixedClassName}WrapDragger`}
-                style={{
-                    ...style,
-                    position: 'absolute',
-                    transform: `translate(${x}px,${y}px)`,
-                }}
-                draggable={true}
-                {...dragMix}
-            >
-                {React.Children.only(this.props.children)}
-            </div>
-        )
-    }
-}

+ 1 - 0
src/lib/dragger/index.tsx

@@ -388,6 +388,7 @@ export class Dragger extends React.Component<DraggerProps, {}> {
     }
 
     render() {
+        
         var { x, y, w, h } = this.state
         var { style, className, canResize } = this.props
         if (!this.props.isUserMove) {

+ 0 - 1
src/lib/gridItem.tsx

@@ -202,7 +202,6 @@ export default class GridItem extends React.Component<GridItemProps, {}> {
         this.props.onResizeEnd && this.props.onResizeEnd({ GridX, GridY, w, h, UniqueKey: UniqueKey + '', event })
     }
     render() {
-
         const { w, h, style, bounds, GridX, GridY, handle, canDrag, canResize } = this.props
         const { x, y } = this.calGridItemPosition(GridX, GridY)
         const { wPx, hPx } = this.calWHtoPx(w, h);