Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

2020-03-18 0 553

哈哈哈俺又来啦,这次带来的是canvas实现一些画布功能的文章,希望大家喜欢!

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

前言

因为也是大三了,最近俺也在找实习,之前有一个自己的小项目:

https://github.com/zhcxk1998/School-Partners

面试官说可以往深层次思考一下,或许加一些新的功能来增加项目的难度,他提了几个建议,其中一个就是 试卷在线批阅,老师可以在上面对作业进行批注,圈圈点点等 俺当天晚上就开始研究这个东东哈哈哈,终于被我研究出来啦!

采用的是 canvas 绘制画笔,由css3的 transform 属性来进行平移与缩放,之后再详细介绍介绍

(希望大家可以留下宝贵的赞与star嘻嘻)

效果预览

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

动图是放cdn的,如果访问不了,可以登录在线尝试尝试: test.algbb.cn/#/admin/con…

公式推导 如果不想看公式如何推导,可以直接跳过看后面的具体实现~ 1. 坐标转换公式 转换公式介绍

其实一开始也是想在网上找一下有没有相关的资料,但是可惜找不到,所以就自己慢慢的推出来了。我就举一下横坐标的例子吧!

通用公式

这个公式是表示,通过公式来将鼠标按下的坐标转换为画布中的相对坐标,这一点尤为重要

(transformOrigin – downX) / scale * (scale-1) + downX – translateX = pointX

参数解释

transformOrigin: transform变化的基点(通过这个属性来控制元素以哪里进行变化)
downX: 鼠标按下的坐标(注意,用的时候需要减去容器左偏移距离,因为我们要的是相对于容器的坐标)
scale: 缩放倍数,默认为1
translateX: 平移的距离

推导过程

这个公式的话,其实就比较通用,可以用在别的利用到 transform 属性的场景,至于怎么推导的话,我是用的笨办法

具体的测试代码,放在文末,需要自取~

1. 先做出两个相同的元素,然后标记上坐标,并且设置容器属性 overflow:hidden 来隐藏溢出内容

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

ok,现在就有两个一样的矩阵啦,我们为他标记上一些红点,然后我们对左边的进行css3的样式变化 transform

矩形的宽高是 360px * 360px 的,我们定义一下他的变化属性,变化基点选择正中心,放大3倍

得到如下结果

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

ok,我们现在对比一下上面的结果,就会发现,放大3倍的时候,恰好是中间黑色方块占据了全部宽度。接下来我们就可以对这些点与原先没有进行变化(右边)的矩形进行对比就可以得到他们坐标的关系啦

2. 开始对两个坐标进行对比,然后推出公式

现在举一个简单的例子吧,例如我们算一下左上角的坐标(现在已经标记为黄色了)

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

其实我们其实就可以直接心算出来坐标的关系啦

这里左边计算坐标的值是我们鼠标按下的坐标

这里左边计算坐标的值是我们鼠标按下的坐标

这里左边计算坐标的值是我们鼠标按下的坐标

因为宽高是 360px ,所以分成3等份,每份宽度是 120px 因为变化之后容器的宽高是不变的,变化的只有矩形本身 我们可以得出左边的黄色标记坐标是 x:120 y:0 ,右边的黄色标记为 x:160 y:120 (这个其实肉眼看应该就能看出来了,实在不行可以用纸笔算一算)

这个坐标可能有点特殊,我们再换几个来计算计算(根据特殊推一般)

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

蓝色标记:左边: x:120 y:120 ,右边: x: 160 y:160 绿色标记:左边: x: 240 y:240 ,右边: x: 200: y:200

好了,我们差不多已经可以拿到坐标之间的关系了,我们可以列一个表

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

还觉得不放心?我们可以换一下,缩放倍数与容器宽高等进行计算

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

不知道大家有没有感觉呢,然后我们就可以慢慢根据坐标推出通用的公式啦

(transformOrigin – downX) / scale * (scale-1) + down – translateX = point

当然,我们或许还有这个 translateX 没有尝试,这个就比较简单一点了,脑内模拟一下,就知道我们可以减去位移的距离就ok啦。我们测试一下

我们先修改一下样式,新增一下位移的距离

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

还是我们上面的状态,ok,我们现在蓝色跟绿色的标记还是一一对应的,那我们看看现在的坐标情况

蓝色:左边: x:0 y:0 ,右边: x:160 y:160 绿色:左边: x:120 y:120 ,右边: x:200 y:200

我们分别运用公式算一下出来的坐标是怎么样的 (以下为经过坐标换算)

蓝色:左边: x:120 y:120 ,右边: x:160 y:160 绿色:左边: x:160 y:160 ,右边: x:200 y:200

不难发现,我们其实就相差了与位移距离 translateX/translateY 的差值,所以,我们只需要减去位移的距离就可以完美的进行坐标转换啦

测试公式

根据上面的公式,我们可以简单测试一下!这个公式到底能不能生效!!!

我们直接沿用上面的demo,测试一下如果元素进行了变化,我们鼠标点下的地方生成一个标记,位置是否显示正确。看起来很ok啊(手动滑稽)

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

可能有人会问,为什么要减去这个 offsetLeftoffsetTop 呢,因为我们上面反复强调,我们计算的是鼠标点击的坐标,而这个坐标还是相对于我们展示容器的坐标,所以我们要减去容器本身的偏移量才行。

组件设计

既然demo啥的都已经测试了ok了,我们接下来就逐一分析一下这个组件应该咋设计好呢(目前仍为低配版,之后再进行优化完善)

1. 基本的画布构成

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

我们先简单分析一下这个构成吧,其实主要就是一个画布的容器,右边一个工具栏,仅此而已

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

大体就这样子啦!

我们唯一需要的一点就是,容器需要设置属性 overflow: hidden 用来隐藏内部canvas画布溢出的内容,也就是说,我们要控制我们可视的区域。同时我们需要动态获取容器宽高来为canvas设置尺寸

2. 初始化canvas画布与填充图片

我们可以弄个方法来初始化并且填充画布,以下截取主要部分,其实就是为canvas画布设置尺寸与填充我们的图片

3. 监听canvas画布的各种鼠标事件

这个控制移动的话,我们首先可以弄一个方法来监听画布鼠标的各种事件,可以区分不同的模式来进行不同的事件处理

4. 实现画布移动

这个就比较好办啦,我们只需要利用鼠标按下的坐标,和我们拖动的距离就可以实现画布的移动啦,因为涉及到每次移动都需要计算最新的位移距离,我们可以定义几个变量来进行计算。

这里监听的是容器的鼠标事件,而不是canvas画布的事件,因为这样子我们可以再移动超过边界的时候也可以进行移动操作

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

简单的总结一下:

传入鼠标按下的坐标 计算当前位移距离,并更新css变化效果 鼠标抬起时更新最新的位移状态

5. 实现画布缩放

画布缩放我主要通过右侧的滑动条以及鼠标滚轮来实现,首先我们再监听画布鼠标事件的函数中加一下监听滚轮的事件

总结一下:

监听鼠标滚轮的变化 更新缩放倍数,并改变样式

接着我们使用hooks的副作用函数,依赖于画布缩放倍数来进行样式的更新

6. 实现画笔绘制

这个就需要用到我们之前推导出来的公式啦!因为呢,仔细想一下,如果我们缩放位移之后,我们鼠标按下的位置,他的坐标可能就相对于画布来说会有变化, 所以我们需要转换一下才能进行鼠标按下的位置与画布的位置一一对应的效果

稍微总结一下:

传入鼠标按下的坐标 通过公式转换,开始在对应坐标下绘制 鼠标抬起时,取消事件监听

7. 橡皮擦的实现

橡皮擦目前还有点问题,现在的话是通过将 canvas 画布的背景图片 + globalCompositeOperation 这个属性来模拟橡皮擦的实现,不过,这时候图片生成出来之后,橡皮擦的痕迹会变成白色,而不是透明

此步骤与画笔实现差不多,只有一点点小变动

设置属性 context.globalCompositeOperation = "destination-out"

8. 撤销与恢复的功能实现

这个的话,我们首先需要了解常见的撤销与恢复的功能的逻辑 分几种情况吧

若当前状态处于第一个位置,则不允许撤销 若当前状态处于最后一个位置,则不允许恢复 如果当前撤销了,然而更新了状态,则取当前状态为最新的状态(也就是说不允许恢复了,这个刚更新的状态就是最新的)

画布状态的更新

所以我们需要设置一些变量来存,状态列表,与当前画笔的状态下标

我们还需要在初始化canvas的时候,我们就添加入当前的状态存入列表中,作为最先开始的空画布状态

然后我们就实现一下,画笔更新时候,我们也需要将当前的状态添加入 画笔状态列表 ,并且更新当前状态对应的下标,还需要处理一下一些细节

总结一下:

鼠标抬起时,获取当前canvas画布状态 添加进状态列表中,并且更新状态下标 如果当前处于撤销状态,若使用画笔更新状态,则将当前的最为最新的状态,原先位置之后的状态全部清空

画布状态的撤销与恢复

ok,其实现在关于画布状态的更新,我们已经完成了。接下来我们需要处理一下状态的撤销与恢复的功能啦

我们先定义一下这个工具栏吧

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

然后我们设置对应的事件,分别是撤销,恢复,与清空,其实都很容易看懂,最多就是处理一下边界情况。

事件设置好之后,我们就可以开始监听一下这个 canvasCurrentHistory 当前状态下标,使用副作用函数进行处理

为canvas画布填充图像信息!

这样就大功告成啦!!!

9. 实现鼠标图标的变化

我们简单的处理一下,画笔模式则是画笔的图标,橡皮擦模式下鼠标是橡皮擦,移动模式下就是普通的移动图标

切换模式时候,设置一下不同的图标

10. 切换图片

现在的话只是一个demo状态,通过点击选择框,切换不同的图片

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

注意事项

注意容器的偏移量

我们需要注意一下,因为公式中的 downX 是相对容器的坐标,也就是说,我们需要减去容器的偏移量,这种情况会出现在使用了 margin 等参数,或者说上方或者左侧有别的元素的情况

我们输出一下我们红色的元素的 offsetLeft 等属性,会发现他是已经本身就有50的偏移量了,我们计算鼠标点击的坐标的时候就要减去这一部分的偏移量

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

注意父组件使用relative相对布局的情况

假如我们现在有一种这种的布局,打印红色元素的偏移量,看起来都挺正常的

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

但是如果我们目标元素的父元素(也就是黄色部分)设置 relative 相对布局

这时候我们打印出来的偏移量会是多少呢

Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式)

两次答案不一样啊,因为我们的偏移量是根据相对位置来计算的,如果父容器使用相对布局,则会影响我们子元素的偏移量

组件代码(低配版)

总结

到此这篇关于Html5 Canvas实现图片标记、缩放、移动和保存历史状态 (附转换公式)的文章就介绍到这了,更多相关Canvas 图片标记 缩放 移动内容请搜索以前的文章或继续浏览下面的相关文章,希望大家以后多多支持!

本知识来源于互联网索引,如有侵权请联系我们!

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在!
点赞 (0)

1、寻代码所有源码、代码、教程和软件均为作者提供和网友推荐收集整理而来!
2、寻代码提供的所有模块、软件等资源,均不提供任何技术服务,请知悉!
3、如您需要商用,请支持正版,寻代码网站所提供的程序仅供学习和研究使用!
4、寻代码源码不得使用于非法商业用途,不得违反国家法律。您必须在下载后24小时内删除!
5、寻代码资源每天实时更新,如遇压缩包解压密码,一律为:www.xundm.com
6、寻代码资源售价和VIP会员只是赞助,收取费用仅维持本站的日常运营所需!
7、如有链接无法下载、失效或广告,请在会员中心下工单!
如有侵犯您版权的,请来信(邮箱:[email protected])指出,本站将立即改正。

寻代码 html5 Html5 Canvas实现图片标记、缩放、移动和保存历史状态功能 (附转换公式) https://xundm.com/202018642.html

常见问题
  • 当然可以,寻代码每日签到奖励1寻币,推广注册奖励5寻币,只要坚持关注和推广我们站,您可以免费下载全站资源
查看详情
  • 寻代码所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 赞助VIP介绍。
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言或在会员中心直接提交工单 。
查看详情
  • 对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
查看详情

相关文章

寻代码站内服务

为您解决烦忧 - 24小时在线 专业服务