简单的低开编辑器(三):实现组件画布内拖拽

好家伙,

0.代码已开源

Fattiger4399/lowcode-demo: 一个简单的低代码编辑器 技术栈:Vue3 element-plus jsx (github.com)

本篇实现效果如下:

1.分析

这玩意的思路很好理解

本质上就是给组件绑个拖拽方法

拽到哪里,就把位置更新给组件就好了,简单粗暴

当然,需要做选中判定,知道我选中了哪些组件

2.选中判定实现

//editor.jsx

复制代码
import { useFocus } from "./useFocus";

let { blockMousedown, focusData } = useFocus(data, (e) => {
            mousedown(e)
        });

//useFocus.js

复制代码
import {computed} from 'vue'

//useFocus用于处理画布中组件元素的选中
export function useFocus(data,callback){ //获取哪些元素被选中了
    const focusData = computed(() => {
        let focus = [];
        let unfocused = [];
        data.value.blocks.forEach(block => (block.focus ? focus : unfocused).push(block))
        return {focus,unfocused}
    })
    return{
        blockMousedown,
        focusData
    }
}

此处,我们做一次选中判定,将选中的组件,和未被选中的组件,分开放,并返回

//useFocus.js

复制代码
const blockMousedown = (e, block) =\> {
//block上我们规划一个属性focus 获取焦点后就将focus变为true
e.preventDefault();
e.stopPropagation();
if (e.shiftKey) {
block.focus = !block.focus
} else {
if (!block.focus) {
clearBlockFocus();
block.focus = true;//清空其他组件的focus属性
} else {
block.focus = false;
}
}
callback(e)
}

判断是否按下了shift键

3.点击触发事件

//editor.jsx

复制代码
<div class="editor-container-canvas__content"
                        style={containerStyles.value}
                        ref={containerRef}
                        onMousedown={containerMousedown}>
                        {
                            (data.value.blocks.map(block => (
                                <EditorBlock
                                    class={block.focus ? 'editor-block-focus' : ''}
                                    block={block}
                                    onMousedown={(e) => blockMousedown(e, block)}
                                ></EditorBlock>
                            )))
                        }
                    </div>
复制代码
let { blockMousedown, focusData } = useFocus(data, (e) => {
            mousedown(e)
        });
        const mousemove = (e) => {
            let { clientX: moveX, clientY: moveY } = e;
            let endX = moveX - dragState.startX;
            let endY = moveY - dragState.startY;

            focusData.value.focus.forEach((block, idx) => {
                // console.log(dragState)
                block.top = dragState.startPos[idx].top + endY;
                block.left = dragState.startPos[idx].top + endX;
            })
        }
        const mouseup = (e) => {
            console.log(document)
            document.removeEventListener('mousemove', mousemove)
            document.removeEventListener('mouseup', mouseup)
        }
        const mousedown = (e) => {
            dragState = {
                startX: e.clientX,
                startY: e.clientY,
                startPos: focusData.value.focus.map(({ top, left }) => ({ top, left }))
            }
            console.log(dragState)
            document.addEventListener('mousemove', mousemove)
            document.addEventListener('mouseup', mouseup)
        }

//useFocus.js

复制代码
const blockMousedown = (e, block) => {
        //block上我们规划一个属性focus 获取焦点后就将focus变为true
        e.preventDefault();
        e.stopPropagation();
        if (e.shiftKey) {
            block.focus = !block.focus
        } else {
            if (!block.focus) {
                clearBlockFocus();
                block.focus = true;//清空其他组件的focus属性
            } else {
                block.focus = false;
            }
        }
        callback(e)
    }

判断是否按下了shift键

复制代码
focusData.value.focus.forEach((block, idx) => {
                // console.log(dragState)
                      block.top = dragState.startPos[idx].top + endY;
                block.left = dragState.startPos[idx].top + endX;
            })

最后更改数据

搞定!