【实战】从零开始打造一个低代码平台——5、拖拽组件2


对这个系列感兴趣的可以关注订阅专栏:从零开始打造一个低代码平台

前言

前面一章我们引入了图标资源,添加了第一个控件,实现了将控件拖拽到画布的事件框架。这一章我们将继续完成整个功能,将控件拖拽到画布上后生一个Button组件。


一、控件和组件

我们先厘清一下控件组件的概念。控件WidgetBar上的元素(Widget),组件是在画布上创建出来的元素(Component),控件是组件的类别,某种控件可以创建出多个组件。例如,拖拽WidgetBar上的Button控件可以在画布上创建多个Button组件。

二、定义组件

我们定义一下组件类型,一个最简单的组件包含类型,位置和尺寸信息。以下是组件类型定义:

interface Widget {
	type: string;
	left: number;
	top: number;
	width: number;
	height: number;
}

然后在Canvas里定义一个widgets:

const [widgets, setWidgets] = useState<Widget>([]);

Canvas负责绘出列表里所有的组件:

<div className={className ?? ""}>
  {widgets.map((widget, index) => {
    return (
      <div
        key={index}
        className="absolute bg-gray-700 rounded-md flex justify-center items-center"
        style={{
          left: `${widget.left}px`,
          top: `${widget.top}px`,
          width: `${widget.width}px`,
          height: `${widget.height}px`,
        }}
      >
        <i>Button</i>
      </div>
    );
  })}
</div>

三、拖拽事件

前一章提到,需要在source元素上实现onDragStart事件,在这里将控件类型等相关信息打包送出,然后在target元素上实现onDrop,接受数据,然后根据控件类型等信息创建组件。
目前我们只定义了一种控件,所以我们先偷点懒,省掉onDragStart打包数据的步骤,直接处理onDrop,在onDrop里新增一个组件。

onDrop={(e) => {
  const { clientX, clientY } = e;
  setWidgets([
    ...widgets,
    { type: "btn", left: clientX, top: clientY, width: 100, height: 50 },
  ]);
}}

四、完整的Canvas组件

改造后的完整Canvas如下:

import { useState } from "react";

interface CanvasProps {
  className?: string;
}

export const Canvas: React.FC<CanvasProps> = ({ className }) => {
  const [widgets, setWidgets] = useState<
    { type: string; left: number; top: number; width: number; height: number }[]
  >([]);

  return (
    <div
      className={className ?? ""}
      onDragOver={(e) => {
        e.preventDefault();
      }}
      onDrop={(e) => {
        const { clientX, clientY } = e;
        setWidgets([
          ...widgets,
          { type: "btn", left: clientX, top: clientY, width: 100, height: 50 },
        ]);
      }}
    >
      {widgets.map((widget, index) => {
        return (
          <div
            key={index}
            className="absolute bg-gray-700 rounded-md flex justify-center items-center"
            style={{
              left: `${widget.left}px`,
              top: `${widget.top}px`,
              width: `${widget.width}px`,
              height: `${widget.height}px`,
            }}
          >
            <i>Button</i>
          </div>
        );
      })}
    </div>
  );
};

现在我们可以从WidgetBar将Button控件拖拽到Canvas上,创建多个的Button组件了。如下图所示:

在这里插入图片描述
但有个小问题,组件生成的位置跟鼠标的位置不一样,似乎有固定的偏差。这个问题我们在后续章节讲组件定位的时候会来解决。


总结

这个章节跟上个章节我们实现了组件的拖拽,一个可视化平台基本又核心的功能。当然,产品化的实现还要考虑很多其它的问题,但我们好歹算开始了我们的第一个功能设计。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值