Canvas绘制不规则图形,实现可拖动,编辑--V1.0第一篇
目前的工作在做在线的标注工具,接触canvas一年了,各种绘制,基本上图像的交互canvas都可以完成,也写了几篇关于canvas的文章,遇到的问题也写博客上了,对于canvas有问题的朋友可以去看看。一直想写一个关于canvas系列的东西,也没时间。正好最近再捣鼓canvas,有时间就写一点,一个功能一个功能的写,争取写一个系列。
以前都是绘制矩形,今天写一个新鲜的,绘制多边形可拖动编辑的多边形。见下图(截取自工程的一部分):

(太大的GIF图传不上来,只能截取一小部分,找个时间把完整的功能录一个视频放在网盘上)。
鼠标点击绘制点,并且自动绘制曲线,(当曲线闭合的时候,弹出名称边界框--不重要),绘制完毕后,点击点可以改变形状,点击曲线内部可以拖动位置。
这篇文章就先写绘制不规则图像与拖动点吧,移动图像值得另起写一篇文章。
正文
写了这么多的canvas代码,我的经验就是一定要去写,一边写边看效果,做的过程中会有新的想法。对于canvas各种绘制的效果,还是得去动手去修改才能出效果。
写之前整理下思路:
1.鼠标点击绘制点-->绘制圆的方法,鼠标点为中心点。
2.每点击一次,绘制线段。--Lineto方法。
3.判断是否闭合。
4.判断是否点击了绘制过的点上--拖动改变形状。
5.重绘。
画布上每一次的更改都是要重新绘制画布的,所以要把绘制的点保存起来。这个思路和画矩形的思路大体相近,可以看下我的绘制矩形的文章。
//线段的点的集合
var points=[];
//可拖动圆圈的点的集合
var circles=[];
//每一个点的对象
function Point(x, y) {
this.x = x;
this.y = y;
}
//圆圈对象
function Circle(x, y) {
this.x = x;
this.y = y;
this.radius = 10;
this.color = "blue";
//拖拽点的标记
this.isSelected = false;
}
/*每一次的点都看作一个对象,然后把点放在数组里保存起来
这样circles和points就会是这种形式
points=[{(x0,y0},{x1,y1},{x2,y2}..]
circles=[{x0,y0,10,blue,false}...]*/
上边的points和circles数组其实xy坐标是一样的,为啥创建两个呢?
如果项目小,就实现一个拖拽的图像就行了,那可以随便设置数组个数,随着标注工具增加,各种重绘,还是各干各的比较好,不要高耦合。
绘制:
canvas.onmousedown=function(e){
var clickX = e.pageX - canvas.offsetLeft;
var clickY = e.pageY - canvas.offsetTop;
//判断当前点击点是否在已经绘制的圆圈上,如果是执行相关操作,并return,不进入画线的代码
for(var i=1; i<circles.length; i++) {
var circle = circles[i];
//使用勾股定理计算这个点与圆心之间的距离
var distanceFromCenter = Math.sqrt(Math.pow(circle.x - clickX, 2)
+ Math.pow(circle.y - clickY, 2));
// 如果是其他的点,则设置可以拖动
if (distanceFromCenter <= circle.radius) {
// 清除之前选择的圆圈
index=i;
isDragging=true;
//停止搜索
return;
}
}
//如果点击新的位置,则进入下面的代码,绘制点
context.clearRect(0,0,canvas.width,canvas.height);
//遍历数组画圆
var circle=new Circle(clickX,clickY);
circles.push(circle);
circles[0].color="green";
for(var i=0; i<circles.length; i++) {
var circle = circles[i];
// 绘制圆圈
context.globalAlpha = 0.85;
context.beginPath();
context.arc(circle.x, circle.y, circle.radius, 0, Math.PI*2);
context.fillStyle = circle.color;
context.strokeStyle = "black";
context.fill();
context.stroke();
}
// 画线
var point=new Point(clickX,clickY);
points.push(point);
context.beginPath();
context.lineWidth = 4;
//从起始点开始绘制
context.moveTo(points[0].x,points[0].y);
for (var i = 0; i < points.length; i++) {
context.lineTo(points[i].x, points[i].y);
}
context.fillStyle="rgb(2,100,30)";
context.fill();
context.strokeStyle="#9d4dca";
context.stroke();
};
每一次点击都要判断一下,如果点在曾经绘制的点上,那么就设置变量isDragging=true可以拖拽,return。如果没有,说明创建的是新的点,那么开始绘制并且加入数组。(代码部分的声明就不写了,直接出关键的思路代码,具体的还要自己动手去写)
拖拽点移动:
canvas.onmousemove=function(e){
// 判断圆圈是否开始拖拽
if (isDragging == true) {
// 判断拖拽对象是否存在
// 取得鼠标位置
var x1 = e.pageX - canvas.offsetLeft;
var y1 = e.pageY - canvas.offsetTop;
context.clearRect(0,0,canvas.width,canvas.height);
//根据上文得到的index设置index点位置随鼠标改变
circles[index].x=x1;
circles[index].y=y1;
points[index].x=x1;
points[index].y=y1;
for(var i=0; i<circles.length; i++) {
var circle = circles[i];
// 绘制圆圈
context.globalAlpha = 0.85;
context.beginPath();
context.arc(circle.x, circle.y, circle.radius, 0, Math.PI*2);
context.fillStyle = circle.color;
context.strokeStyle = "black";
context.fill();
context.stroke();
}
context.beginPath();
context.moveTo(points[0].x,points[0].y);
for (var i = 0; i < points.length; i++) {
context.lineTo(points[i].x, points[i].y);
}
context.lineTo(points[0].x,points[0].y);
// context.fillStyle="#831f68";
context.fillStyle="rgb(2,100,30)";
context.fill();
context.strokeStyle="#9d4dca";
context.stroke();
}
};
canvas.onmouseup=function(){
isDragging=false;
};
canvas.onmouseout=function(){
isDragging=false;
};
其实实现拖拽并不难, 有一个地方就是如何判断鼠标点在了已经绘制的点上。循环所有点,只要鼠标点到圆心的距离小于半径,那么一定点在了这个点上。
这样一个简单的拖拽就实现了,后面的文章我还会继续增加新的功能,慢慢丰富代码。欢迎关注。

更新:一个V1.0工程的视频,百度网盘:链接: https://pan.baidu.com/s/1qFF3yF4T9oE9quiUx7hfoA 密码: md6g
1.0版本,后续版本慢慢更新,包括canvas的绘制和Vue的一些东东。可绘制、拖拽、编辑、下载坐标信息,对于一些数据集的标注工作可以辅助标记。
Canvas绘制不规则图形,实现可拖动,编辑--V1.0第一篇的更多相关文章
- 学习笔记:HTML5 Canvas绘制简单图形
HTML5 Canvas绘制简单图形 1.添加Canvas标签,添加id供js操作. <canvas id="mycanvas" height="700" ...
- Canvas学习:封装Canvas绘制基本图形API
Canvas学习:封装Canvas绘制基本图形API Canvas Canvas学习 从前面的文章中我们了解到,通过Canvas中的CanvasRenderingContext2D对象中的属性和方 ...
- [html5] 学习笔记-Canvas 绘制渐变图形与绘制变形图形
在 HTML5 中,使用 Canvas API 绘制图形的知识,可以对绘制图形进行处理,包含使用 Canvas API 绘制渐变图形,使用 Canvas API 的坐标轴变换处理功能绘制变形图形.其中 ...
- canvas绘制简单图形
canvas绘图篇: canvas绘制矩形: <!DOCTYPE html> <html> <head lang="en"> <meta ...
- h5 的canvas绘制基本图形
文章地址:https://www.cnblogs.com/sandraryan/ canvas是一个标签,可用于绘制复杂图形,渲染效果比普通DOM快 某些低版本浏览器不支持 canvas 使用原生几乎 ...
- Android采用canvas绘制各种图形
canvas通俗的说就是一个帆布,我们可以用刷子paint,就此随机抽签显卡. 原理: 能够canvas视Surface替代或接口.图形绘制Surface向上.Canvas封装了全部的绘制调用. 通过 ...
- canvas绘制旋转图形
将绘制到canvas上的要素进行旋转: 1.绘制时,通过操作画布的坐标轴状态:平移画布原点,旋转坐标轴等,达到旋转图形的目的 2.操作操作DOM元素,直接旋转canvas画布 操作画布的坐标轴状态: ...
- css3创建多边形clip属性,可用来绘制不规则图形了
.path1 { clip-path: polygon(5px 10px, 16px 3px, 16px 17px); } .path2 { clip-path: polygon(3px 5px, 1 ...
- CSS3绘制不规则图形,代码收集
三角形系列(三角形.倒三角.左三角.右三角.左上三角.右上三角.左下三角.右下三角) 主要用到的是:宽度高度设置为0, border的各个边的设置(各个边的透明或不透明): .triangle-up ...
随机推荐
- 部署knight项目
发布CRM你将使用以下软件 nginx uWSGI CentOS7 CRM项目文件 virtualenv supervisor WSGI.uWSGI python web服务器开发使用WSGI协议(W ...
- 004-集成maven和Spring boot的profile功能打包
参考地址:https://blog.csdn.net/lihe2008125/article/details/50443491 一.主要目标 1.通过mvn在命令行中打包时,可以指定相应的profil ...
- TQ2440系统介绍入门 、linux系统目录结构
TQ2440开发板系统安装步骤: 1.先用JTAG线安装BIOS到开发板.下载BIOS,NOR/NAND开关选在NOR位置. 2.linux安装步骤: (1).格式化分区 (2).安装BIOS---& ...
- #运算符、不同的指针类型、数组和指针、指针运算、堆、栈、静态区、只读区、下标VS指针
#运算符:用于在预编译期将宏参数转换为字符串 #define CONVERS(x) #x //注:没用双引号包括. 不同类型的指针占用的内存空间大小相同. 局部变量 定义: a[5]; 打印a[ ...
- 练习webpack遇到的一些问题以及解决办法,供自己以后参考
1.利用nodeJs安装webpack时报出以下错误提示: 这个错误我在网上搜了一下,说是npm文件配置问题,也就是权限不够 解决办法:npm config set registry http://r ...
- Linux系统——引导过程与服务控制
一.Linux开机启动原理(十步) (1)开机自检BIOS 开机检测,主板检测 (2)MBR引导 硬盘512字节 (3)GRUB菜单 操作系统菜单 (4)加载内核(kernel) 启动操作系统核心,根 ...
- zip解压破解
B2TQZJEpzFAUHcHaTQRjtKi8C4Q5mpFsBFLYsNTfCs7ZD65X
- mycat 指定mycat节点
mycat 指定节点: /*!mycat:dataNode=order1*/select seq_nextval('APPOINTMENT_NO'); 指定节点创建存储过程或建表: /*!mycat: ...
- vuex是什么?怎么用,例子
什么是vuex? 官方的解释是:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 为什么要用 ...
- C#使用window API 控制打印纸张大小(转载)
windows一个特点就是设备无关性,这样就给程序控制打印机提供了很好的方法. 首先引用“泥人张”写的打印API类. using System;using System.Collections;usi ...