Browse Source

模块拆分

方正 7 năm trước cách đây
mục cha
commit
16731310a1

+ 7 - 252
app/src/App.js

@@ -1,257 +1,15 @@
 import React from 'react'
 import PropTypes from 'prop-types'
 import GridItem, { checkInContainer } from './GridItem'
+import { compactLayout, compactItem } from './util/compact';
+import { quickSort, 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'
+import './style.css';
 
-/**
- * 这个函数会有副作用,不是纯函数,会改变item的Gridx和GridY
- * @param {*} item 
- */
-const correctItem = (item, col) => {
-    const { GridX, GridY } = checkInContainer(item.GridX, item.GridY, col, item.w)
-    item.GridX = GridX;
-    item.GridY = GridY;
-}
-const correctLayout = (layout, col) => {
-    var copy = [...layout];
-    for (let i = 0; i < layout.length - 1; i++) {
-        correctItem(copy[i], col)
-        correctItem(copy[i + 1], col);
-
-        if (collision(copy[i], copy[i + 1])) {
-            copy = layoutCheck(copy, copy[i], copy[i].key, copy[i].key, undefined)
-        }
-    }
-
-    return copy;
-}
-
-/**
- * 用key从layout中拿出item
- * @param {*} layout 输入进来的布局
- * @param {*} key 
- */
-const layoutItemForkey = (layout, key) => {
-    for (let i = 0, length = layout.length; i < length; i++) {
-        if (key === layout[i].key) {
-            return layout[i]
-        }
-    }
-}
-
-/**
- * 初始化的时候调用
- * 会把isUserMove和key一起映射到layout中
- * 不用用户设置
- * @param {*} layout 
- * @param {*} children 
- */
-
-const MapLayoutTostate = (layout, children) => {
-    return layout.map((child, index) => {
-        let newChild = { ...child, isUserMove: true, key: children[index].key, static: children[index].static }
-        return newChild
-    })
-}
-
-/**
- * 把用户移动的块,标记为true
- * @param {*} layout 
- * @param {*} key 
- * @param {*} GridX 
- * @param {*} GridY 
- * @param {*} isUserMove 
- */
-const syncLayout = (layout, key, GridX, GridY, isUserMove) => {
-    const newlayout = layout.map((item) => {
-        if (item.key === key) {
-            item.GridX = GridX
-            item.GridY = GridY
-            item.isUserMove = isUserMove
-            return item
-        }
-        return item
-    })
-    return newlayout
-}
-
-const collision = (a, b) => {
-    if (a.GridX === b.GridX && a.GridY === b.GridY &&
-        a.w === b.w && a.h === b.h) {
-        return true
-    }
-    if (a.GridX + a.w <= b.GridX) return false
-    if (a.GridX >= b.GridX + b.w) return false
-    if (a.GridY + a.h <= b.GridY) return false
-    if (a.GridY >= b.GridY + b.h) return false
-    return true
-}
-
-const sortLayout = (layout) => {
-    return [].concat(layout).sort((a, b) => {
-        if (a.GridY > b.GridY || (a.GridY === b.GridY && a.GridX > b.GridX)) {
-            if (a.static) return 0//为了静态,排序的时候尽量把静态的放在前面
-            return 1
-        } else if (a.GridY === b.GridY && a.GridX === b.GridX) {
-            return 0
-        }
-        return -1
-    })
-}
-
-/**获取layout中,item第一个碰撞到的物体 */
-const getFirstCollison = (layout, item) => {
-    for (let i = 0, length = layout.length; i < length; i++) {
-        if (collision(layout[i], item)) {
-            return layout[i]
-        }
-    }
-    return null
-}
-
-
-/**
- * 压缩单个元素,使得每一个元素都会紧挨着边界或者相邻的元素
- * @param {*} finishedLayout 压缩完的元素会放进这里来,用来对比之后的每一个元素是否需要压缩
- * @param {*} item 
- */
-const compactItem = (finishedLayout, item) => {
-    if (item.static) return item;
-    const newItem = { ...item }
-    if (finishedLayout.length === 0) {
-        return { ...newItem, GridY: 0 }
-    }
-    /**
-     * 类似一个递归调用
-     */
-    while (true) {
-        let FirstCollison = getFirstCollison(finishedLayout, newItem)
-        if (FirstCollison) {
-            /**第一次发生碰撞时,就可以返回了 */
-            newItem.GridY = FirstCollison.GridY + FirstCollison.h
-            return newItem
-        }
-        newItem.GridY--
-
-        if (newItem.GridY < 0) return { ...newItem, GridY: 0 }/**碰到边界的时候,返回 */
-    }
-    return newItem
-}
-
-/**
- * 压缩layout,使得每一个元素都会紧挨着边界或者相邻的元素
- * @param {*} layout 
- */
-const compactLayout = (layout) => {
-    let sorted = sortLayout(layout)
-    const needCompact = Array(layout.length)
-    const compareList = []
-    for (let i = 0, length = sorted.length; i < length; i++) {
-        let finished = compactItem(compareList, sorted[i])
-        finished.isUserMove = false
-        compareList.push(finished)
-        needCompact[i] = finished
-    }
-    return needCompact
-}
-
-const layoutCheck = (layout, layoutItem, key, fristItemkey, moving) => {
-    let i = [], movedItem = []/**收集所有移动过的物体 */
-    let newlayout = layout.map((item, idx) => {
-
-        if (item.key !== key) {
-            if (item.static) {
-                return item
-            }
-            if (collision(item, layoutItem)) {
-                i.push(item.key)
-                /**
-                 * 这里就是奇迹发生的地方,如果向上移动,那么必须注意的是
-                 * 一格一格的移动,而不是一次性移动
-                 */
-                let offsetY = item.GridY + 1
-
-                /**这一行也非常关键,当向上移动的时候,碰撞的元素必须固定 */
-                // if (moving < 0 && layoutItem.GridY > 0) offsetY = item.GridY
-
-                if (layoutItem.GridY > item.GridY && layoutItem.GridY < item.GridY + item.h) {
-                    /**
-                     * 元素向上移动时,元素的上面空间不足,则不移动这个元素
-                     * 当元素移动到GridY>所要向上交换的元素时,就不会进入这里,直接交换元素
-                     */
-                    offsetY = item.GridY
-                }
-                /**
-                 * 物体向下移动的时候
-                 */
-
-                if (moving > 0) {
-                    if (layoutItem.GridY + layoutItem.h < item.GridY) {
-                        let collision;
-                        let copy = { ...item }
-                        while (true) {
-                            let newLayout = layout.filter((item) => {
-                                if (item.key !== key && (item.key !== copy.key)) {
-                                    return item
-                                }
-                            })
-                            collision = getFirstCollison(newLayout, copy)
-                            if (collision) {
-                                offsetY = collision.GridY + collision.h
-                                break
-                            } else {
-                                copy.GridY--
-                            }
-                            if (copy.GridY < 0) {
-                                offsetY = 0
-                                break
-                            }
-                        }
-                    }
-                }
-
-                movedItem.push({ ...item, GridY: offsetY, isUserMove: false })
-                return { ...item, GridY: offsetY, isUserMove: false }
-            }
-        } else if (fristItemkey === key) {
-
-            /**永远保持用户移动的块是 isUserMove === true */
-            return { ...item, GridX: layoutItem.GridX, GridY: layoutItem.GridY, isUserMove: true }
-        }
-
-        return item
-    })
-    /** 递归调用,将layout中的所有重叠元素全部移动 */
-    const length = movedItem.length;
-    for (let c = 0; c < length; c++) {
-        newlayout = layoutCheck(newlayout, movedItem[c], i[c], fristItemkey, undefined)
-    }
-    return newlayout
-}
-
-function quickSort(a) {
-    return a.length <= 1 ? a : quickSort(a.slice(1).filter(item => item <= a[0])).concat(a[0], quickSort(a.slice(1).filter(item => item > a[0])));
-}
-
-const getMaxContainerHeight = (layout, elementHeight = 30, elementMarginBottom = 10) => {
-    const ar = layout.map((item) => {
-        return item.GridY + item.h
-    })
-    const h = quickSort(ar)[ar.length - 1];
-    const height = h * (elementHeight + elementMarginBottom) + elementMarginBottom
-    return height
-}
-
-const getDataSet = (children) => {
-    return children.map((child) => {
-        return { ...child.props['data-set'], isUserMove: true, key: child.key, }
-    })
-}
-
-const stringJoin = (source, join) => {
-    return source + (join ? ` ${join}` : '')
-}
 
 export class DraggerLayout extends React.Component {
     constructor(props) {
@@ -288,9 +46,6 @@ export class DraggerLayout extends React.Component {
         padding: PropTypes.number,
     }
 
-
-
-
     onDragStart(bundles) {
         const { GridX, GridY, w, h, UniqueKey } = bundles
 

+ 0 - 2
app/src/Dragger.js

@@ -249,8 +249,6 @@ export default class Dragger extends React.Component {
         doc.removeEventListener('touchend', this.onDragEnd)
         doc.removeEventListener('mouseup', this.onDragEnd)
 
-        console.log('清除lsner')
-
         this.setState({
             zIndex: 1
         })

+ 3 - 11
app/src/GridItem.js

@@ -2,19 +2,11 @@ import React from 'react'
 
 import PropTypes from 'prop-types'
 import Dragger from './Dragger'
+import { checkInContainer } from './util/correction';
 
 
 
 
-export const checkInContainer = (GridX, GridY, col, w) => {
-    /**防止元素出container */
-    if (GridX + w > col - 1) GridX = col - w //右边界
-    if (GridX < 0) GridX = 0//左边界
-    if (GridY < 0) GridY = 0//上边界
-    return { GridX, GridY }
-}
-
-
 export default class GridItem extends React.Component {
     constructor(props) {
         super(props)
@@ -93,9 +85,9 @@ export default class GridItem extends React.Component {
 
 
     shouldComponentUpdate(props, state) {
-        
+
         return this.props.GridX !== props.GridX ||
-            this.props.GridY !== props.GridY||
+            this.props.GridY !== props.GridY ||
             this.props.isUserMove !== props.isUserMove
     }
 

+ 0 - 20
app/src/NormalLayout/index.js

@@ -6,26 +6,6 @@ const Words = [
     { 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: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' },
-    { 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' }
 ]
 

+ 97 - 0
app/src/util/collison.js

@@ -0,0 +1,97 @@
+export const collision = (a, b) => {
+    if (a.GridX === b.GridX && a.GridY === b.GridY &&
+        a.w === b.w && a.h === b.h) {
+        return true
+    }
+    if (a.GridX + a.w <= b.GridX) return false
+    if (a.GridX >= b.GridX + b.w) return false
+    if (a.GridY + a.h <= b.GridY) return false
+    if (a.GridY >= b.GridY + b.h) return false
+    return true
+}
+
+
+/**获取layout中,item第一个碰撞到的物体 */
+export const getFirstCollison = (layout, item) => {
+    for (let i = 0, length = layout.length; i < length; i++) {
+        if (collision(layout[i], item)) {
+            return layout[i]
+        }
+    }
+    return null
+}
+
+export const layoutCheck = (layout, layoutItem, key, fristItemkey, moving) => {
+    let i = [], movedItem = []/**收集所有移动过的物体 */
+    let newlayout = layout.map((item, idx) => {
+
+        if (item.key !== key) {
+            if (item.static) {
+                return item
+            }
+            if (collision(item, layoutItem)) {
+                i.push(item.key)
+                /**
+                 * 这里就是奇迹发生的地方,如果向上移动,那么必须注意的是
+                 * 一格一格的移动,而不是一次性移动
+                 */
+                let offsetY = item.GridY + 1
+
+                /**这一行也非常关键,当向上移动的时候,碰撞的元素必须固定 */
+                // if (moving < 0 && layoutItem.GridY > 0) offsetY = item.GridY
+
+                if (layoutItem.GridY > item.GridY && layoutItem.GridY < item.GridY + item.h) {
+                    /**
+                     * 元素向上移动时,元素的上面空间不足,则不移动这个元素
+                     * 当元素移动到GridY>所要向上交换的元素时,就不会进入这里,直接交换元素
+                     */
+                    offsetY = item.GridY
+                }
+                /**
+                 * 物体向下移动的时候
+                 */
+
+                if (moving > 0) {
+                    if (layoutItem.GridY + layoutItem.h < item.GridY) {
+                        let collision;
+                        let copy = { ...item }
+                        while (true) {
+                            let newLayout = layout.filter((item) => {
+                                if (item.key !== key && (item.key !== copy.key)) {
+                                    return item
+                                }
+                            })
+                            collision = getFirstCollison(newLayout, copy)
+                            if (collision) {
+                                offsetY = collision.GridY + collision.h
+                                break
+                            } else {
+                                copy.GridY--
+                            }
+                            if (copy.GridY < 0) {
+                                offsetY = 0
+                                break
+                            }
+                        }
+                    }
+                }
+
+                movedItem.push({ ...item, GridY: offsetY, isUserMove: false })
+                return { ...item, GridY: offsetY, isUserMove: false }
+            }
+        } else if (fristItemkey === key) {
+
+            /**永远保持用户移动的块是 isUserMove === true */
+            return { ...item, GridX: layoutItem.GridX, GridY: layoutItem.GridY, isUserMove: true }
+        }
+
+        return item
+    })
+    /** 递归调用,将layout中的所有重叠元素全部移动 */
+    const length = movedItem.length;
+    for (let c = 0; c < length; c++) {
+        newlayout = layoutCheck(newlayout, movedItem[c], i[c], fristItemkey, undefined)
+    }
+    return newlayout
+}
+

+ 47 - 0
app/src/util/compact.js

@@ -0,0 +1,47 @@
+import { sortLayout } from "./sort";
+import { getFirstCollison } from "./collison";
+
+/**
+ * 压缩单个元素,使得每一个元素都会紧挨着边界或者相邻的元素
+ * @param {*} finishedLayout 压缩完的元素会放进这里来,用来对比之后的每一个元素是否需要压缩
+ * @param {*} item 
+ */
+export const compactItem = (finishedLayout, item) => {
+    if (item.static) return item;
+    const newItem = { ...item }
+    if (finishedLayout.length === 0) {
+        return { ...newItem, GridY: 0 }
+    }
+    /**
+     * 类似一个递归调用
+     */
+    while (true) {
+        let FirstCollison = getFirstCollison(finishedLayout, newItem)
+        if (FirstCollison) {
+            /**第一次发生碰撞时,就可以返回了 */
+            newItem.GridY = FirstCollison.GridY + FirstCollison.h
+            return newItem
+        }
+        newItem.GridY--
+
+        if (newItem.GridY < 0) return { ...newItem, GridY: 0 }/**碰到边界的时候,返回 */
+    }
+    return newItem
+}
+
+/**
+ * 压缩layout,使得每一个元素都会紧挨着边界或者相邻的元素
+ * @param {*} layout 
+ */
+export const compactLayout = (layout) => {
+    let sorted = sortLayout(layout)
+    const needCompact = Array(layout.length)
+    const compareList = []
+    for (let i = 0, length = sorted.length; i < length; i++) {
+        let finished = compactItem(compareList, sorted[i])
+        finished.isUserMove = false
+        compareList.push(finished)
+        needCompact[i] = finished
+    }
+    return needCompact
+}

+ 33 - 0
app/src/util/correction.js

@@ -0,0 +1,33 @@
+import { collision } from "./collison";
+
+
+export const checkInContainer = (GridX, GridY, col, w) => {
+    /**防止元素出container */
+    if (GridX + w > col - 1) GridX = col - w //右边界
+    if (GridX < 0) GridX = 0//左边界
+    if (GridY < 0) GridY = 0//上边界
+    return { GridX, GridY }
+}
+
+/**
+ * 这个函数会有副作用,不是纯函数,会改变item的Gridx和GridY
+ * @param {*} item 
+ */
+export const correctItem = (item, col) => {
+    const { GridX, GridY } = checkInContainer(item.GridX, item.GridY, col, item.w)
+    item.GridX = GridX;
+    item.GridY = GridY;
+}
+export const correctLayout = (layout, col) => {
+    var copy = [...layout];
+    for (let i = 0; i < layout.length - 1; i++) {
+        correctItem(copy[i], col)
+        correctItem(copy[i + 1], col);
+
+        if (collision(copy[i], copy[i + 1])) {
+            copy = layoutCheck(copy, copy[i], copy[i].key, copy[i].key, undefined)
+        }
+    }
+
+    return copy;
+}

+ 52 - 0
app/src/util/initiate.js

@@ -0,0 +1,52 @@
+
+/**
+ * 把用户移动的块,标记为true
+ * @param {*} layout 
+ * @param {*} key 
+ * @param {*} GridX 
+ * @param {*} GridY 
+ * @param {*} isUserMove 
+ */
+export const syncLayout = (layout, key, GridX, GridY, isUserMove) => {
+    const newlayout = layout.map((item) => {
+        if (item.key === key) {
+            item.GridX = GridX
+            item.GridY = GridY
+            item.isUserMove = isUserMove
+            return item
+        }
+        return item
+    })
+    return newlayout
+}
+
+
+/**
+ * 初始化的时候调用
+ * 会把isUserMove和key一起映射到layout中
+ * 不用用户设置
+ * @param {*} layout 
+ * @param {*} children 
+ */
+
+export const MapLayoutTostate = (layout, children) => {
+    return layout.map((child, index) => {
+        let newChild = { ...child, isUserMove: true, key: children[index].key, static: children[index].static }
+        return newChild
+    })
+}
+
+/**
+ * 用key从layout中拿出item
+ * @param {*} layout 输入进来的布局
+ * @param {*} key 
+ */
+export const layoutItemForkey = (layout, key) => {
+    for (let i = 0, length = layout.length; i < length; i++) {
+        if (key === layout[i].key) {
+            return layout[i]
+        }
+    }
+}
+
+

+ 25 - 0
app/src/util/sort.js

@@ -0,0 +1,25 @@
+export function quickSort(a) {
+    return a.length <= 1 ? a : quickSort(a.slice(1).filter(item => item <= a[0])).concat(a[0], quickSort(a.slice(1).filter(item => item > a[0])));
+}
+
+export const sortLayout = (layout) => {
+    return [].concat(layout).sort((a, b) => {
+        if (a.GridY > b.GridY || (a.GridY === b.GridY && a.GridX > b.GridX)) {
+            if (a.static) return 0//为了静态,排序的时候尽量把静态的放在前面
+            return 1
+        } else if (a.GridY === b.GridY && a.GridX === b.GridX) {
+            return 0
+        }
+        return -1
+    })
+}
+
+export const getMaxContainerHeight = (layout, elementHeight = 30, elementMarginBottom = 10) => {
+    const ar = layout.map((item) => {
+        return item.GridY + item.h
+    })
+    const h = quickSort(ar)[ar.length - 1];
+    const height = h * (elementHeight + elementMarginBottom) + elementMarginBottom
+    return height
+}
+

+ 11 - 1
app/src/utils.js

@@ -46,4 +46,14 @@ export const parseBounds = (bounds) => {
 
 export const isNumber = (things) => {
     return typeof things === 'number' ? true : false
-}
+}
+
+export const getDataSet = (children) => {
+    return children.map((child) => {
+        return { ...child.props['data-set'], isUserMove: true, key: child.key, }
+    })
+}
+
+export const stringJoin = (source, join) => {
+    return source + (join ? ` ${join}` : '')
+}