项目的一个新需求,动态生成矩形框,鼠标点击拖动改变矩形框的位置,并可以调整大小。

之前做过一个小demo,需求类似,但是在canvas内只有一个矩形框,拖动移动,当时记得是用isPointInPath()直接判断鼠标是否点在了矩形框以内。新需求的矩形框个数为n,经过测试,isPointinPath实现过程中有bug,并不能精准定位到具体点击到canvas的某一个矩形框。经过一系列的头脑风暴,才想出了解决办法,才发现原来是最简单的方法,但是在思考的当初就被pass了,见代码:

html:

<body>
<canvas id="canvas" width="400" height="300">
</canvas>
</body>

小demo,不做其他修饰,直接写逻辑吧。

js:

第一步,创建一个容器,以保存Canvas内绘制的元素点。Canvas是一种非保留性的绘图界面,即不会记录过去执行的绘图操作,而是保持最终结果(构成图像的彩色像素)。

如果想让Canvas变得具有交互性,比如用户可以选择、拖动画布上的图形。那么我们必须记录绘制的每一个对象,才能在将来灵活的修改并重绘它们,实现交互。
     // canvas 矩形框集合
var rects=[];
function rectar(x,y,width,height){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.isSelected = false;
};

绘制矩形框:

 function drawRect() {
// 清除画布,准备绘制
context.clearRect(0, 0, canvas.width, canvas.height); // 遍历所有矩形框
for(var i=0; i<rects.length; i++) {
var rect = rects[i]; // 绘制矩形
context.strokeStyle="#FF0000";
context.strokeRect(rect.x,rect.y,rect.width,rect.height,rect.color); if (rect.isSelected) {
context.lineWidth = 50;
}
else {
context.lineWidth = 10;
}
}
}

这是一个绘制函数,因为在Canvas的所有操作,全部都是重新绘制的(先清除,在绘制),每次程序刷新画布时,会先使用 clearRect() 方法清除画布上的所有内容。但不用当心这样会造成画布闪烁,即画布上的圆圈一下子全部消失,然后一下子又重新出现。因为Canvas针对这个问题进行了优化,会在所有绘图逻辑执行完毕后才清除或绘制所有内容,保证最终结果的流畅。然后遍历矩形数组 其中的x,y,width,height来画矩形。

*这里我的项目是根据病变位置动态生成的矩形框,每一次生成矩形框,都要把它的位置信息添加到数组中,这里就直接创建矩形框了,可以根据自己需求改造

 function addRandomRect() {
var x=10;
var y=10;
var width=100;
var height=100;
// 创建一个新的矩形对象
var rect=new rectar(x,y,width,height); // 把它保存在数组中
rects.push(rect);
// 重新绘制画布
drawRect();
13 };

*Canvas点击事件

     var SelectedRect;
var x1;
var y1;
var right=false;
var widthstart,widthend;
var heightstart,heightend; function canvasClick(e) {
// 取得画布上被单击的点
var clickX = e.pageX - canvas.offsetLeft;
var clickY = e.pageY - canvas.offsetTop; // 查找被单击的矩形框
for(var i=rects.length-1; i>=0; i--) {
var rect = rects[i]; widthstart=rect.x;
widthend=rect.x+rect.width; heightstart=rect.y;
heightend=rect.y+rect.height; // 判断这个点是否在矩形框中
if ((clickX>=widthstart&&clickX<(widthend-20))&&(clickY>=heightstart)&&(clickY<(heightend-20))) {
console.log(clickX);
// 清除之前选择的矩形框
if (SelectedRect != null) SelectedRect.isSelected = false;
SelectedRect = rect;
x1=clickX-SelectedRect.x;
y1=clickY-SelectedRect.y;
//选择新圆圈
rect.isSelected = true; // 使圆圈允许拖拽
isDragging = true; //更新显示
drawRect();
//停止搜索
return;
};
/*
设置拉伸的界限。
*/
// if ((clickX>=(widthend-20))&&(clickY>=(heightend-20)))
// {
// SelectedRect = rect;
// right=true;
// }
//18-02-01改
            if ((clickX>=(widthend-20)&&((clickX<=(widthend+20)))&&(clickY>=(heightend-20))&&(clickY>=(heightend+20))) 
{
SelectedRect = rect;
right=true;
}
   } 

 }

代码中23行为判断具体点击哪个元素的语句,其实很简单,当初绕了很久,很简单直接判断鼠标点击点是否在矩形框之内即可,无论是哪个矩形框,只要在矩形框之内,就把当前矩形框设置为点击的矩形框。29行判断鼠标点击点相对于矩形框的位置。42-49行,是鼠标拉伸改变大小的判断,可以设置矩形四个角拉伸,但我认为太复杂了,只保留了右下角拉伸的点击判断,操作更简单一些。

响应事件:

  function dragRect(e) {
// 判断矩形是否开始拖拽
if (isDragging == true) {
// 判断拖拽对象是否存在
if (SelectedRect != null) {
// 取得鼠标位置
var x = e.pageX - canvas.offsetLeft;
var y = e.pageY - canvas.offsetTop;
// 将圆圈移动到鼠标位置
SelectedRect.x= x-x1;
SelectedRect.y= y-y1; // 更新画布
drawRect();
}
}
//判断是否开始拉伸
if (right) {
//设置拉伸最小的边界
if ((e.pageX - canvas.offsetLeft-SelectedRect.x)>50) {
SelectedRect.width=e.pageX - canvas.offsetLeft-SelectedRect.x;
}
else {
SelectedRect.width=50;
}
console.log(SelectedRect.width);
if((e.pageY - canvas.offsetTop-SelectedRect.y)>50){
SelectedRect.height=e.pageY - canvas.offsetTop-SelectedRect.y; }
else {
SelectedRect.height=50;
}
drawRect();
}
};

以上就完成了对矩形框的基本操作,然后添加onmouseup的函数和调用函数:

    var isDragging = false;
function stopDragging() {
isDragging = false;
right=false;
};

function clearCanvas() {
     // 去除所有矩形
      rects = [];

// 重新绘制画布.

    drawCircles();
    }

  window.onload = function() {
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
canvas.onmousedown = canvasClick;
canvas.onmouseup = stopDragging;
canvas.onmouseout = stopDragging;
canvas.onmousemove =dragRect;
; };

canvas实现鼠标拖拽矩形移动改变大小的更多相关文章

  1. JS实现漂亮的窗口拖拽效果(可改变大小、最大化、最小化、关闭)

    转自<JS实现漂亮的窗口拖拽效果(可改变大小.最大化.最小化.关闭)>:http://www.jb51.net/article/73157.htm   这篇文章主要介绍了JS实现漂亮的窗口 ...

  2. WPF 在image控件用鼠标拖拽出矩形

    原文:WPF 在image控件用鼠标拖拽出矩形 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee ...

  3. 2018-11-19-WPF-在image控件用鼠标拖拽出矩形

    title author date CreateTime categories WPF 在image控件用鼠标拖拽出矩形 lindexi 2018-11-19 15:35:13 +0800 2018- ...

  4. Java3D读取3DMax模型并实现鼠标拖拽、旋转、滚轮缩放等功能

    /**-------------------------------------------------代码区--------------------------------------------- ...

  5. CSharpGL(20)用unProject和Project实现鼠标拖拽图元

    CSharpGL(20)用unProject和Project实现鼠标拖拽图元 效果图 例如,你可以把Big Dipper这个模型拽成下面这个样子. 配合旋转,还可以继续拖拽成这样. 当然,能拖拽的不只 ...

  6. 拼图 canvas分割 dom拖拽 pc 移动端

    参考:Canvas drag 实现拖拽拼图小游戏 参考的案例,不支持手机端.总结下实现过程中遇到的小坑. gitHub:https://github.com/WppFrontEnd/puzzle 大概 ...

  7. JavaScript鼠标拖拽特效及相关问题总结

    #div1{width:200px;height:200px;background:red;position:absolute;} #div2{width:200px;height:200px;bac ...

  8. 一款基于jQuery的支持鼠标拖拽滑动焦点图

    记得之前我们分享过一款jQuery全屏广告图片焦点图,图片切换效果还不错.今天我们要分享另外一款jQuery焦点图插件,它的特点是支持鼠标拖拽滑动,所以在移动设备上使用更加方便,你只要用手指滑动屏幕即 ...

  9. 【狼】unity 鼠标拖拽物体实现任意角度自旋转

    主要涉及函数 Input.GetAxis(“Mouse x”) 可取得鼠标横向(x轴)移动增量 Input.GetAxis(“Mouse y”) 可取得鼠标竖向(y轴)移动增量 通过勾股定理获取拖拽长 ...

随机推荐

  1. DOM扩展学习笔记

    对DOM的两个主要扩展是Selectors API(选择符API)和HTML5,还有一个不太瞩目的Element Traversal元素遍历规范为DOM添加了一些属性,另外还有一些专有扩展. 选择符A ...

  2. Oracle数据库查找持有锁的SQL语句,而不是请求锁的SQL语句(原创)

    Oracle数据库查找持有锁的SQL语句,而不是请求锁的SQL语句 查找活动的事务以及活动事务关联的会话信息 select s.sid 会话ID, s.serial# 会话序列号, s.usernam ...

  3. pycharm使用技巧。(mac版本)

    一.pycharm使用中的一些快捷键 1.cmd  + b 跳转到声明处(cmd加鼠标) 2.option + c 复制光标当前行,剪切同理 3.option + v 粘贴复制的行 4.option ...

  4. 练习webpack遇到的一些问题以及解决办法,供自己以后参考

    1.利用nodeJs安装webpack时报出以下错误提示: 这个错误我在网上搜了一下,说是npm文件配置问题,也就是权限不够 解决办法:npm config set registry http://r ...

  5. co.js异步回调原理理解

    co.js是基于es6的generator实现的,相当于generator函数的一个自动执行器 generator的简单介绍 function* fn(){ before() yield firstY ...

  6. Element 中表单非必填数据项 必须为数字的验证问题

    Element-ui 的el-form组建中,自带基本的验证功能,比如某些项必填的验证,直接加入rules 规则中即可,如下实例: 在页面中书写如下: <el-form-item label=& ...

  7. django连接mongodb mongoengine

    优点 MongoEngine (http://mongoengine.org)1. 提供了和 Django 原生 ORM 几乎一样的一切,功能已经相当强大;2. 用起来比 Django 原生 ORM ...

  8. Hadoop RPC实例

    本文发表于本人博客. 上次写了个hadoop伪分布环境搭建的笔记了,今天来说下hadoop分布式构建的基础RPC,这个RPC在提交Job任务的时候底层就是创建了RPC来实现远程过程调用服务端. 我们首 ...

  9. 参数或变量中有语法错误。 服务器响应为: mail from address must be same as authorization user

    企业qq发邮件失败,提示: 参数或变量中有语法错误. 服务器响应为: mail from address must be same as authorization user 解决办法: 登录邮箱,设 ...

  10. PKU 3169 Layout(差分约束系统+Bellman Ford)

    题目大意:原题链接 当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些.FJ有N(2<=N<=1000)头奶牛,编号从1到N,沿一条直线站着等候喂食.奶牛排在队伍中的顺序和它们的编号是相同的 ...