lowcode-engine
lowcode-engine copied to clipboard
组件拖拽是否可以直接拖拽后绝对定位
想实现个类似大屏的场景,需要支持以下特性:
能否让组件拖拽到哪就显示在哪,默认绝对定位。 拖拽的组件是否可以覆盖在其他组件之上。
目前没现成的东西
我准备尝试一下这个需求
一周后来反馈进度
目前demo有了新的进展,利用plugin和custom/setter可以完成拖拽了。细节上还需要进一步的优化。稍后会奉上代码
由于是利用官方的插件讨巧实现的,所以感觉有些卡顿。应该是官方做了防抖导致的。具体优化需要等待官方提供更优雅的解决方案。实现原理就是监听官方的画布拖拽事件然后通过设置器实时修改样式属性。稍后附上完整的例子。欢迎讨论提供更好的解决方案 目录结构: plugin-dragon-event |- setters |-|_ dragon-setter.tsx // 设置器 |_ index.tsx
在项目插件目录下,例如:demo-basic-antd/src/plugins下新建自定义插件 index.tsx
import { IPublicModelPluginContext } from '@alilc/lowcode-types';
import DragonSetter from './setters/dragon-setter';
const DragonEventPlugin = (ctx: IPublicModelPluginContext) => {
return {
async init() {
const { setters,event, canvas } = ctx;
setters.registerSetter("DragonSetter",DragonSetter)
canvas.dragon?.onDragstart((e) => {
event.emit('dragon.onDragstart', e);
});
canvas.dragon?.onDrag((e) => {
event.emit('dragon.onDrag', e);
});
canvas.dragon?.onDragend((e) => {
event.emit('dragon.onDragend', e);
});
},
};
};
DragonEventPlugin.pluginName = 'DragonEventPlugin';
export default DragonEventPlugin;
配置设置器 dragon-setter.tsx
import { event } from '@alilc/lowcode-engine';
const DragonSetter = (props: any) => {
const { field = {}, selected = {} } = props;
const { parent, node } = field;
const onDragstart = {
canvasX: 0,
canvasY: 0,
};
const onDragMove = {
canvasX: 0,
canvasY: 0,
};
let oldStyle: any = {};
event.on(`common:dragon.onDragstart`, function (e) {
onDragstart.canvasX = e.canvasX;
onDragstart.canvasY = e.canvasY;
oldStyle = parent?.getPropValue('style') || {};
});
event.on(`common:dragon.onDrag`, function (e) {
const {
dragObject: { nodes },
} = e;
if (nodes?.length > 0 && selected._id == nodes[0].id) {
onDragMove.canvasX = e.canvasX;
onDragMove.canvasY = e.canvasY;
const { left: oldX = 0, top: oldY = 0 } = oldStyle;
const parentNode = node?.parent;
if (parentNode) {
const parentEle = parentNode.getDOMNode();
const { clientWidth: parentWidth = 0, clientHeight: parentHeight = 0 } = parentEle;
const element = node.getDOMNode();
const { clientWidth: eleWidth = 0, clientHeight: eleHeight = 0 } = element;
// 移动的趋势
// 大于0为往右位移,小于0为往左位移
const distanceX = onDragMove.canvasX - onDragstart.canvasX;
// 大于0往下位移,小于0往上位移
const distanceY = onDragMove.canvasY - onDragstart.canvasY;
// 新位置 = left + 移动趋势
const newLeft = oldX + distanceX;
// 新位置 = top + 移动趋势
const newTop = oldY + distanceY;
const style: any = {};
if (distanceX >= 0) {
if (newLeft + eleWidth < parentWidth) {
style.left = newLeft;
style.right = '';
} else {
style.left = '';
style.right = 0;
}
} else {
if (newLeft >= 0) {
style.left = newLeft;
style.right = '';
} else {
style.left = 0;
}
}
if (distanceY >= 0) {
if (newTop + eleHeight < parentHeight) {
style.top = newTop;
style.bottom = '';
} else {
style.top = '';
style.bottom = 0;
}
} else {
if (newTop >= 0) {
style.top = newTop;
style.bottom = '';
} else {
style.top = 0;
}
}
parent.setPropValue('style', { position: 'absolute', ...style });
}
}
});
event.on(`common:dragon.onDragend`, function (e) {
console.log('onDragend', onDragMove);
});
return <div>拖拽监听</div>;
};
export default DragonSetter;
index.ts
await plugins.register(DragonEventPlugin);
配置设置器,组件方可拖拽
meta.js
"setter": {
"componentName": "DragonSetter",
"props": { },
"initialValue": ""
}
由于是利用官方的插件讨巧实现的,所以感觉有些卡顿。应该是官方做了防抖导致的。具体优化需要等待官方提供更优雅的解决方案。实现原理就是监听官方的画布拖拽事件然后通过设置器实时修改样式属性。稍后附上完整的例子。欢迎讨论提供更好的解决方案 目录结构: plugin-dragon-event |- setters |-|_ dragon-setter.tsx // 设置器 |_ index.tsx
在项目插件目录下,例如:demo-basic-antd/src/plugins下新建自定义插件 index.tsx
import { IPublicModelPluginContext } from '@alilc/lowcode-types'; import DragonSetter from './setters/dragon-setter'; const DragonEventPlugin = (ctx: IPublicModelPluginContext) => { return { async init() { const { setters,event, canvas } = ctx; setters.registerSetter("DragonSetter",DragonSetter) canvas.dragon?.onDragstart((e) => { event.emit('dragon.onDragstart', e); }); canvas.dragon?.onDrag((e) => { event.emit('dragon.onDrag', e); }); canvas.dragon?.onDragend((e) => { event.emit('dragon.onDragend', e); }); }, }; }; DragonEventPlugin.pluginName = 'DragonEventPlugin'; export default DragonEventPlugin;
配置设置器 dragon-setter.tsx
import { event } from '@alilc/lowcode-engine'; const DragonSetter = (props: any) => { const { field = {}, selected = {} } = props; const { parent, node } = field; const onDragstart = { canvasX: 0, canvasY: 0, }; const onDragMove = { canvasX: 0, canvasY: 0, }; let oldStyle: any = {}; event.on(`common:dragon.onDragstart`, function (e) { onDragstart.canvasX = e.canvasX; onDragstart.canvasY = e.canvasY; oldStyle = parent?.getPropValue('style') || {}; }); event.on(`common:dragon.onDrag`, function (e) { const { dragObject: { nodes }, } = e; if (nodes?.length > 0 && selected._id == nodes[0].id) { onDragMove.canvasX = e.canvasX; onDragMove.canvasY = e.canvasY; const { left: oldX = 0, top: oldY = 0 } = oldStyle; const parentNode = node?.parent; if (parentNode) { const parentEle = parentNode.getDOMNode(); const { clientWidth: parentWidth = 0, clientHeight: parentHeight = 0 } = parentEle; const element = node.getDOMNode(); const { clientWidth: eleWidth = 0, clientHeight: eleHeight = 0 } = element; // 移动的趋势 // 大于0为往右位移,小于0为往左位移 const distanceX = onDragMove.canvasX - onDragstart.canvasX; // 大于0往下位移,小于0往上位移 const distanceY = onDragMove.canvasY - onDragstart.canvasY; // 新位置 = left + 移动趋势 const newLeft = oldX + distanceX; // 新位置 = top + 移动趋势 const newTop = oldY + distanceY; const style: any = {}; if (distanceX >= 0) { if (newLeft + eleWidth < parentWidth) { style.left = newLeft; style.right = ''; } else { style.left = ''; style.right = 0; } } else { if (newLeft >= 0) { style.left = newLeft; style.right = ''; } else { style.left = 0; } } if (distanceY >= 0) { if (newTop + eleHeight < parentHeight) { style.top = newTop; style.bottom = ''; } else { style.top = ''; style.bottom = 0; } } else { if (newTop >= 0) { style.top = newTop; style.bottom = ''; } else { style.top = 0; } } parent.setPropValue('style', { position: 'absolute', ...style }); } } }); event.on(`common:dragon.onDragend`, function (e) { console.log('onDragend', onDragMove); }); return <div>拖拽监听</div>; }; export default DragonSetter;
index.ts
await plugins.register(DragonEventPlugin);
配置设置器,组件方可拖拽
meta.js "setter": { "componentName": "DragonSetter", "props": { }, "initialValue": "" }
膜拜
经过最近的有一段时间研究,结合官方反馈了一些思路,有了新的进展。稍后我会附上自由拖拽和磁吸的例子
插个眼,坐等大佬新进展 👍
插个眼
经过没日没夜的尝试:终于完成了可用的版本 http://lowcode.zerocmf.com/ 拖拽一个容器,选上自由布局,然后就可以拖入若干个可以移动的按钮了。遇到问题欢迎反馈。我继续优化 代码:https://github.com/daifuyang/zero-materials 我最近打算做一个用于nextjs的低代码物料。主要用于建站业务。不知道官方的渲染器不知道支不支持ssr。不支持的话后续可能还会实现基于nextjs的渲染器。有志同道合的小伙伴欢迎一起入坑。
反馈个问题哈,把组件拖进自由布局的容器时,可以拖,但是焦点离开这个容器后,再进去拖动发现就失效了
自由画布金禅之前做的有个demo可以参考 https://github.com/jinchanz/plugin-ablosute-designer
反馈个问题哈,把组件拖进自由布局的容器时,可以拖,但是焦点离开这个容器后,再进去拖动发现就失效了
需要使组件处于激活状态才行
https://github.com/loganjingdi/lowcode-material-magneticContainer 磁吸布局之前做了一个小demo,大家可以提提意见~
https://github.com/loganjingdi/lowcode-material-magneticContainer 磁吸布局之前做了一个小demo,大家可以提提意见~
标题是绝对定位,和磁吸还不太一样。em...,可以参考金蝉大佬的 https://github.com/jinchanz/plugin-ablosute-designer , 不过这里面用的engine-core内核是做了些改造的,太久之前研究的,一时想不起来是哪个分支了。。。
https://lowcode-engine.cn/demo/demo-general/index.html 官方 DEMO 中容器也可以转化成自由布局容器,欢迎体验。
https://lowcode-engine.cn/demo/demo-general/index.html 官方 DEMO 中容器也可以转化成自由布局容器,欢迎体验。
赞,后续计划支持对齐用的参考线么
https://lowcode-engine.cn/demo/demo-general/index.html 官方 DEMO 中容器也可以转化成自由布局容器,欢迎体验。
赞,后续计划支持对齐用的参考线么
目前没有,欢迎共建~
https://lowcode-engine.cn/demo/demo-general/index.html 官方 DEMO 中容器也可以转化成自由布局容器,欢迎体验。
反馈个问题:
蹲
https://lowcode-engine.cn/demo/demo-general/index.html 官方 DEMO 中容器也可以转化成自由布局容器,欢迎体验。
固定组件面板,只能拖入一个组件,后面拖的组件报错