canvas实现图片标记
前言
由于业务需求,需要有一个图片标记功能,其实就是对图片画框画线做标记,类似微信的图片编辑

但是需要存下标记图及其标记的具体数据,。功能其实很简单,但刚开始的时候也是费了一些功夫的。我将原项目中该功能抽离出来单独写了一个demo,作为记录,同时你们在开发过程中有类似需求的话也可以参考一下该思路,其中有不足之处还请指出来。
实现目标
1、定点缩放。
2、图片拖拽。
3、图片中绘制点、直线、矩形、圆形、多边形。
4、上传原图。
5、下载标注图。
6、记录标记数据。
具体效果

浏览地址:http://xisite.top/original/other/imgMark/index.html
源码地址:https://gitee.com/xi1213/img-mark
实现思路
项目是纯原生canvas实现的,没使用任何其他插件。由于canvas没有图层的概念,实现切换不同的绘制模式时有一点麻烦。具体方案是:分别单独存下每次绘制的数据,再将该数据添加到一个大列表中(如下图中的canvasData),每次绘制图形时都需要重绘该大列表,若需要操作绘制的图形,则变动大列表中对应的数据后重绘即可。

具体逻辑
1、绑定事件。先添加画布canvas,并指定画布尺寸与绑定各种事件:滚轮事件(mousewheel)、右键事件(contextmenu)、鼠标按下事件(mousedown)、鼠标松开事件(mouseup)、鼠标移动事件(mousemove)、双击事件(dblclick)。

2、绘制模式。该功能有五种绘图模式:点模式、直线模式、矩形模式、多边形模式、圆形模式。点模式最简单,在鼠标松开事件中绘制点,然后获取到坐标,最后将数据添加到大列表中。

其中canvas绘制点的方法如下,其实就是利用ctx.arc绘制一个实心圆,arc四个参数分别为圆心坐标x、y、半径、起始角度、终止角度。

直线模式的绘制是在鼠标移动事件中,移动时不停的调用ctx.clearRect清除绘制的图形,然后再不停的绘制大列表的数据,鼠标松开后将再将直线绘图数据添加到大列表中,从而实现拖拽画线的效果。canvas绘制直线的方法如下,其中最主要的便是ctx.lineTo方法。

矩形模式的绘制与直线绘制一样,也是放在鼠标移动事件中的。拖拽即可绘制出矩形。具体canvas绘制矩形的方法如下,其中ctx.strokeRect方法四个参数分别为矩形左上角的x、y坐标,矩形长度、矩形宽度。

多边形绘制模式比较麻烦一点。我设计的操作模式是,右键依次点击多边形的顶点,最后需要闭合时双击左键即可完成绘制,闭合多边形,将多边形数据添加到大列表中。这样只需判断每次点击绘制时是否闭合即可,双击事件处理如下。

圆形模式绘制的绘制与点的绘制类似,也是使用ctx.arc。不同的是圆需要计算半径,在鼠标松开的一瞬间记录下坐标,使用该坐标平方后再开根即可计算出半径。具体绘制方法如下。

3、定点缩放。需要保证鼠标中心位置与图片比例不能改变,该功能是绑定鼠标滚动事件的,每次缩放时需要重新计算比例与坐标,重绘大列表的数据,这是滚动事件的处理,需要注意事件中wheelDelta值的正负。

这是改变画布的方法,画布尺寸是通过缩放倍数与原图尺寸控制的,画布位置是通过旧位置加偏移量来控制的。需要限制缩放倍数的话控制maxZoom与minZoon即可。

4、图片拖拽。该功能的实现则比较简单,点击左键后打开限制拖拽的状态,记录拖拽偏移量。

鼠标移动时,实时改变画布的top与left即可(这里是通过position: absolute;定位的)。

5、上传原图。这里的上传并不是上传到服务器中,而是利用input type="file"选取文件到浏览器中处理,需要限制为只选取图片,使用accept="image/jpeg"属性。

其中上传的方法如下,需要限制文件大小,然后通过createObjectURL获取到url(该url比较特殊,只在当前dom页面中有效)。
最后通过loadBgImg方法返回一个img,页面中即可使用该图片,从而实现“上传”。

6、下载标注图。值得注意的是为防止标记错位,需要下载前需要将图片尺寸位置还原,然后再获取页面中canvas的DOM,然后通过toDataURL获取到base64。

将该base64生成转化为Blob,然后创建事件,使用a标签下载,路径仍然使用createObjectURL获取。

7、记录标记数据。记录标记数据的好处是,将来若需要单独编辑每个标记,则可以直接改变记录下的数据,然后重绘该数据即可。记录数据的逻辑是写在鼠标松开事件中的,每次绘制完标记后都需要将绘图数据push到大列表中。
结语
在开发过程中我还是踩了很多坑的,文章中记录的只是很少的一部分。还是建议看文章开头的项目源码链接,源码中我写了大量详细的注释。
原文链接:https://xiblogs.top/?id=30
canvas实现图片标记的更多相关文章
- canvas学习笔记:canvas对图片的像素级处理--ImageData的应用
学习了canvas的基本绘图功能后,惊喜的发现canvas对图片数据也有相当强大的处理功能,能够从像素级别操作位图,当然[lte ie8]不支持. 主要的函数有三个: ctx.createImageD ...
- 快速解决Canvas.toDataURL 图片跨域的问题
出现Canvas.toDataURL 图片跨域问题怎么解决呢?下面小编就为大家带来一篇Canvas.toDataURL 图片跨域问题的快速解决方法.一起跟随小编过来看看吧 如题,在将页面的图片地址进行 ...
- 用canvas实现图片滤镜效果详解之灰度效果
前面展示了一些canvas实现图片滤镜效果的展示,并且给出了相应的算法,下面来介绍一下具体的实现方法. 前面介绍的特效中灰度效果最简单,就从这里开始介绍吧. 1.获取图像数据 img.src = ’h ...
- 【2017-03-20】HTML基础知识、文字标记、图片标记、空格换行、表格、表格嵌套及布局、超链接
一.HTML基础知识 HTML: 网站(站点) - 网页 网站是由一个或者多个网页组合起来的 HTML作为文件后缀名,可以把文件变为网页 HTML是一门编程语言的名字:超文本标记语言 超越了文字的范畴 ...
- 使用canvas进行图片裁剪简单功能
1.html部分 使用一个input[type="file"]进行图片上传: canvas进行图片的裁剪展示 <div> <input type="fi ...
- 利用canvas 导出图片
1.使用canvas绘制图片,并将图片导出. 在本地直接访问静态网页时,无法使用toDataURL(),需要将网页发布后,canvas才能使用toDataURL获取画布上的内容.因为canvas不允许 ...
- canvas将图片转为base64
最简例子 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta ...
- 用tornado实现图片标记
背景介绍 在文章Keras入门(四)之利用CNN模型轻松破解网站验证码中,其中的验证码图片标记是采用tornado实现的网页实现的.本文将会讲述如何利用tornado来实现图片标记. 我们的示 ...
- [JavaScript] canvas 合成图片和文字
Canvas Canvas 是 HTML5 新增的组件,就像一个画板,用 js 这杆笔,在上面乱涂乱画 创建一个 canvas <canvas id="stockGraph" ...
- canvas转图片
<script> var canvas, context2D, canvasimg, context2Dimg ,fontSize = 100; window.onload ...
随机推荐
- Qt 学习笔记 - 第四章 - Qt的三驾马车之 - 网络编程
Qt 学习笔记全系列传送门: Qt 学习笔记 - 第一章 - 快速开始.信号与槽 Qt 学习笔记 - 第二章 - 添加图片.布局.界面切换 Qt 学习笔记 - 第三章 - Qt的三驾马车之一 - 串口 ...
- mysql 授权远程连接
解决方案 改表法 可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑,登入mysql后,更改 "mysql" 数据库里的 &quo ...
- Simple WPF: WPF自定义一个可以定义步长的SpinBox
最新内容优先发布于个人博客:小虎技术分享站,随后逐步搬运到博客园. 通过WPF的按钮.文本输入框实现了一个简单的SpinBox数字输入用户组件并可以通过数据绑定数值和步长.本文中介绍了通过Xaml代码 ...
- 题解:AT_abc357_f [ABC357F] Two Sequence Queries
题意 维护一个数据结构,支持两个数列的区间求和,和查询区间内两数列各元素积的和. 分析 线段树万岁! 这道题要维护两个序列,所以线段树中要同时存储两个区间和.但还要在维护一个信息,是该区间内两序列元素 ...
- Day 8 - 并查集、堆、set 与 map
并查集 引入 并查集是一种用于管理元素所属集合的数据结构,实现为一个森林,其中每棵树表示一个集合,树中的节点表示对应集合中的元素. 顾名思义,并查集支持两种操作: 合并(\(\text{Union}\ ...
- SQL Server 图解备份(完全备份、差异备份、增量备份)和还原
常用的数据备份方式有完全备份.差异备份以及增量备份,那么这三种备份方式有什么区别,在具体应用中又该如何选择呢? 1.三种备份方式 完全备份(Full Backup):备份全部选中的文件夹,并不依赖文件 ...
- AS自制闹钟学习,关于PendingIntent与AlarmManager
PendingIntent是Intent的封装,不是立刻执行某个行为,而是满足某些条件或触发某些事件后才执行指定的行为实例获取一般为下列5个用法 getActivity() getActivities ...
- 【Linux】快速文件交互 lrzsz
首先需要安装依赖: yum install -y lrzsz 没有此依赖,Linux提示找不到命令: [root@localhost ~]# rz -bash: rz: 未找到命令 [root@loc ...
- CyberDog测试视频 —— 【开箱】小米"限量"机器狗!被我玩坏了...
地址: https://www.youtube.com/watch?v=3ntAhy3thXM PS. 现在的智能机器人其实真的没有人们想象中的那么智能.感觉现在的智能机器人最为有用的功能一个是倒地自 ...
- 【转载】 PID原理与参数调试
原文地址: http://m.elecfans.com/article/1153309.html --------------------------------------------------- ...