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

之前做过一个小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. Ant-Design如何使用

    1.下载Node.js Node.js的版本需要不低于V4.x,本不在省略,如果需要出门左转Node.js安装教程. 查看Node.js版本: C:\Users\Administrator>no ...

  2. JavaWeb—Session与Cookie

    概念 会话:指从一个浏览器窗口打开到关闭期间的一系列动作(可简单理解为用户开一个浏览器,点击多个链接,访问服务器多个web资源,然后关闭浏览器). HTTP协议是无状态协议:每次连接(比如同一个网站的 ...

  3. xadmin快速搭建一个后台管理系统

    环境:python3.5.2 ,django 2.0 ,xadmin2.0 Firsttly, 到 https://github.com/sshwsfc/xadmin/tree/django2上下载源 ...

  4. MFC中存在的不属于任何类的全局函数,它们统统在函数名称开头加上Afx

    MFC中存在的不属于任何类的全局函数,它们统统在函数名称开头加上Afx. 函数名称 说明 AfxWinInit 被WinMain(MFC提供)调用的一个函数,用做MFC GUI程序初始化的一部分,如果 ...

  5. Objective-C中的alloc和init问题

    从开始学的NSString *name=[[NSString alloc] init] 起,仅仅这句话是分配内存空间,一直在用,从来没考虑过它的内部是怎么实现的.今天无意中看到了这一句代码: NSSt ...

  6. Zen cart 根据数量打折插件

    Quantity Discounts 可以根据顾客购买多少来打折,很不错. 假如顾客买了3个以上的产品,就给他10%折扣,设置如下: Turn On Quantity Discount 1. In t ...

  7. 阿里云搭建go开发环境

    开通了一个阿里云来玩,记录一下环境搭建的过程 运行环境 ECS Ubuntu 16.04 64位 过程 #切换到安装文件夹 cd /usr/local #下载go #由于墙的原因,直接下载官方的可能会 ...

  8. The 15th UESTC Programming Contest Preliminary C - C0ins cdoj1554

    地址:http://acm.uestc.edu.cn/#/problem/show/1554 题目: C0ins Time Limit: 3000/1000MS (Java/Others)     M ...

  9. POJ - 2699 The Maximum Number of Strong Kings (最大流+枚举)

    题意:有n(n<=10)个选手,两两之间打比赛,共有n*(n-1)/2场比赛,赢一场得1分.给出每个人最后的得分.求有多少个定义如下的strong king:赢了所有得分比自己高的人或本身就是分 ...

  10. ACM-ICPC 2018 沈阳赛区网络预赛 G. Spare Tire (容斥原理)

    可推出$a_n = n^2+n, $ 设\(S_n = \sum_{i=1}^{n} a_i\) 则 \(S_n = \frac{n(n+1)(2n+1)}{6} + \frac{n(n+1)}{2} ...