js 获取鼠标在画布的位置_云凤蝶如何打造媲美 sketch 的自由画布

a2050b6fb559a093eeb7ae93e0abc669.png

在 Design Tools 中,组件间的对齐与吸附功能是否好用是决定其画布是否可以高效进行产品设计的关键因素。云凤蝶作为一款快速制作高品质中后台应用的 hpaPaaS 平台,同样拥有自由拖拽的可视化画布。那么在云凤蝶的自由画布中,对齐规则是怎样的?实现这些规则的策略是怎样的?规则和策略是否足够完备?最终效果如何?能否媲美 Sketch 等设计软件?这篇文章就来对这些问题进行一一解答。

几个术语

在开始前,先简单介绍几个术语及其在画布中出现时的样式。

48276e15a3d8be128d6edcc647bc158a.png
构成组件的 6 条线

可以看到,一个组件在画布中可以由 6 条线 (vt / vm / vb | hl / hm / hr) 来表示,组件移动过程中的对齐其实就是组件的 6 条线到其它组件线的集合中寻找临近线,找到后考虑 吸附 + 对齐 的过程。

8a1fd958a6c2bb37633cb97acefa0b51.png
对齐线

79b077c09acad8918e62c9716d9cc378.png
间距线

347c66ca394aeb67df465c9fb5d38ab6.png
间距块

以上是组件在移动过程中对齐时出现的几种状态,其中出现 3 个名词,3 种辅助样式:

  • 红色实线代表吸附线
  • 蓝色实线代表距离线
  • 粉色块代表间距块

通用规则

在介绍云凤蝶画布中的对齐规则之前,我们先来直观地看下当下几款不错的设计产品在对齐方面是如何做的。这里主要以 Sketch 和 Figma 这两款设计工具为例,其它如 FramerX、墨刀等也可自行参考,效果大致相同,只是它们在实现上的优化程度略有高低。

Sketch

bb9708ad25bb8caea85a999357ef7ccb.gif
Sketch 对齐

af6aa9894262dfc2954b6d0007d2ed44.gif
Sketch 对齐

在 Sketch 中,以带边框组件的边框中线为基准,在移动过程中不断去找到距离最近的线去对齐。其中

  • 在首次接近某条线时,有一个吸附的过程。如在移动 1px 找到吸附线时,会让组件实际移动 6px,达到吸附效果
  • 当组件在吸附线上时,再次移动时,考虑是否能找到相邻的线,如果可以找到,则移动到下条吸附线上;如果未找到时,则鼠标移动某个距离时,触发移动,有种卡点的感觉,用以辅助对齐;
  • 另外还有比较细节的地方,比如当某一个方向移动吸附到相邻的线后(右图),如果相反方向移动,则非常轻松,而如果继续同一方向继续移动,则需要移动比较大的距离,以此实现了更好的吸附对齐效果。
  • ...

Figma

c8c9f0c8c2937c39a1d240f0862eac4b.gif
Figma 对齐

13bdbeb3919d92202b82627aa80815bd.gif
Figma 对齐

在 Figma 中,功能大致相同,与 Sketch 不同的是组件是以外边框为对齐线,且在组件移动过程中没有距离线的出现的。

提前剧透:这方面云凤蝶会有独特的策略。

对比

以上用最简单的组件移动示例分别展示了 Sketch 和 Figma 这两款设计产品在组件移动时的一个不断对齐的过程,核心主要涉及到

  • 对齐(与哪些组件边框线对齐)
  • 吸附(多少距离内时吸附)
  • 距离(与哪些组件边框线考虑展示距离)
  • 画线(画哪几条线、从哪里出线)

至于它们是如何实现,目前是不了解的,未查找到其完整的策略及算法。但是通过细致的使用,我们可以体验到这些产品中触发不同功能的时机、功能的优化以及顺畅度等等。另外,这些设计工具中还有有很多其它的辅助功能,如精心设计的快捷键、间距块的辅助、可视区域内的防干扰对齐等等,这里没有进行展示,下面在介绍云凤蝶自由画布中的辅助功能时会有介绍。

Sketch 和 Figma 在设计领域已经算是比较上乘的产品了,通过了解它们,我们可以看到当前设计产品中画布较好的的使用体验是怎样的,以此借鉴来优化我们的画布体验。

云凤蝶规则

好了,前置内容铺垫结束,到了云凤蝶画布这里。云凤蝶也有可自由拖拽的画布,还有更丰富的资产支持添加更多样的组件。不过,我们除了支持上述 Design Tools 中两条线的预期偏差对齐吸附,还遵循 Ant Design 设计规范中的 Gutter=(8n)px 的原则,所以云凤蝶画布中组件在对齐吸附时,还需要在几个特殊的无形线(8px / 16px / 24px)处做间距卡点吸附

关于布局、网格单位、栅格等规范,可以参考 Ant Design 官网中 布局 一节进行详细了解。

接下来让我们详细来看下云凤蝶中的规则以及当前已经完成的功能和效果。

对齐吸附

2eb371577ab9a761117dbdea40ec9d03.gif
对齐吸附

当组件朝某一方向移动时,以上图中横向左移动为例,它的 hl / hm / hr 会不断的去查找与这 3 条线相邻最近的线。其中

  • 当没有找到相邻线时,组件跟随鼠标移动;
  • 当初次找到时,组件便移动一个较大距离吸附过去;
  • 当在吸附线上再次移动时,继续查找相邻线,看是否有下一条吸附线
    • 如果有,则移动到下一条吸附线上;
    • 如果没有,则在鼠标移动一定距离后,组件离开;

以上便是组件对齐吸附的时机及规则,这是可自由拖拽画布中最基础的一个吸附对齐能力。

间距吸附

832b06963aef5e5f27c7c55ea9927c67.gif
间距吸附

上文中提到过,在云凤蝶中搭建页面时,组件的摆放要遵循 Ant Design 中 (8n)px 的原则,所以在云凤蝶的自由画布中也要实现组件间距满足要求时的吸附能力。

resize 吸附

2f13258bcfbe83c08ea113ae68fa390f.gif
resize 吸附

resize 吸附的使用场景是在调整组件宽高时,想要与目标组件的某条边线对齐。由上图也可以看到,对于组件的边框对齐,我们是做了内外的一个适配,站在用户搭建使用的角度来,给出对齐提示。

间距块吸附

5396850fd8706bfb8d0b247a4432f414.gif
间距块吸附

间距块的对齐吸附更多的是给到用户一种提示,即横/纵方向上几个组件间满足同等间距。

吸附剪枝

9e7c7e56867f1673892dc4bbd110b4b0.gif
可视区域变化

46a209bd79b95553794d7decdf51bd42.gif
可视区域内组件变化

吸附剪枝主要是解画布中组件太多时组件需要对齐的目标组件太多的问题,该规则依赖于“用户只关心当前画布中组件的对齐”这一假设,减少对齐时的干扰。上动图中主要展示跟随可视区域变化,其内组件数量变化时的剪枝。

另一种吸附剪枝是在组件快速移动时,也要避免一直找线,干扰正常移动,如下图中所示。

8337537b46c27b6dee0349f92aafa8c5.gif
快速移动时的剪枝

快捷键

这里简单举两个与辅助线相关功能的快捷键 command / option | alt。其实看到后面的实现后就会发现,只要有了这套线的逻辑,想实现类似的功能是比较容易的。

f5d275ff6fc30306584fa67f98de66ca.gif
command 键标识组件相对位置

b3c79834120f30cd541f173569c5cce2.gif
option/alt 键标识任意两个组件相对位置

1ddaaf6c8f418090583e5733d1d03adc.gif
command 键移动组件时无吸附对齐

画线原则

baa8bf1014fecdba0aa38e262cc5fc12.png
对齐

一个组件在对齐时,通常情况下出现的线的条数最多是

  • 3 + 3 条 红色的对齐线
  • 2 条 蓝色的距离线(蓝色线永远从移动的组件中线出发)

对于 Label

  • 横向线,label 在上
  • 纵向线,label 在左

规则原因

这里简单解释下,为什么要在画布中实现吸附对齐能力。

首先,可以回归到吸附对齐的作用 -- 弥补用户在精确操作鼠标上的不足。考虑以下场景:当用户试图把一个组件精确摆放到另一个组件旁边时,目标区域只有 1px,当在移动组件时,如何准确摆放到想要的位置?如果没有吸附对齐的能力,要想实现精确摆放是非常难操作的,要么容易重合,要么容易分离。此时,如果有吸附对齐的能力,就有种让“目标区域”变大的效果,当拖拽组件与目标组件两者仅仅相差某个指定范围的像素时,即认为是进入了吸附对齐的范围内,直接把移动组件吸附到目标位置上。与此同时,当组件离开时也会有一个“吸附引力”,即也有一个同等的离开距离,以形成卡点效果。这样,整个对齐操作就比较有控制力了。

同时,这种能力可以让画布中组件的摆放更加高效。依赖于 Ant Design 的 Gutter 设计原则,当我们在画布中进行页面搭建时,可以比较轻松的摆放到更符合设计原则的位置上去,更快速地搭建页面,从而达到提效的目标。

实现策略

当我们总结出自由画布中组件对齐吸附的能力之后,就可以考虑如何实现它。涉及到对齐吸附,一定就涉及到”移动组件“和”目标组件“,下面就从组件移动的角度来大致介绍实现以上规则的一种思路。

存储

在上文中提到,一个组件可以看做是由 6 条线构成的,组件移动过程中的吸附就是这些线之间的对齐关系。所以,首先要做的就是对组件进行线的存储。下面是一种可行的存储数据结构

一条线有自身的 pos、type及其所归属的 Box

// 线的数据结构
interface Line {pos: number;type: LineType;box?: Box | null;
}

一个组件有 6 条线,且冗余存储其 node 及组件实例信息 instance

// 组件的数据结构
interface Box {id: string;vt: Line;vm: Line;vb: Line;hl: Line;hm: Line;hr: Line;node: HTMLElement;instance: ComponentInstance;
}

线的存储可以考虑使用二叉树,普通二叉树可以参考 typescript-collections/src/lib/BSTree.ts,而横纵线可以构造两颗二叉树

// 线的集合
interface Lines {vLines: BSTree;hLines: BSTree;
}
如果你有其它好的思路,可以一起探讨,比如桶

移动

组件的移动,可以考虑两种实现方式

  • H5 Drag And Drop
  • 拖放鼠标事件

其中,H5 DnD 不是移动 HTML 元素,而是将数据对象从一个位置移动到另一个位置。要移动 HTML 元素,必须使用 MouseEvents:

  • mousedown: 选中元素
  • mousemove: 移动元素
  • mouseup: 释放元素
至于为什么会有对 DnD 的误解,可以参考 《Drag & Drop vs. MouseEvents - A misunderstanding》

为了实现更好地拖拽移动效果,我们采用 MouseEvents 的实现方式。决定了如何拖拽以后,接下来就来考虑,如何实现组件的移动。下图展示了鼠标选中组件时的移动位置关系,其中, A 为鼠标 mousedown 时的选中点,B 为鼠标移动后的 mouseup 的释放点,moveX 则表示鼠标的移动距离,也即组件即将横向移动的距离。

15ae7cbf6bdb9754a739979983c5a388.png
鼠标在组件上的移动

找线

线的查找与线的存储数据结构密切相关。在存储时,我们采用的是二叉树,所以找线的过程就变成了在二叉树中查找与某个位置具有某种大小关系的线,具体的找线算法这里不表,只能说根据业务规则尽量找到最优的算法。找线逻辑是整个策略中的关键一环,通过合理的策略找出离当前组件最近的线,只有这样才能保证后面的吸附是正确的。

找线策略在上文对齐吸附中有提到,这里不再赘述。需要说明的是,“离当前组件最近”是需要重点考虑的,因为在横/纵向查找的过程中,3 条线都有可能遇到最近的线,而且还有 Ant Design Gutter 8xpx 原则在这里,所以这里需要综合考虑。

吸附

当通过前置步骤找到了要吸附的线,我们就可以考虑是否将组件进行移动吸附了,这里主要还是要结合找到的”最近的线”。不过需要注意的是,我们不能在找到线时就移动过去,是因为组件移动距离与鼠标移动偏差不一致时可能会带来的抖动。

此外,对于组件在吸附状态下的移动,也是需要做二次找线的,因为当此时可能直接离开当前的引力区域,也可能是移动到下一条吸附线上。

吸附同样是非常关键的一环,处理不好将直接影响到画布的使用体验,处理了上述两方面,理论上就达到一个不错的效果。

分类

在文章开头,给出了几种不同辅助功能的线,在目前的对齐策略中,有以下几种

enum PairType {distance = 'distance', // 距离线alignment = 'alignment', // 对齐线spacing = 'spacing', // 间距线area = 'area', // 间距块
}

无论是对齐线、距离线、间距线还是间距块,都是通过二叉树中一对 Line 构成的 LinePair 画出的

export interface LinePair {source: Line; // 需要对齐的边target: Line; // 可以被对齐的边type: PairType; // 这对线的关系delta: number; // 这对线的偏差duplicate?: Line[]; // 目标对齐线可能包含多条位置相同的边框线或者中间线
}

根据以上数据结构,我们可以对找到的线进行一个分类,标识出一对线的关系及偏差。

画线

在以上步骤中拿到分好类的线,就可以进行画线操作了。通过线的分类及规范的数据结构,我们可以保证各类型线的画线逻辑的纯粹性。然后针对不同类型的线,在画布中用不同的层来实时展示即可。

至于如何实现更高效的画线以及用何种技术手段来实现,则可以仁者见仁了。

总结

本文主要总结了当前云凤蝶自由画布中支持的对齐、吸附、间距、resize、画线等辅助功能以及实现这些功能的整体规则和策略,这些都是自由画布中最基础的能力,也是推导出画布中吸附对齐涉及取值的理论基础。

梳理下来可以看到,要想在自由画布中实现对齐的能力并不难,麻烦的是如何将规则和策略理清楚、提炼和沉淀,从全局的视角和可扩展的角度来实现。最近云凤蝶自由画布中对齐等辅助能力已经根据这些原则进行了 2.0 的升级,从整体使用体验上,组件摆放这件事情已经变得比较容易。

未来

这里罗列几点当前云凤蝶画布中相较于 Design Tools 中还可以优化的地方:

  • 标尺的对齐与吸附(标尺可以看做是只有一条 h / v 方向 height / width 为画布大小的线)
  • 间距块的查找纳入对齐吸附的整体查找策略中(当前是与对齐线、辅助线的查找分开的)
  • 无极缩放,在更小的区域也能优雅地实现想要的操作
  • 揣测用户意图,更“智能”快速的摆放策略

看到上述几点,感觉也不是很难啊,为啥还没做?

是的,主要是因为...

等你来,一起做!

参考

  • Ant Design 布局https://ant.design/docs/spec/layout-cn
  • typescript-collectionshttps://github.com/basarat/typescript-collections/blob/release/src/lib/BSTree.ts
  • H5 Drag And Drophttps://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API
  • MouseEventhttps://developer.mozilla.org/en-US/docs/Web/API/MouseEvent
  • Drag'n'Drop with mouse eventshttps://javascript.info/mouse-drag-and-drop
  • Drag & Drop vs. MouseEvents - A misunderstandinghttps://steffenjahr.de/2016/02/07/drag-drop-vs-mouse-events-a-missunderstanding/
  • Sketchhttps://www.sketch.com/
  • Figmahttps://www.figma.com/

未来已来,时不我待!

云凤蝶招聘前端、Java、PD、设计岗位,未来等你共创!

如果你感兴趣,欢迎联系 chenyu@antfin.com 或 shuai.shao@antfin.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/433515.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux下TI omap芯片 MUX 配置分析(以AM335X芯片为例)

在移植内核的时候,通常会遇到引脚复用(MUX)的配置问题。在现在的Linux内核中,对于TI的ARM芯片,早已经有了比较通用的MUX配置框架。这对于许多TI的芯片都是通用的,这次看AM335X的代码顺手写一下分析&#xf…

是网关吗_智能家居网关功能这么多,你都知道吗?

在科技发达的今天,我们的生活也开始趋向于智能化,智能家居已经迎来了新时代。电动窗帘、扫地机器人、电视、空调等电器都能智联wifi,可是使用的时候得一个个去控制,数量多的话懒癌们肯定嫌麻烦的。所以很多聪明的人都选择安装智能…

一个数据包大小是多少k_算法交流: 6046 数据包的调度机制 【2.6基本算法之动态规划】...

【题目描述】 6046 数据包的调度机制 By OIer14wa随着 Internet的迅猛发展,多媒体技术和电子商务应用日益广泛,Internet上的服务质量(QoS,Qualityof Service)问题已越来越受到重视。网络中采用的数据包调度机制与网络的服务质量 QoS 有着密切的关系。研究表明传统的基于队列的调…

iOS vs. Android,应用设计该如何对症下药?

摘要:从iOS到Android,两大平台应用设计有何不同?又都存在什么样的问题?Android定制性太高,该如何进行UI设计?在CMDN CLUB第28期活动中,咕咚网高级产品经理王磊,从iOS、Android谈起&a…

cs8900a网卡驱动--寄存器

1. CS8900内部有一个4k的RAM用于访问其内部寄存器,称为PacketPage。 2. LineCTL 网卡状态设置 从上图看到,此寄存器的6,7位用于设置网卡的收发使能。8,9位用于设置网卡状态。是10BASE-T还是 AUI。下面这图更详细介绍了8&…

jQuery图表插件 JS Charts

JS Charts 是一款免费的基于javascript的轻量级插件,用JS Charts 绘制图表是很轻松地事,因为你只需要关心客户端的脚本。 Loading...Loading...Loading...Loading...Loading...Loading...Loading...Loading...Loading...Loading...Loading...转载于:https://www.cnb…

使用正则把数字前面的符号替换_正则表达式(一) 基本表达式

定义 正则表达式(Regular Expression)用某种模式去匹配一类字符串的公式,主要用来描述字符串匹配的工具。 匹配文本或字符存在不止一个部分满足给定的正则表达式,这是每一个这样的部分都被称为一个匹配。 匹配分为以下三种类型: 形容词性的匹…

jsp思维导图_2019年经济法基础思维导图

参加2019年初级考试的考生们明天可以打印准考证啦时间:2019.4.26-5.5日(传送门:http://kjbm8.mof.gov.cn/ksbm/usercxzkz.jsp)为了帮助大家快速梳理教材考点,下面蓝星职业教育为大家整理了初级会计职称考试各章节思维导图,希望给大…

海量数据持久层解决方案_爱数AnyBackup重磅发布海量非结构化数据超可用解决方案...

海量非结构化数据有三大备份恢复问题一直没有得到有效解决:备份慢、恢复慢、备份数据不可查询。这三大问题已经对行业数字化转型造成了重大阻碍。今天,AnyBackup Family 7线上发布会——重磅发布海量非结构化数据超可用解决方案。AnyBackup以创新超可用技…

wpf 使子ui元素可视区域不超过父元素_对游戏UI设计的一点思考

UI决定了一个游戏的初体验,甚至决定了玩家的初始留存,甚至可以说决定了一个游戏的品质,虽然看起来是表象的,却是直指游戏核心的。简单讲,玩家认可一款游戏永远都是造型场景好,剧情好,画质棒&…

grpc入门到精通_Spring Cloud 从入门到精通(一)Nacos 服务中心初探

点击上方蓝色“Java精选”,选择“设为星标”技术文章第一时间送达!什么是Nacos?Nacos是阿里巴巴开源的项目,是一个更易于帮助构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos英文全称是Dynamic Naming and Configur…

百度新年贪吃蛇效果

闲来无事&#xff0c;在网上闲逛的时候开到有人说百度蛇年的贪吃蛇logo小游戏不错&#xff0c;于是乎就自己仿照写了一个。&#xff08;注&#xff1a;所有素材都来自百度&#xff09; 效果图 用到的图片 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional…

贝叶斯公式设b_数据分析经典模型——朴素贝叶斯

编辑导语&#xff1a;做过数据分析的人&#xff0c;想必对贝叶斯模型都不会陌生。贝叶斯预测模型是运用贝叶斯统计进行的一种预测&#xff0c;不同于一般的统计方法&#xff0c;其不仅利用模型信息和数据信息&#xff0c;而且充分利用先验信息。通过实证分析的方法&#xff0c;…

Asterisk使用数据库配置方法

安装&#xff1a; 1、安装 unixODBC unixODBC-devel libtool-ltdl libtool-ltdl-devel &#xff0c;为了使asterisk支持数据库存储&#xff08;必须先安装&#xff09; 2、安装 mysql 并设置好 C_INCLUDE_PATH 和 LD_LIBRARY_PATH 3、从 http://www.asterisk.org/downloads 下载…

linux文件系统_Linux的文件系统简介

inux操作系统的本质可以说就是文件系统的集合&#xff0c;文件系统既包含文件的数据也包含文件系统的结构。在Linux文件系统中&#xff0c;EXT2文件系统、虚拟文件系统、/proc文件系统是三个具有代表性的文件系统。/proc文件系统是一个伪文件系统&#xff0c;它只存在内存当中&…

删除按钮_汪涵拜师学艺第七篇:往来单位查询删除按钮和新增判断的设计!

老师好&#xff01;大家好&#xff01;我叫汪涵&#xff1a;今天给大家分享往来单位查询删除按钮和新增判断的设计&#xff01;在开始具体内容之前&#xff0c;请让我先分享我们的价值观&#xff1a;用自律和勤奋来改变命运&#xff0c;不走捷径&#xff0c;有爱心&#xff0c;…

Ubuntu 12.04(32位)安装Oracle 11g(32位)全过程以及几乎所有问题的解决办法

这两天在Ubuntu上安装Oracle把人折腾毁了&#xff0c;即使照着网上的教程来&#xff0c;还是出了很多问题。好在最后终于搞定了。写出来总结一下&#xff0c;免得以后忘了。 标题注明32位是因为网上教程几乎全是以64位安装为例的&#xff0c;32位系统下照着做是绝对会安装失败的…

解决asterisk sip呼叫 488 no acceptable here

这两天实验了一下asterisk static realtime方案&#xff0c;将sip.conf的信息保存到mysql数据库里。但是呼叫的时候&#xff0c;总是 报 488 no acceptable here。 这是我的sip.conf文件&#xff0c;数据库里和sip.conf文件一模一样&#xff0c;但是就是不行。 [general] c…

关于浏览器模式和文本模式的困惑

什么是浏览器模式和文本模式&#xff1f; 经常使用IE开发者工具的同学&#xff0c;肯定见过浏览器模式和文本模式&#xff0c;对于这两个名词&#xff0c;综合相关文档解释如下&#xff1a; 浏览器模式&#xff08;Browser Mode&#xff09;&#xff0c;用于切换IE针对该网页的…

mysql 关联索引_mysql中关于关联索引的问题——对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引?...

情况描述&#xff1a;在MySQL的user表中&#xff0c;对a,b,c三个字段建立联合索引&#xff0c;那么查询时使用其中的2个作为查询条件&#xff0c;是否还会走索引&#xff1f;根据查询字段的位置不同来决定&#xff0c;如查询a, a,b a,b,c a,c 都可以走索引的&#…