-
Notifications
You must be signed in to change notification settings - Fork 294
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
可视化拖拽组件库一些技术要点原理分析(四) #33
Comments
文字组件有一点小问题哦~ 文字组件编辑点击其他组件的话不能正确触发blur事件 |
我试了一下没问题,可以录个动图和复现步骤吗?另外,请在可视化的仓库下提 issue,这个仓库是博客。 |
有没有比较好的生成html文件的方案 |
主要是做落地页,然后打包放到不同域名里面去,又害怕改组件的时候会影响到之前的页面,分版本的话可能会迭代多个版本。非常没有必要 |
1 similar comment
主要是做落地页,然后打包放到不同域名里面去,又害怕改组件的时候会影响到之前的页面,分版本的话可能会迭代多个版本。非常没有必要 |
可以在 HTML 文件上直接 |
想问下 我能不能基于这个为后台 生产一个前台页面呢 想了解一下步骤是怎么实现的 |
没太明白你的意思,可以再详细描述下。 |
这个eslint报错难定啊 |
我是真的搞不明白了都配置eslint了为何不配个prettier的配置。一按保存满屏都飘红还得自己配语法检查 |
prettier 和 airbnb 语法格式差太多了。 |
想请教一下保存到数据库的问题。 我把这个低代码平台通过iframe植入到wordpress的后台(php)页面中,希望达到后台用户登录后通过它生成json存入数据表的字段中,现在用户登录了,我应该如何获取用户登录态身份认证并POST到后台中?有没有相关的技术文档,谢谢 |
iframe 之间可以通过 postmessage 通信传递数据,然后用 localStorage 存起来。 |
孩子的毕业论文就靠您的文章了啊。大佬yyds |
大佬,我想问一下,关于适配的疑问比如画布大小是1200740,但实际屏幕大小是19201080,是不是后续生成页面,要自己手写一个单位转化,比如组件的宽高等 |
是的 目前没有考虑自适应 |
本文是可视化拖拽系列的第四篇,比起之前的三篇文章,这篇功能点要稍微少一点,总共有五点:
如果你对我之前的系列文章不是很了解,建议先把这三篇文章看一遍,再来阅读本文(否则没有上下文,不太好理解):
另附上项目、在线 DEMO 地址:
SVG 组件
目前项目里提供的自定义组件都是支持自由放大缩小的,不过他们有一个共同点——都是规则形状。也就是说对它们放大缩小,直接改变宽高就可以实现了,无需做其他处理。但是不规则形状就不一样了,譬如一个五角星,你得考虑放大缩小时,如何成比例的改变尺寸。最终,我采用了 svg 的方案来实现(还考虑过用 iconfont 来实现,不过有缺陷,放弃了),下面让我们来看看具体的实现细节。
用 SVG 画一个五角星
假设我们需要画一个 100 * 100 的五角星,它的代码是这样的:
svg 上的版本、命名空间之类的属性不是很重要,可以先忽略。重点是 polygon 这个元素,它在 svg 中定义了一个由
一组首尾相连的直线线段构成的闭合多边形形状
,最后一点连接到第一点。也就是说这个多边形由一系列坐标点组成,相连的点之间会自动连上。polygon 的 points 属性用来表示多边形的一系列坐标点,每个坐标点由 x y 坐标组成,每个坐标点之间用,
逗号分隔。上图就是一个用 svg 画的五角星,它由十个坐标点组成
50 0,62.5 37.5,100 37.5,75 62.5,87.5 100,50 75,12.5 100,25 62.5,0 37.5,37.5 37.5
。由于这是一个 100*100 的五角星,所以我们能够很容易的根据每个坐标点的数值算出它们在五角星(坐标系)中所占的比例。譬如第一个点是 p1(50,0
),那么它的 x y 坐标比例是50%, 0
;第二个点 p2(62.5,37.5
),对应的比例是62.5%, 37.5%
...既然知道了五角星的比例,那么要画出其他尺寸的五角星也就易如反掌了。我们只需要在每次对五角星进行放大缩小,改变它的尺寸时,等比例的给出每个坐标点的具体数值即要。
其他 SVG 组件
同理,要画其他类型的 svg 组件,我们只要知道它们坐标点所占的比例就可以了。如果你不知道一个 svg 怎么画,可以网上搜一下,先找一个能用的 svg 代码(这个五角星的 svg 代码,就是在网上找的)。然后再计算它们每个坐标点所占的比例,转成小数点的形式,最后把这些数据代入上面提供的
drawPolygon()
函数即可。譬如画一个三角形的代码是这样的:动态属性面板
目前所有自定义组件的属性面板都共用同一个 AttrList 组件。因此弊端很明显,需要在这里写很多 if 语句,因为不同的组件有不同的属性。例如矩形组件有 content 属性,但是图片没有,一个不同的属性就得写一个 if 语句。
幸好,这个问题的解决方案也不难。在本系列的第一篇文章中,有讲解过如何动态渲染自定义组件:
在每个自定义组件的数据结构中都有一个
component
属性,这是该组件在 Vue 中注册的名称。因此,每个自定义组件的属性面板可以和组件本身一样(利用component
属性),做成动态的:同时,自定义组件的目录结构也需要做下调整,原来的目录结构为:
调整后变为:
现在每一个组件都包含了组件本身和它的属性面板。经过改造后,图片属性面板代码也更加精简了:
这样一来,组件和对应的属性面板都变成动态的了。以后需要单独给某个自定义组件添加属性就非常方便了。
数据来源(接口请求)
有些组件会有动态加载数据的需求,所以特地加了一个
Request
公共属性组件,用于请求数据。当一个自定义组件拥有request
属性时,就会在属性面板上渲染接口请求的相关内容。至此,属性面板的公共组件已经有两个了:从上面的动图可以看出,api 请求的方法参数等都是可以手动修改的。但是怎么控制返回来的数据赋值给组件的某个属性呢?这可以在发出请求的时候把组件的整个数据对象
obj
以及要修改属性的key
当成参数一起传进去,当数据返回来时,就可以直接使用obj[key] = data
来修改数据了。组件联动
组件联动:当一个组件触发事件时,另一个组件会收到通知,并且做出相应的操作。
上面这个动图的矩形,它分别监听了下面两个按钮的悬浮事件,第一个按钮触发悬浮并广播事件,矩形执行回调向右旋转移动;第二个按钮则相反,向左旋转移动。
要实现这个功能,首先要给自定义组件加一个新属性
linkage
,用来记录所有要联动的组件:对应的属性面板为:
组件联动本质上就是订阅/发布模式的运用,每个组件在渲染时都会遍历它监听的所有组件。
事件监听
从上述代码可以看出:
v-click
v-hover
两个事件(目前只有点击、悬浮两个事件)事件触发
从上述代码可以看出,在渲染组件时,每一个组件的最外层都监听了
click
mouseenter
事件,当这些事件触发时,eventBus 就会触发对应的事件( v-click 或 v-hover ),并且把当前的组件 id 作为参数传过去。最后再捊一遍整体逻辑:
组件按需加载
目前这个项目本身是没有做按需加载的,但是我把实现方案用文字的形式写出来其实也差不多。
第一步,抽离
第一步需要把所有的自定义组件出离出来,单独存放。建议使用 monorepo 的方式来存放,所有的组件放在一个仓库里。每一个 package 就是一个组件,可以单独打包。
- node_modules - packages - v-text # 一个组件就是一个包 - v-button - v-table - package.json - lerna.json
第二步,打包
建议每个组件都打包成一个 js 文件 ,例如叫 bundle.js。打包好直接调用上传接口放到服务器存起来(发布到 npm 也可以),每个组件都有一个唯一 id。前端每次渲染组件的时,通过这个组件 id 向服务器请求组件资源的 URL。
第三步,动态加载组件
动态加载组件有两种方式:
import()
<script>
标签第一种方式实现起来比较方便:
但是兼容性上有点小问题,如果要支持一些旧的浏览器(例如 IE),可以使用
<script>
标签的形式来加载:为了同时支持这两种加载方式,在加载组件时需要判断一下浏览器是否支持 ES6。如果支持就用第一种方式,如果不支持就用第二种方式:
最后一点,打包也要同时兼容这两种加载方式:
同时导出组件和把组件挂在 window 下。
其他小优化
图片镜像翻转
图片镜像翻转需要使用 canvas 来实现,主要使用的是 canvas 的
translate()
scale()
两个方法。假设我们要对一个 100*100 的图片进行水平镜像翻转,它的代码是这样的:ctx.translate(width, 0)
这行代码的意思是把图片的 x 坐标往前移动 width 个像素,所以平移后,图片就刚好在画布外面。然后这时使用ctx.scale(-1, 1)
对图片进行水平翻转,就能得到一个水平翻转后的图片了。垂直翻转也是一样的原理,只不过参数不一样:
实时组件列表
画布中的每一个组件都是有层级的,但是每个组件的具体层级并不会实时显现出来。因此,就有了这个实时组件列表的功能。
这个功能实现起来并不难,它的原理和画布渲染组件是一样的,只不过这个列表只需要渲染图标和名称。
但是有一点要注意,在组件数据的数组里,越靠后的组件层级越高。所以不对数组的数据索引做处理的话,用户看到的场景是这样的(假设添加组件的顺序为文本、按钮、图片):
从用户的角度来看,层级最高的图片,在实时列表里排在最后。这跟我们平时的认知不太一样。所以,我们需要对组件数据做个
reverse()
翻转一下。譬如文字组件的索引为 0,层级最低,它应该显示在底部。那么每次在实时列表展示时,我们可以通过下面的代码转换一下,得到翻转后的索引,然后再渲染,这样的排序看起来就比较舒服了。经过转换后,层级最高的图片在实时列表里排在最上面,完美!
总结
至此,可视化拖拽系列的第四篇文章已经结束了,距离上一篇系列文章的发布时间(2021年02月15日)已经有一年多了。没想到这个项目这么受欢迎,在短短一年的时间里获得了很多网友的认可。所以希望本系列的第四篇文章还是能像之前一样,对大家有帮助,再次感谢!
The text was updated successfully, but these errors were encountered: