从零实现一套低代码(保姆级教程) --- 【3】实现Button组件和画布区的拖拽

这篇具有很好参考价值的文章主要介绍了从零实现一套低代码(保姆级教程) --- 【3】实现Button组件和画布区的拖拽。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

摘要

目前是每天更新一篇, 因为我不止要写文章,这些代码也是我正在敲的。可能速度没有那么快,但是这个频率感觉还是可以的。

本篇是这个系列的第三篇,如果你是第一次看到这个文章,那你应该会对低代码有那么一丢丢兴趣或者很有兴趣。从标题来看,也知道我这个系列就是实现一个低代码的项目。

那如果你想知道,我实现的项目的样子是什么样的,可以访问下面的链接:
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
XinBuilder 点击跳转

如果你有兴趣,跟着实现这么一套代码,那么你可以从第一章节开始阅读:
从零实现一套低代码(保姆级教程) — 【1】初始化项目,实现左侧组件列表

因为上一篇文章,没有额外的提交,所有的代码都写在了文章里,所以这里就直接继续上一篇开始说。

在上一篇结束后,我们实现了左侧组件拖拽到画布区的效果!!!

但是因为我们组件里面只有一个文本,所以今天我们主要来实现组件,以及画布区中组件的拖拽。
从零实现一套低代码(保姆级教程) --- 【3】实现Button组件和画布区的拖拽,低代码,rxjava,android

1.组件的实现

在上一节中,我们在Button组件中,从props里面接收了style,从而实现组件在画布区的定位效果。

但是之所以显示文本,是因为我们写的就是文本,现在我们给它改成antD里面的Button组件。

import { Button as AntButton } from 'antd'

export default function Button(props: any) {
  const {style} = props
  return (
    <div style={style}>
      <AntButton>按钮</AntButton>
    </div>
  )
}

这里注意一下,因为我的组件就叫Button,如果引入antD的Button时,没有改名会引起报错

你可以有两种解决办法,一种是像我这样,另一种就是修改自己这个组件的名,例如不叫Button,叫XButton即可

当你修改完后,再拖拽组件,那么在画布区显示的就不是一段文本了!!!!

从零实现一套低代码(保姆级教程) --- 【3】实现Button组件和画布区的拖拽,低代码,rxjava,android

2.实现画布区的拖拽

现在呢,我们拖拽到画布区的组件,就定死在那里了,不能拖拽,现在我们要给画布区的组件添加拖拽的效果。

现在请读者打开mainPart下的index.jsx文件,看一下最终的return。

我们在遍历comList的时候,返回的Com外层应该包一层div用来实现拖拽的效果。
从零实现一套低代码(保姆级教程) --- 【3】实现Button组件和画布区的拖拽,低代码,rxjava,android

同时也要给这个外层的div一个拖拽的方法,onDragStart,由于在画布区拖拽组件,也只能拖拽到画布区,所以我们不需要像上次一样,做一些禁止默认行为的处理了。

  // 画布区的组件拖拽方法
  const onDragStart = (com: ComJson) => {
    return () => {

    }
  }


  return (
    <div onDrop={onDrop} onDragOver={onDragOver} onDragEnter={onDragEnter} className='mainCom'>
      {
        comList.map(com => {
          const Com = components[com.comType as keyof typeof components];
          // 在外面包一层控制拖拽的div
          return <div draggable onDragStart={onDragStart(com)}>
            <Com style={com.style} />
          </div>
        })
      }
    </div>
  )

OK。现在请打开浏览器看一下实现的效果吧,是不是发现有点问题,每次你在画布区拖拽后,都会生成一个新的组件,而不是组件的移动。这是为什么呢?

从零实现一套低代码(保姆级教程) --- 【3】实现Button组件和画布区的拖拽,低代码,rxjava,android
答案在我们写的onDrop方法里,因为每次拖拽完都会触发onDrop方法,每次都会push一个新的组件

所以我们应该是从左侧组件列表拖拽的时候,进行push。如果是在画布区拖拽,我们只需要更新style属性即可。

那怎么判断是画布区拖拽的组件还是左侧栏拖拽的组件呢?我们可以在这里的onDragStart里,将window.nowCom设定为一个特殊的值。在onDrop根据这个值去判断走哪条分支。

  // 用于保存当前画布区拖拽的节点
  const [dragCom, setDragCom] = useState<ComJson | null>(null)

  const onDrop = (e: any) => {
    const endLeft = e.clientX;
    const endTop = e.clientY;
    const style = {
      position: 'absolute',
      left: endLeft + 'px',
      top: endTop + 'px',
      zIndex:100
    }
    // 判断当前拖拽的节点是从画布区拖拽,还是左侧组件栏拖拽
    if(window.nowCom === 'renderCom' && dragCom) {
      dragCom.style = style
    }else{
      comList.push({
        comType: window.nowCom,
        style
      })
    }
    setComList([...comList])
  }
  
  const onDragStart = (com: ComJson) => {
    return () => {
      // 设置拖拽的节点和nowCom的固定值
      window.nowCom = 'renderCom';
      setDragCom(com)
    }
  }

现在请再看一下效果,在画布区的拖拽就已经解决了。
但是呢,是不是位置不太准确呢

3.计算组件拖拽后的位置

好像在画布区拖拽完组件,新的位置总是差了那么一点,这是为什么呢?
先给一点提示,如果你拖拽的时候,鼠标位置在组件的左上角,那就没有问题了。

答案是,你给组件的left和top的定位,是基于鼠标位置的,也就是说,你把鼠标距离顶部和左部的距离,给了组件,那如果组件有自己的宽高,那么这个定位就是不准的。

所以为了算出正确的位置,我们应该计算出鼠标向左移动的距离和向上移动的距离。
然后加上组件本身的left和top值。

组件位置.left = 组件旧位置.left + 鼠标向左移动的距离
组件位置.top= 组件旧位置.top+ 鼠标向上移动的距离

那怎么计算鼠标移动的距离呢?我们可以在dragStart中,保存鼠标的位置。drop事件里,再保存一下鼠标的位置,诶?两者的差值不就是鼠标移动的位置嘛?
简单画一下流程图:

从零实现一套低代码(保姆级教程) --- 【3】实现Button组件和画布区的拖拽,低代码,rxjava,android

  // 用来保存鼠标的开始位置和结束位置
  const distance = useRef<Distance>({
    startLeft: void 0,
    startTop: void 0,
    endLeft: void 0,
    endTop: void 0
  })
  
  const onDragStart = (com: ComJson) => {
    return (e: any) => {
      window.nowCom = 'renderCom';
      setDragCom(com);
      // 开始位置
      distance.current.startLeft = e.clientX;
      distance.current.startTop = e.clientY;
    }
  }

    const onDrop = (e: any) => {
    // 鼠标的结束位置
    distance.current.endLeft = e.clientX;
    distance.current.endTop = e.clientY;
    let style: any;
    if(window.nowCom === 'renderCom' && dragCom && dragCom.style) {
      // 根据鼠标位置的差值计算组件位置
      dragCom.style = {
        ...dragCom.style,
        left: parseInt(dragCom.style.left) + (e.clientX - (distance.current.startLeft || 0)) + 'px',
        top: parseInt(dragCom.style.top) + (e.clientY - (distance.current.startTop || 0)) + 'px'
      }
    }else{
      style = {
        position: 'absolute',
        left: distance.current.endLeft + 'px',
        top: distance.current.endTop + 'px',
        zIndex:100
      }
      comList.push({
        comType: window.nowCom,
        style
      })
    }
    setComList([...comList])
  }

基于上面的实现,我们就完成了组件在画布区的拖拽了。

本章内容会提交在github上:
https://github.com/TeacherXin/XinBuilder2
commit: 第三节:实现Button组件和画布区的拖拽

如果可以的话,可以给博主的GitHub点亮一颗小星星(╹▽╹)

博主补充

那如果现在你已经完成了所有的过程,你可以自己把其他组件的代码也补充一下。
我会在github上提交一段代码,用来补充文本框组件的代码,内容可以在github上查看

https://github.com/TeacherXin/XinBuilder2
commit: 第三节:实现Input组件代码

第二个问题,为什么鼠标的位置我们通过useRef来进行存储。因为这四个变量不需要更新去渲染组件,所以没必要通过useState去管理。但是呢,每次更新组件的时候还需要拿到之前的值,所以我们使用useRef进行管理。

第三个问题,现在我们有comList保存所有的组件数据,dragCom保存在画布区拖拽的组件。这个在后面,我们会采用redux进行管理,会有所更改,目前的话我们先使用这种模式来把整个流程串通。

最后,博主的TS可能没有那么熟练,如果有建议的话,博主也会积极采纳的!!!!

下一篇
从零实现一套低代码(保姆级教程) — 【4】实现右侧属性面板文章来源地址https://www.toymoban.com/news/detail-763295.html

到了这里,关于从零实现一套低代码(保姆级教程) --- 【3】实现Button组件和画布区的拖拽的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【模型+代码/保姆级教程】使用Pytorch实现手写汉字识别

    参考文章: 最初参考的两篇: 【Pytorch】基于CNN手写汉字的识别 「Pytorch」CNN实现手写汉字识别(数据集制作,网络搭建,训练验证测试全部代码) 模型: EfficientNetV2网络详解 数据集(不必从这里下载,可以看一下它的介绍): CASIA Online and Offline Chinese Handwriting Databases 鉴于

    2024年02月07日
    浏览(31)
  • Unity教程2:保姆级教程.几行代码实现输入控制2D人物的移动

    目录 人物的创建以及刚体的设置 图层渲染层级设置 角色碰撞箱设置 使用代码控制人物移动 创建脚本文件  初始函数解释 控制移动代码 初始化变量  获得键盘输入  调用函数 手册链接在这:Unity User Manual (2019.3) - Unity 手册 没有控制人物移动的2D游戏就太说不过去了!那么接

    2024年02月06日
    浏览(31)
  • docker从零部署jenkins保姆级教程

    jenkins,基本是最常用的持续集成工具。在实际的工作中,后端研发一般没有jenkins的操作权限,只有一些查看权限,但是我们的代码是经过这个工具构建出来部署到服务器的,所以我觉着有必要了解一下这个工具的搭建过程以及简单的一些使用。尽可能多的了解公司中和你开

    2024年02月10日
    浏览(38)
  • 高级圣诞树代码实现合集-保姆级教程【前端三件套实现—0基础直接运行】

    0基础直接运行教程: 1.新建txt文本: 2.将代码粘贴到txt文本里: 3.将后缀改为html 4.双击打开html文件,观察效果~ 这段代码是一个用HTML和JavaScript实现的圣诞树动画效果。我将代码分成几个部分进行讲解。 HTML结构: 在 head 标签中定义了页面的标题、字符集和样式。 样式部分

    2024年02月04日
    浏览(52)
  • docker从零部署jenkins保姆级教程(下)

    上一篇文章,我们完成了以下工作。 1)、docker部署jenkins 2)、建立第一个jenkins job 3)、通过jenkins job自动编译构建我们的github项目 上面所做的3个工作,其实都是为了这一篇文章打基础,不管是部署docker还是部署jenkins,我们最终的目的还是部署我们的项目,让项目跑起来,让流

    2024年02月09日
    浏览(76)
  • docker从零部署jenkins保姆级教程(上)

    jenkins,基本是最常用的持续集成工具。在实际的工作中,后端研发一般没有jenkins的操作权限,只有一些查看权限,但是我们的代码是经过这个工具构建出来部署到服务器的,所以我觉着有必要了解一下这个工具的搭建过程以及简单的一些使用。尽可能多的了解公司中和你开

    2024年02月09日
    浏览(37)
  • 保姆级教程:从零构建GitHub Pages静态网站

    Github Pages官网:https://pages.github.com/ GitHub Pages 是 GitHub 提供的一个免费的静态网站托管服务,它允许 GitHub 用户创建和托管自己的静态网站,这些网站可以通过特定的 GitHub 仓库进行管理和托管。 GitHub Pages 的主要特点包括 : 免费托管 : GitHub Pages 提供免费的静态网站托管服务

    2024年02月04日
    浏览(45)
  • 「教程」如何使用一套代码在多种程序中接入天气预警API

    天气预警的重要性不言而喻,在遭受自然灾害和极端天气时,及时获得预警信息可以拯救生命和减少财产损失。如今,随着科技的进步,开发者和企业可以借助天气预警 API 这款强大的服务,将实时预警信息集成到自己的应用中,为用户提供准确的预警通知。 本文将重点探讨

    2024年02月14日
    浏览(49)
  • 全网最详细·教你从零复现【人工智能病理】项目的保姆级教程

    这期推文来盘一盘如何从零开始复现一个深度学习的项目,我选择的项目是与AI病理相关的。 挑选好项目以后,可以建立一个简单的思维导图辅助我们梳理架构,首先要关注的,就是我红框选出来的两个文档。 先翻译一下标题。 作者放了一个动图。 然后就介绍了一下配套论

    2024年04月22日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包