图形编辑器开发:以光标位置缩放画布

这篇具有很好参考价值的文章主要介绍了图形编辑器开发:以光标位置缩放画布。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

画布缩放是图形设计工具中很重要的基础能力。

通过它,我们可以像举着一台摄影机,在图形所在的世界到处游逛,透过镜头,可以只看自己想看的图形;可以拉近摄影机,看到图形的细节;也可以拉远摄影机,总览多个图形之间的关系。

ok,那么我们看看如何实现缩放画布功能。

文中的动图演示来自我正在开发的图形设计工具:

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

线上体验:

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

场景坐标系和视图坐标系

场景坐标系 就是图形所在的二维平面世界,所使用的坐标系。单位是像素(px)。坐标系的原点在画布(canvas 元素)的左上角,x 轴向右,y 轴向下。

图形会被绘制到这个平面,理论上它的范围是可以 无限延展 的。(不过实际上我们会给一个上限,但这个值也非常大。无限大的话没有意义,且浮点数是取值范围的)

然而显示器的宽高是有限的,只能看一个矩形范围内的内容。

所以我们需要引入一个 “摄影机”:视图坐标系,只看部分的区域。

图形编辑器开发:以光标位置缩放画布

其实就是将原来真实的图形的坐标做一个线性计算。

首先是将特定区域 移动 到视口中,就像摄影机从原点移动我们想要观察的某个物体上。不过实际上是物体所在的平面做了一个方向的移动。

图形编辑器开发:以光标位置缩放画布

然后再做一个缩放,就像摄影机拉近或远离与目标物体距离,效果是物体在镜头下变大或变小。

图形编辑器开发:以光标位置缩放画布

转换就两步,移动然后缩放

视图矩阵转换

场景坐标系到视图坐标系的转换,我们通过 视图矩阵 相乘来实现。

事实上,任意两个坐标系下坐标的转换,都可以通过一个矩阵乘法来实现。

关于矩阵和矩阵乘法,可以看我的这篇文章

《计算机图形学:变换矩阵》

首先是将坐标进行位移,x 方向位移 -viewport.x,y 方向位移 -viewport.y。这里是负数,虽然我们想要移动 “摄影机”这是因为移动的是画布

<平移矩阵> * 坐标

然后再缩放(缩放值我们会用 zoom 表示):

<缩放矩阵> * 平移后的坐标

所有过程写在一起,就是:

<缩放矩阵> * <平移矩阵> * 坐标

矩阵乘法符合结合律,所以我们的视图矩阵为:

  <视图矩阵>
= <缩放矩阵> * <平移矩阵>

矩阵表示为:

图形编辑器开发:以光标位置缩放画布

计算结果为:

图形编辑器开发:以光标位置缩放画布

对应的 Canvas 2D 代码:

ctx.scale(zoom, zoom);
ctx.translate(-viewport.x, -viewport.y);

写成一个方法:

// 场景坐标转视图坐标
function sceneCoordsToViewport(x, y, zoom, scrollX, scrollY) {
  return {
		x: (x - scrollX) * zoom,
		y: (y - scrollY) * zoom
  };
}

至于反过来,场景坐标系转视图坐标,计算它的逆矩阵即可:

图形编辑器开发:以光标位置缩放画布

以光标为中心缩放

图形编辑器开发:以光标位置缩放画布

首先我们来认清本质,所谓以光标为中心缩放,不变的是什么?

光标所在点在视图坐标系距离视口左上角的相对位置,保持不变

我们要做的事是,在 zoom 变化后,调整 viewport.x 和 viewport.y 的值,让光标在视图坐标系上相对视口左上角距离不变。

这里得补充一个知识点。就是两个坐标系中距离的转换:

  1. 场景转视图,距离转换为 dist * zoom
  2. 视图转场景,距离的转换是 dist / zoom。因为视口看到的图形都是缩放(乘以 zoom)后的结果,所以反过来就要除回去。

实现思路是:

  1. 记录好缩放前,光标所在位置的场景坐标;
  2. 计算 (cx, cy) 在旧缩放比(zoom)的场景坐标。
  3. 计算 cx 在新的缩放比(zoom)下,(cx / zoom, cy / zoom)
  4. 然后二者相减,即可得到新的适口左上角坐标。

图形编辑器开发:以光标位置缩放画布

代码实现为:

/**
 * 以某点为中心,进行画布缩放
 * @param {number} zoom 新的缩放比
 * @param {number} cx 缩放中心(使用视图坐标)
 * @param {number} cy
 */
const setZoomAndUpdateViewport = (zoom, cx, cy) => {
  const prevZoom = this.zoom;
  this.zoom = zoom;

  // 计算缩放中点的场景坐标
  const { x: sceneCX, y: sceneCY } = viewportCoordsToScene(
    cx,
    cy,
    prevZoom,
    this.viewport.x,
    this.viewport.y,
  );

  // 核心代码
  const newViewportX = sceneCX - cx / zoom;
  const newViewportY = sceneCY - cy / zoom;

  this.viewport.x = newViewportX;
  this.viewport.y = newViewportY;

  this.renderScene();
};

以画布为中心进行缩放

如果缩放时光标不在画布上,比如通过手动输入缩放值时,会 以画布的中心位置进行缩放

实现同上,只是 cx 和 cy 改成传入视口(即画布)的宽高除以 2:(viewport.width / 2), (viewport.height / 2)

图形编辑器开发:以光标位置缩放画布

结尾

要实现画布缩放,重点是理解场景坐标和视图坐标之间的关系。

场景坐标转视图坐标,首先需要将画布进行移动,让场景坐标的原点和视图坐标的原点对上(场景坐标移动 -viewport.x 和 -viewport.x),然后再进行缩放(乘以 zoom)。

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

到了这里,关于图形编辑器开发:以光标位置缩放画布的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

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

    大家好,我是前端西瓜哥。 对于一个图形设计软件,它最基础的工具是什么? 选择工具 。 但这个选择工具,却是相当的复杂。这次我来和各位,细说细说选择工具的一些弯弯道道。 我正在开发的图形设计工具的: https://github.com/F-star/suika 线上体验: https://blog.fstars.wang/ap

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

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

    2024年02月15日
    浏览(32)
  • 基于fabric.js的图片编辑器, 画布背景实现原理

    使用了element-plus提供的图片上传 el-upload 组件 图片上传支持两种元素,普通图片元素和背景图片元素,所以定义属性type进行区分 type为 Image 为普通图片, background 为背景 背景也是一张图片,使用fabric.Image创建图片元素 因为没有图片服务器所以把上传的文件转换了base64图片,作为f

    2024年02月02日
    浏览(36)
  • C语言 实现带透明度的鼠标光标 .cur 编辑器

    操作参考:  .cur 鼠标光标编辑器-CSDN博客 增加了滑块修改透明度 有一个bug,就是取色在绘图板上取色时,取到的颜色的透明度是0,也就是说,同样的颜色,有的是透明出来的,有的就是本身的颜色。但是不打算改了,这样的具有启发的BUG就留作纪念,如果想取色带透明度,

    2024年04月27日
    浏览(26)
  • Linux :: vim 编辑器:详解:光标移动定位内容,行间:快速定位至文本:开头 / 结尾;行内:词间跳跃

    前言:本篇是 Linux 基本操作篇章的内容! 笔者使用的环境是基于腾讯云服务器:CentOS 7.6 64bit。 学习集: C++ 入门到入土!!!学习合集 Linux 从命令到网络再到内核!学习合集 前言:已讲述了 vim 的基本操作,本文不再赘述直接上手操作! Linux :: 【简单开发篇 :: vim 编辑器:

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

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

    2024年02月01日
    浏览(40)
  • 【Java AWT 图形界面编程】使用鼠标滚轮缩放 Canvas 画布中绘制的背景图像 ( 绘制超大图像 + 鼠标拖动 + 鼠标滚轮缩放 + 以当前鼠标指针位置为缩放中心 示例 )

    鼠标指针指向界面中的 Canvas 画布某个位置 , Canvas 画布中绘制着一张超大图片 , 以该位置为中心 , 滑动鼠标滚轮时进行缩放 ; 使用鼠标滚轮缩放后 , 在 Canvas 中绘制的图片的尺寸肯定是放大或者缩小了 , 尺寸发生了改变 ; 图片缩放时 , 鼠标指针指向一个位置 , 该位置对应着一

    2024年02月15日
    浏览(26)
  • 【vim进阶】vim编辑器的分屏操作(分屏显示文件,关闭分屏,分屏间光标的移动,移动分屏)

    VIM 可以实现分屏操作,一个屏幕被多个文件给分占,有左右和上下两种分屏的方式。 左右分屏如下操作: n是数字,表示分屏的数量,n要大于等于文件个数 上下分屏如下操作: 这个命令跟上一个命令不同的是其中的参数 -on( n 是要打开的具体文件的数目:1,2,3 …) 中的 o

    2024年02月14日
    浏览(31)
  • Vue3 中vue-quill富文本编辑器图片缩放

     导包   添加配置   注: 该编辑器已经不在维护了,很古老了,打包后如果报错,建议使用其他编辑器

    2024年04月25日
    浏览(31)
  • vue3富文本编辑器vue-quill-editor、图片缩放ImageResize详细配置及使用教程

    官网地址:https://vueup.github.io/vue-quill/ 效果图  1、安装 2、在vue.config.js中添加配置,否则quill-image-resize-module会出现Cannot read property ‘imports‘ of undefined报错问题 3、创建quillTool.js(用于添加超链接、视频) 4、完整代码

    2024年02月04日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包