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 ...
随机推荐
- PHP 程序员是学 Swoole ?还是学 Go ?
大家好,我是码农先森. 面临现状 这次为什么要讨论这个话题,因为 Swoole 和 Go 在 PHP 程序员坊间一直都是茶语饭后的谈资,觉得懂 Swoole 和 Go 的就高人一等.相信有很多的 PH ...
- javaweb使用gson工具使浏览器返回json数据
1.什么是序列化和反序列化 (1)Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程: (2)序列化:对象序列化的最主要的用处就是在传递和保 ...
- [oeasy]python0082_[趣味拓展]控制序列_清屏_控制输出位置_2J
光标位置 回忆上次内容 上次了解了键盘演化的过程 ESC 从 组合键 到 独立按键 添加图片注释,不超过 140 字(可选) ESC的作用 是 进入 控制序列 配置 控制信息 控制信息 ...
- [oeasy]python0096_游戏娱乐行业_雅达利_米洛华_四人赛马_影视结合游戏
游戏娱乐行业 回忆上次内容 游戏机行业从无到有 雅达利 公司 一枝独秀 并且带领 行业 发展起来 雅达利公司 优秀员工 乔布斯 在 朋友 帮助下完成了<pong> Jobs 黑了 Woz ...
- 辅助分类器生成对抗网络( Auxiliary Classifier Generative Adversarial Network,ACGAN)(附带pytorch代码)
1 ACGAN基本原理 1.2 ACGAN模型解释 ACGAN相对于CGAN使的判别器不仅可以判别真假,也可以判别类别 .通过对生成数据类别的判断,判别器可以更好地传递loss函数使得生成器能够更加准 ...
- 安卓快速掌网络请求HttpUrlConnection,GET和getHttp相关示例
HttpURLConnection 是 Java 标准库中的一部分,它不依赖于特定的 Android 版本.,从 Android 9(API 级别 28)开始,Google 官方推荐使用更现代化的网络 ...
- python_xecel
移动并重命名工作簿 1 from pathlib import Path # 导入pathlib模块的path类 2 import time 3 4 # Press the green button ...
- jpa+querydsl的平替国产easy-query最好用的orm
jpa+querydsl的平替国产easy-query最好用的orm 一款国产最强java orm,完美支持可控强类型dsl,外加完美支持对象模型筛选拉取的orm,拥有非常智能的include(s)一 ...
- 【Vue2】Computed 计算属性
计算属性在编写的时候是一个方法 但是在调用的时候作为属性使用 <!DOCTYPE html> <html lang="en"> <head> & ...
- 【H5】04 建立超链接
摘自: https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks 超链接 ...