vue-grid-layout 外部拖入单元格

本文演示 vue-grid-layout 外部拖入单元格。

在线试一试

完整代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>vue-grid-layout vue umd版本</title>
    <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, minimal-ui">
    <script src="https://www.itxst.com/package/vue/vue.min.js"></script>
    <script src="https://www.itxst.com/package/vue-grid-layout/vue-grid-layout.umd.min.js"></script>
</head>
<body style="padding:10px;">
    <div id="app">
        <div @drag="drag" @dragend="dragend" class="droppable-element" draggable="true" unselectable="on">点击拖动me</div>
        <div id="content">
            <grid-layout ref="gridlayout" :layout.sync="layout" :col-num="12" :row-height="30">

                <grid-item v-for="item in layout" :x="item.x" :y="item.y" :w="item.w" :h="item.h" :i="item.i"
                    :key="item.i">
                    {{item.i}}
                </grid-item>
            </grid-layout>
        </div>
    </div>
    <script>
        let mouseXY = { "x": null, "y": null };
        let DragPos = { "x": null, "y": null, "w": 1, "h": 1, "i": null };
        var app = new Vue({
            el: '#app',
            components: {
                GridLayout: VueGridLayout.GridLayout,
                GridItem: VueGridLayout.GridItem
            },
            data() {
                return {
                    layout: [
                        { "x": 0, "y": 0, "w": 2, "h": 2, "i": "0" },
                        { "x": 2, "y": 0, "w": 2, "h": 2, "i": "1" },
                        { "x": 4, "y": 0, "w": 2, "h": 2, "i": "2" },
                        { "x": 0, "y": 1, "w": 6, "h": 2, "i": "3" },
                    ]
                };
            },
            mounted() {
                document.addEventListener("dragover", function (e) {
                    mouseXY.x = e.clientX;
                    mouseXY.y = e.clientY;
                }, false);
            },
            beforeDestroy() {
            },
            methods: {
                drag: function (e) {
                    let parentRect = document.getElementById('content').getBoundingClientRect();
                    let mouseInGrid = false;
                    if (((mouseXY.x > parentRect.left) && (mouseXY.x < parentRect.right)) && ((mouseXY.y > parentRect.top) && (mouseXY.y < parentRect.bottom))) {
                        mouseInGrid = true;
                    }
                    if (mouseInGrid === true && (this.layout.findIndex(item => item.i === 'drop')) === -1) {
                        this.layout.push({
                            x: (this.layout.length * 2) % (this.colNum || 12),
                            y: this.layout.length + (this.colNum || 12), // puts it at the bottom
                            w: 1,
                            h: 1,
                            i: 'drop',
                        });
                    }
                    let index = this.layout.findIndex(item => item.i === 'drop');
                    if (index !== -1) {
                        try {
                            this.$refs.gridlayout.$children[this.layout.length].$refs.item.style.display = "none";
                        } catch {
                        }
                        let el = this.$refs.gridlayout.$children[index];
                        el.dragging = { "top": mouseXY.y - parentRect.top, "left": mouseXY.x - parentRect.left };
                        let new_pos = el.calcXY(mouseXY.y - parentRect.top, mouseXY.x - parentRect.left);
                        if (mouseInGrid === true) {
                            this.$refs.gridlayout.dragEvent('dragstart', 'drop', new_pos.x, new_pos.y, 1, 1);
                            DragPos.i = String(index);
                            DragPos.x = this.layout[index].x;
                            DragPos.y = this.layout[index].y;
                        }
                        if (mouseInGrid === false) {
                            this.$refs.gridlayout.dragEvent('dragend', 'drop', new_pos.x, new_pos.y, 1, 1);
                            this.layout = this.layout.filter(obj => obj.i !== 'drop');
                        }
                    }
                },
                dragend: function (e) {
                    let parentRect = document.getElementById('content').getBoundingClientRect();
                    let mouseInGrid = false;
                    if (((mouseXY.x > parentRect.left) && (mouseXY.x < parentRect.right)) && ((mouseXY.y > parentRect.top) && (mouseXY.y < parentRect.bottom))) {
                        mouseInGrid = true;
                    }
                    if (mouseInGrid === true) {
                        alert(`Dropped element props:\n${JSON.stringify(DragPos, ['x', 'y', 'w', 'h'], 2)}`);
                        this.layout = this.layout.filter(obj => obj.i !== 'drop');
                        //************ 添加到拖动的目标位置
                        this.layout.push({
                            x: DragPos.x,
                            y: DragPos.y,
                            w: 1,
                            h: 1,
                            i: DragPos.i,
                        });
                        this.$refs.gridLayout.dragEvent('dragend', DragPos.i, DragPos.x, DragPos.y, 1, 1);
                        try {
                            this.$refs.gridLayout.$children[this.layout.length].$refs.item.style.display = "block";
                        } catch {
                        }
                    }
                },
            }
        });
    </script>
    <style scoped>
        .droppable-element {
            width: 120px;
            text-align: center;
            background: #fdd;
            border: 1px solid black;
            margin: 10px 0;
            padding: 10px;
        }

        .vue-grid-layout {
            background: #eee;
        }

        .vue-grid-item:not(.vue-grid-placeholder) {
            background: #ccc;
            border: 1px solid black;
        }

        .vue-grid-item .resizing {
            opacity: 0.9;
        }

        .vue-grid-item .static {
            background: #cce;
        }

        .vue-grid-item .text {
            font-size: 24px;
            text-align: center;
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            margin: auto;
            height: 100%;
            width: 100%;
        }

        .vue-grid-item .no-drag {
            height: 100%;
            width: 100%;
        }

        .vue-grid-item .minMax {
            font-size: 12px;
        }

        .vue-grid-item .add {
            cursor: pointer;
        }

        .vue-draggable-handle {
            position: absolute;
            width: 20px;
            height: 20px;
            top: 0;
            left: 0;
            background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><circle cx='5' cy='5' r='5' fill='#999999'/></svg>") no-repeat;
            background-position: bottom right;
            padding: 0 8px 8px 0;
            background-repeat: no-repeat;
            background-origin: content-box;
            box-sizing: border-box;
            cursor: pointer;
        }
    </style>
</body>
</html>