图形编辑器开发:最基础但却复杂的选择工具

这篇具有很好参考价值的文章主要介绍了图形编辑器开发:最基础但却复杂的选择工具。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

大家好,我是前端西瓜哥。

对于一个图形设计软件,它最基础的工具是什么?选择工具

但这个选择工具,却是相当的复杂。这次我来和各位,细说细说选择工具的一些弯弯道道。

我正在开发的图形设计工具的:

https://github.com/F-star/suika

线上体验:

https://blog.fstars.wang/app/suika/

单选

最基本的,要做到单个图形的选中。

光标停留在图形上方,按下鼠标左键,这个图形就被选中了。这就是一个简单的选中了单个图形的场景。

注意必须是 mousedown,不是 click。后面会说为什么。

在代码层,我们会使用 “图形拾取” 算法确定光标落在哪个图形的点击区域上,注意考虑隐藏、锁定、组的情况。

如果你对图形拾取的细节感兴趣,可以看我的这篇文章:

《如何在 Canvas 上实现图形拾取?》

隐藏和锁定的图形会被忽略,如果点的是组下的一个元素,要将整个组的所有元素都选中。

清空 被选中图形集合(暂且叫做 selectSet),然后把这个图形添加进去。

selectSet.clear()
selectSet.add(targetEl)

选中集合保存的是被选中的图形,可以保存 id,也可以是图形对象。

在渲染层,会对被选中的图形进行轮廓高亮,让用户有感知。

此外还会有一个 矩形选中框,上面还会有控制点,让用户可以缩放和旋转图形。

选中框是图形的包围盒,通常是 带旋转的 OBB 包围盒

如果点击到空白区域,要将 selectSet 清空。

图形编辑器开发:最基础但却复杂的选择工具

多选

有时候我们希望选中出多个图形。

通常的做法是,按住 Shift 键,然后点击一个图形。

同时也要 支持取消选中:原来被选中的一个图形,我按住 Shift 再

代码的核心逻辑是:

如果这个图形不在 selectSet 中,将其加入;如果这个图形在 selectSet,将其移除

if (event.shiftKey) {
  if (selectSet.has(targetEl)) {
    selectSet.delete(targetEl)
  } else {
    selectSet.add(targetEl)
  }
}

多个图形被选中了,除了给它们高亮轮廓线,我们还需要用一个更大的矩形选中框包裹所有被选中图形

一个小点:如果是取消选中的逻辑,需要鼠标释放后才更新 selectSet。因为要防止和后面会说的按住 Shift 水平垂直拖拽冲突。

图形编辑器开发:最基础但却复杂的选择工具

框选

框选,提供了 一次性选中大量特定区域内图形 的能力。

在空白区域按下鼠标拖拽,然后释放,可以构造出一个矩形,这个矩形我们称为 “选区”。

图形编辑器开发:最基础但却复杂的选择工具

选区矩形会和图形进行碰撞检测判断,决定将哪些图形是被框选中的。

碰撞检测有三种方案:

  1. 选区矩形和选中图形的包围盒属于 包含(contain)关系
  2. 选区矩形和选中图形的包围盒属于 相交(intersect)关系
  3. 不使用包围盒,精准判断是否有真正的 像素上的相交

个人比较推荐相交的判断方案,figma 也选择了该方案。

如果你对碰撞检测的细节感兴趣,可以看我之前写的文章:

《图形编辑器——矩形选区是如何实现选中多个图形的?》

《几何算法:矩形碰撞和包含检测算法》

框选可以和多选结合。即你可以按住 Shift 键,然后去框选。

它的效果是和按住 Shift 一个个去选中图形的效果是一样的。

核心代码实现:

if (!event.shiftKey) {
  selectSet.clear();
}

for (const el of elementsInScence) {
  // 判断是否碰撞,这个方法
  if (isRectIntersect(selectionBox, el)) {
    // 普通框选
    if (!event.shiftKey) {
      selectSet.add(el);
    }
    // 连续和框选的组合
    else {
      if (selectSet.has(el)) {
        selectSet.delete(el);
      } else {
        selectSet.add(el);
      }
    }
  }
}

移动

选择工具,主要是用来选择,选中后一个很普遍的操作是:移动选中元素

所以这也是它有时候也被叫做 移动工具 的原因。

移动的交互过程:

  1. 光标停留在已经被选中的图形上,按下鼠标不放;
  2. 然后拖拽鼠标,被选中图形跟随光标移动;
  3. 释放鼠标,表示移动到目标位置,移动结束。

图形编辑器开发:最基础但却复杂的选择工具

代码核心实现:

  1. 移动前此时记录图形的位置,和起始位置;
  2. 拖拽时计算相对位移,更新图形的位置;
  3. 释放时重置状态,以及记录到历史记录中。
// 图形移动前位置
let elStartCoords = [];
// 鼠标按下事件的光标位置,计算偏移量时作为基准
let startCoord = { x: undefined, y: undefined };

const onStart = (e) => {
  // 记录初始坐标
  elStartCoords = elements.map((el) => ({ x: el.x, y: el.y }));
  startCoord.x = e.clientX;
  startCoord.y = e.clientY;
};

const onDrag = (e) => {
  // 计算偏移量,更新坐标
  const dx = e.clientX - startCoord.x;
  const dy = e.clientY - startCoord.y;
  elements.forEach((el, i) => {
    el.x = elStartCoords[i].x + dx;
    el.y = elStartCoords[i].y + dy;
  });
};

const onEnd = () => {
  // 重置状态
  elStartCoords = [];
  startCoord = { x: undefined, y: undefined };
};

按住 Shift 键的垂直水平移动

假设我们做好了几个对齐的图形,当我们移动其中一个图形的时候,希望能够保持原来的对齐。

这时候,限制移动为水平或垂直方向就很有用。

通常通过在拖拽时按住 Shift 来开启这个能力。

图形编辑器开发:最基础但却复杂的选择工具

要点:

  1. 拖拽的中途从没按住 Shift 到按住,要立即响应,代码实现上要补一个键盘事件监听,而不是靠鼠标移动事件,因为你不移动鼠标,被选中元素就不会更新。
  2. 比较 dx 和 dy 的大小。dx 大,水平移动;dy 大,垂直移动。这样图形就能尽量靠近十字线(水平线+垂直线)

对齐到像素网格

对齐到网格,开启后,让图形在移动的时候,让图片尽量贴到网格线上。

图形编辑器开发:最基础但却复杂的选择工具

做法是将一个或多个图形的包围盒(AABB)的左上角坐标,进行取余,得到一个落在网格线上的位置,用这位置去更新选中图形。

扩展能力:控制点

选中图形,是为了对它们进行操作。

这些 操作的实现,要通过控制点来落地

常见的有:

  • 缩放控制点,在图形选中框的 4 个角上;

  • 旋转控制点,拖拽它设置图形的旋转,旋转控制点;

  • 给图形设置渐变填充色,需要指定两种颜色的颜色和位置,需要的 渐变色控制点

下面是 figma 的缩放和旋转演示,我开发的编辑器还没实现完整。

图形编辑器开发:最基础但却复杂的选择工具

此外,不同图形绘制工具可能会有它们独有的操作方式,这些都需要你根据图形的特性去设计。

看看 Figma 对不同图形的特殊控制点逻辑。

图形编辑器开发:最基础但却复杂的选择工具

所以选择工具模块在设计上,要提供 注册各种类型图形控制点逻辑 的能力。

在 “图形拾取” 时,要把控制点也考虑进来,光标是否点在控制点上。

如果点在控制点上,拖拽逻辑就要走控制点的逻辑,不再走选择工具的基础逻辑。

其他

还有一些可考虑实现的增强能力:

  • 双击,进入编辑模式,进行一些更复杂的操作,比如可以变成贝塞尔曲线操作任意点。
  • 移动时,用线条显示和其他图形的点(比如中点、选中框角落的 4 个点)的距离,并在很接近时吸附过去。

结尾

总结一下,选择工具,是一款图形设计软件最基础的功能。

它的作用是选中的图形,对它们进行操作,目的是 更新指定图形属性

最基础的操作是移动,接着是通过控制点实现的增强操作。

控制点操作的两个基本能力是旋转和缩放。然后我们会根据不同类型的图形,去实现不同的控制点逻辑。

说是工具的一种,但它其实的定位更多是底层的基础建设。

我是前端西瓜哥,欢迎关注我,学习更多图形开发知识。文章来源地址https://www.toymoban.com/news/detail-487012.html

到了这里,关于图形编辑器开发:最基础但却复杂的选择工具的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 图形编辑器开发:是否要像 Figma 一样上 wasm

    大家好,我是前端西瓜哥。 wasm 拿来做 Web 端的图形编辑器貌似是不错的选择。 因为图形处理会有相当多无法利用到 WebGL GPU 加速的 CPU 密集的计算。比如对一条复杂贝塞尔曲线进行三角化,对多个图形进行复杂图形的布尔运算。 图形编辑器性能天花板 Figma 用了 wasm,我们也

    2024年02月15日
    浏览(39)
  • C#时间轴曲线图形编辑器开发2-核心功能实现

    目录 三、关键帧编辑 1、新建Winform工程 (1)界面布局  (2)全局变量 2、关键帧添加和删除 (1)鼠标在曲线上识别 (2)键盘按键按下捕捉 (3)关键帧添加、删除  (4)修改关键帧值 3、曲线插值 (1)三次样条插值 (2)工程代码下载链接 四、曲线数据导出和读取 1、数

    2024年02月15日
    浏览(48)
  • Python零基础教程6——编辑器的选择(IDLE?Visual Studio Code?PyCharm?Anaconda?)

    上一节课是1-5节课复盘 大家无论之前有没有看过 都对前面的知识有了一定的了解 我在其中提到我的2023年总结 没人评论的事 没想到真有热心肠的小伙伴帮忙 再次感谢! 有评必回呀,互动起来! 这节课就是复盘之后产生的 遂 更加贴合实际! 在我们熟悉了一定的编程之后 我

    2024年01月25日
    浏览(66)
  • 【Linux环境基础开发工具】编辑器-vim

    vim是一个编辑器,是在Linux下编程的常用工具,如果要学习在Linux下的编程, 那学会使用vim是一个必修课,今天我就来讲解如何使用vim编辑器。 目录 写在前面 什么是vim vim的常用命令 (1)gg:定位光标到第一行第一个位置 (2)shift + g:定位光标到最后一行 (3)n + shift + g:

    2024年02月07日
    浏览(54)
  • 图形编辑器:历史记录设计

    大家好,我是前端西瓜哥。今天讲一下图形编辑器如何实现历史记录,做到撤销重做。 其实就是版本号的更替。每个版本保存一个状态。 要记录图形编辑器的历史记录,支持撤销重做功能,需要两个栈: 撤销(undo)栈和重做(redo)栈 。 每当用户进行一个操作(比如移动一

    2024年02月01日
    浏览(54)
  • Yjs + Quill 实现文档多人协同编辑器开发(基础+实战)

            感谢大家对文章的关注哈,大家提出的无法在不同浏览器协同的问题,经过两天多的学习研究,终于是解决了。目前版本已经正常提到 git 上了, 运行脚本:npm run startServer,是通过WebRTC 的形式实现协同(该方案仅支持内网系统,因为webRTC在外网使用需要stun 服务支

    2024年02月10日
    浏览(56)
  • Sprite Editor图片编辑器的使用_unity基础开发教程

    SpriteEditor是Unity引擎中的一个工具,用于创建和编辑2D图片。它提供了一系列功能,可以对图片进行剪裁、切割、翻转、旋转、调整大小等操作,以及设置图片的碰撞检测形状和渲染模式。 SpriteEditor可以帮助开发者将多张图片合并成动画精灵,并为每一帧设置播放时间和循环

    2024年02月01日
    浏览(44)
  • Visual Studio连接unity编辑器_unity基础开发教程

    当我们在unity编辑器中打开C#脚本的时候发现Visual Studio没有连接unity编辑器,在编写代码的时候也没有unity的提醒。 简单来说就是敲代码没有代码提示。 这时候需要在unity中进行设置,与Visual Studio进行连接 在unity编辑器中,选择Edit,点击Preference 在Preference窗口中选择

    2024年02月04日
    浏览(55)
  • 简版的富文本编辑器、VUE+ElementUI 富文本编辑器 element ui富文本编辑器的使用(quill-editor) 不好用你来打我!全网醉简单!要复杂的别来!

    实现效果   1.安装插件 npm install vue-quill-editor --save 2.安装成功后在package.json中查看 3.在main.js中全局引入插件 4.页面实现 感谢老哥: ElementUI生成富文本编辑器 https://blog.csdn.net/keplerm/article/details/123379511?spm=1001.2101.3001.6650.9utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCom

    2024年02月16日
    浏览(73)
  • 编辑器的新选择(基本不用配置)

    不用看网上那些教程Cline几乎不用配置。 点击设置直接选择Chinese, C++直接在选择就行了。 Cline是一个很好的编辑器,有很多懒人必备的功能。 这是一个 根本不用配置 的C++编辑器。  旁边有目录,而且配色也很好,语言标准可以自己选择。 但有一个缺点就是如果编辑时有问题

    2024年02月20日
    浏览(40)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包