图片标注编辑平台搭建系列教程(3)——画布拖拽、缩放实现

简介

标注平台很关键的一点,对于整个图片为底图的画布,需要支持缩放、拖拽,并且无论画布位置在哪里,大小如何,所有绘制的点、线、面的坐标都是相对于图片左上角的,并且,拖拽、缩放,点、线、面的坐标不改变。

要实现这一点,其实就是理解这个画布的坐标系,以及变换矩阵。

画布

fabric.js的底层是canvas绘图。canvas作为画布,要支持拖拽、缩放,就需要有个容器监听鼠标事件。如果我们直接对canvas dom进行拖拽、缩放,有两个缺陷:1是后续只能在最新的canvas范围内进行缩放、拖拽,不易点击;2是dom大小和位置变更,会不断触发浏览器的重绘,性能开销较大,容易卡顿。

为了解决上述问题,我提供以下解决方案:

以一个固定位置的canvas作为画布,拖拽、缩放,只改变canvas的变形矩阵即可transform(a, b, c, d, e, f)。

a:水平方向的缩放;b:竖直方向的倾斜偏移;c:水平方向的倾斜偏移;d:竖直方向的缩放;e:水平方向的移动;f:竖直方向的移动

因此,我们的平移可以通过设置e和f,缩放可以通过设置a和d。

在fabric.js中,可以通过viewportTransform属性,获取这六个参数。然后再通过setViewportTransform方法,设置这六个参数。

居中

画布居中是标注平台必须的功能,因为你拖拽缩放后图像可能偏离视图范围很多,需要快速复原。居中的功能,说起来简单,但是实现还是有一些困难。其原理如下图所示。

首先,获取要标注的图片,宽100,高80,设置canvas的背景图片。

const canvas = new fabric.Canvas(domId, {width: 100,height: 80
}); 
canvas.setBackgroundImage('图片链接');

其次,初始化canvas的为父容器的宽高(100x60),初始化变换矩阵[1,0,0,1,0,0],即平移0,缩放1(不缩放)。

canvas.setDimensions({ width: 100, height: 60 });
canvas.setViewportTransform([1,0,0,1,0,0]);

再次,根据canvas父容器的宽高(100x60),按图像能全展示的比例对canvas视图范围进行等比缩放(0.75),得到新的宽高75x60。即a=0.75,d=0.75。

canvas.setCanvasZoom(0.75);

最后,将canvas视图范围往右平移15,即e=15,f=0。

canvas.setViewportTransform[0.75,0,0,0.75,15,0]

这样,我们的canvas始终是父容器的范围,而viewport范围已经居中。

注意,变换矩阵设置后,还需要执行渲染重置方法,这个是fabric的底层逻辑漏洞,如果不重置,画布上的点线面的位置会偏移。

canvas.renderAndReset();

平移

首先,我们需要监听canvas的mousedown、mousemove、mouseup。

mousedown的回调函数,我们设置全局变量active为true(用于mousemove判断是否需要执行平移),并记录lastX = e.pageX和lastY = e.pageY。

mousemove的回调函数,如果active为true,我们根据e.pageX - lastX和e.pageY - lastY确定横向和纵向的平移量,再通过对transform的e和f进行叠加这个平移量,实现平移功能。

mouseup的回调函数,设置acitve为false。

缩放

监听canvas的wheel,鼠标滚轮事件。

wheel的回调函数,如果e.deltaY > 0,则表示缩小,否则表示放大。缩小,我们对当前的缩放比例统一进行 -0.1,放大统一 +0.1。如果你想更人性化,可以对缩放比例做非线性的变化。

注意点

canvas的缩放,是基于canvas左上角的原点,并非基于平移后的点为原点。因此,需要先将canvas的平移参数置为0后,再设置缩放比例。

另外,我们的缩放,是基于鼠标当前位置为原点进行缩放。如图,红色点处(x, y)进行缩放,视图从v1变到v2,我们已知两个视图对应的缩放比例z1和z2,要求deltaX和deltaY,根据相似定理得:

deltaX = (x - left) * (1 - z2 / z1)

deltaY = (y - top) * (1 - z2 / z1)

newLeft = deltaX + left

newTop = deltaY + top

因此,我们在上一步设置好缩放比例后,执行平移操作(e=newLeft,f=newTop),从而将视图从黑色框缩放至蓝色框。

预告

下一章, 聊聊fabric的几何定制化渲染。

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

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

相关文章

远程技术支持软件方案如何帮助一线客服提升效率?

远程控制在企业远程技术支持体系中,是非常主流的方案,而优秀的远程控制方案本身,就可以非常直观的帮助一线技术支持员工提升效率,降低时间与人力成本,其中向日葵技术支持解决方案就是很好的例子,这里我们来…

厨余垃圾处理设备工业监控PLC连接APP小程序智能软硬件开发之功能原理篇

接着上一篇《厨余垃圾处理设备工业监控PLC连接APP小程序智能软硬件开发之功能结构篇》继续总结一下厨余垃圾处理设备智能软硬件统的原理。所有的软硬件系统全是自己一人独自开发,看法和角度难免有局限性。希望抛砖引玉,将该智能软硬件系统分享给更多有类…

FPGA结构与片上资源

文章目录 0.总览1.可配置逻辑块CLB1.1 6输入查找表(LUT6)1.2 选择器(MUX)1.3 进位链(Carry Chain)1.4 触发器(Flip-Flop) 2.可编程I/O单元2.1 I/O物理级2.2 I/O逻辑级 3.布线资源4.其…

【STM32CubeMX(3)】GPIO上拉输入——读取按键状态

通过本节可以学习到: 如何在CubeMX配置上拉输入什么是上拉输入如何读取一个GPIO的输入状态 软件环境: STM32CubeMX version6.10.0 Keil_v5(MDK-ARM) version 5.32 硬件环境: STM32F103C8T6最小系统板(…

windwos权限维持

1.php 不死马权限维持 <?php ignore_user_abort(); //关掉浏览器&#xff0c;PHP脚本也可以继续执行. set_time_limit(0);//通过set_time_limit(0)可以让程序无限制的执行下去 $interval 5; // 每隔*秒运行 do { $filename test.php; if(file_exists($filename)) { echo…

深入探讨多线程编程:从0-1为您解释多线程(下)

文章目录 6. 死锁6.1 死锁原因 6.2 避免死锁的方法加锁顺序一致性。超时机制。死锁检测和解除机制。 6. 死锁 6.1 死锁 原因 系统资源的竞争&#xff1a;&#xff08;产生环路&#xff09;当系统中供多个进程共享的资源数量不足以满足进程的需要时&#xff0c;会引起进程对2…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 3月29日,星期五

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年3月29日 星期五 农历二月二十 1、 网络表演&#xff08;直播与短视频&#xff09;运营团体标准发布&#xff1a;应建立举报处置机制。 2、 商务部&#xff1a;中国决定终止对澳大利亚进口葡萄酒征收反倾销税和反补贴税。…

编程语言|C语言——数组与指针

一、数组 同一类型的变量——元素&#xff08;element&#xff09;集中在一起&#xff0c;在内存上排列成一条直线&#xff0c;这就是数组&#xff08;array&#xff09;。 1.1 一维数组 一维数组的声明 int arr1[10]; int arr2[2 8];#define N 10 int arr3[N];int count 10;…

深度学习 - PyTorch基本流程 (代码)

直接上代码 import torch import matplotlib.pyplot as plt from torch import nn# 创建data print("**** Create Data ****") weight 0.3 bias 0.9 X torch.arange(0,1,0.01).unsqueeze(dim 1) y weight * X bias print(f"Number of X samples: {len(…

基于资源的约束委派(下)

webclient http self relay Web 分布式创作和版本控制 (WebDAV) 是超文本传输协议 (HTTP) 的扩展&#xff0c;它定义了如何使用 HTTP ( docs.microsoft.com )执行复 制、移动、删除和创建等基本文件功能 需要启用 WebClient 服务才能使基于 WebDAV 的程序和功能正常工作。事实…

全国中学基础信息 API 数据接口

全国中学基础信息 API 数据接口 基础数据&#xff0c;高校高考&#xff0c;提供全国初级高级中学基础数据&#xff0c;定时更新&#xff0c;多维度筛选。 1. 产品功能 2024 年数据已更新&#xff1b;提供最新全国中学学校基本信息&#xff1b;包含全国初级中学与高等中学&…

虚拟现实(VR)项目的开发工具

虚拟现实&#xff08;VR&#xff09;项目的开发涉及到多种工具&#xff0c;这些工具可以帮助开发者从建模、编程到最终内容的发布。以下是一些被广泛认可的VR开发工具&#xff0c;它们覆盖了从3D建模到交互设计等多个方面。北京木奇移动技术有限公司&#xff0c;专业的软件外包…

为什么我的微信小程序 窗口背景色backgroundColor设置参数 无效的问题处理记录!

当我们在微信小程序 json 中设置 backgroundColor 时&#xff0c;实际在电脑的模拟器中根本看不到效果。 这是因为 backgroundColor 指的窗体背景颜色&#xff0c;而不是页面的背景颜色&#xff0c;即窗体下拉刷新或上拉加载时露出的背景。在电脑的模拟器中是看不到这个动作的…

Acwing_795前缀和 【一维前缀和】+【模板】二维前缀和

Acwing_795前缀和 【一维前缀和】 题目&#xff1a; 代码&#xff1a; #include <bits/stdc.h> #define int long long #define INF 0X3f3f3f3f #define endl \n using namespace std; const int N 100010; int arr[N];int n,m; int l,r; signed main(){std::ios::s…

Gitlab 实现仓库完全迁移,包括所有提交记录、分支、标签

1 方案一&#xff1a;命令 cd <项目目录> git fetch --all git fetch --tags git remote rename origin old-origin #可以不保留 git remote add origin http://***(项目的新仓库地址) #git remote set-url origin <项目的新仓库地址> git push origin --all git…

项目管理:项目进度管理的五大关键步骤

作为项目经理&#xff0c;要想做好项目进度管理&#xff0c;可以遵循以下五个关键步骤&#xff1a; 一、确定范围和分解目标 1、明确项目目标&#xff1a;首先&#xff0c;要清晰地定义项目的总体目标和预期成果。 2、范围界定&#xff1a;详细列出项目所需完成的所有任务和…

LDL^H分解求逆矩阵与MATLAB仿真(Right-Looking)

通过分解将对称正定厄米特矩阵分解成下三角矩阵L和对角矩阵D来求其逆矩阵 目录 前言 一、LDL^H基本算法 二、LDL^H Right-Looking算法 三、D矩阵求逆 四、L矩阵求逆 五、A矩阵求逆 六、计算量分析 七、MATLAB仿真 八、参考资料 总结 前言 在线性代数中&#xff0c;LDL…

HarmonyOS入门--配置环境 + IDE汉化

文章目录 下载安装DevEco Studio配置环境先认识DevEco Studio界面工程目录工程级目录模块级目录 app.json5module.json5main_pages.json通知栏预览区 运行模拟器IED汉化 下载安装DevEco Studio 去官网下载DevEco Studio完了安装 配置环境 打开已安装的DevEco Studio快捷方式…

Java中有哪些容器(集合类)?

Java中的集合类主要由Collection和Map这两个接口派生而出&#xff0c;其中Collection接口又派生出三个子接 口&#xff0c;分别是Set、List、Queue。所有的Java集合类&#xff0c;都是Set、List、Queue、Map这四个接口的实现 类&#xff0c;这四个接口将集合分成了四大类&#…

蓝桥杯 - 小明的背包1(01背包)

解题思路&#xff1a; 本题属于01背包问题&#xff0c;使用动态规划 dp[ j ]表示容量为 j 的背包的最大价值 注意&#xff1a; 需要时刻提醒自己dp[ j ]代表的含义&#xff0c;不然容易晕头转向 注意越界问题&#xff0c;且 j 需要倒序遍历 如果正序遍历 dp[1] dp[1 - vo…