canvas实现鼠标拖拽矩形移动改变大小
项目的一个新需求,动态生成矩形框,鼠标点击拖动改变矩形框的位置,并可以调整大小。
之前做过一个小demo,需求类似,但是在canvas内只有一个矩形框,拖动移动,当时记得是用isPointInPath()直接判断鼠标是否点在了矩形框以内。新需求的矩形框个数为n,经过测试,isPointinPath实现过程中有bug,并不能精准定位到具体点击到canvas的某一个矩形框。经过一系列的头脑风暴,才想出了解决办法,才发现原来是最简单的方法,但是在思考的当初就被pass了,见代码:
html:
<body>
<canvas id="canvas" width="400" height="300">
</canvas>
</body>
小demo,不做其他修饰,直接写逻辑吧。
js:
第一步,创建一个容器,以保存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实现鼠标拖拽矩形移动改变大小的更多相关文章
- JS实现漂亮的窗口拖拽效果(可改变大小、最大化、最小化、关闭)
转自<JS实现漂亮的窗口拖拽效果(可改变大小.最大化.最小化.关闭)>:http://www.jb51.net/article/73157.htm 这篇文章主要介绍了JS实现漂亮的窗口 ...
- WPF 在image控件用鼠标拖拽出矩形
原文:WPF 在image控件用鼠标拖拽出矩形 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee ...
- 2018-11-19-WPF-在image控件用鼠标拖拽出矩形
title author date CreateTime categories WPF 在image控件用鼠标拖拽出矩形 lindexi 2018-11-19 15:35:13 +0800 2018- ...
- Java3D读取3DMax模型并实现鼠标拖拽、旋转、滚轮缩放等功能
/**-------------------------------------------------代码区--------------------------------------------- ...
- CSharpGL(20)用unProject和Project实现鼠标拖拽图元
CSharpGL(20)用unProject和Project实现鼠标拖拽图元 效果图 例如,你可以把Big Dipper这个模型拽成下面这个样子. 配合旋转,还可以继续拖拽成这样. 当然,能拖拽的不只 ...
- 拼图 canvas分割 dom拖拽 pc 移动端
参考:Canvas drag 实现拖拽拼图小游戏 参考的案例,不支持手机端.总结下实现过程中遇到的小坑. gitHub:https://github.com/WppFrontEnd/puzzle 大概 ...
- JavaScript鼠标拖拽特效及相关问题总结
#div1{width:200px;height:200px;background:red;position:absolute;} #div2{width:200px;height:200px;bac ...
- 一款基于jQuery的支持鼠标拖拽滑动焦点图
记得之前我们分享过一款jQuery全屏广告图片焦点图,图片切换效果还不错.今天我们要分享另外一款jQuery焦点图插件,它的特点是支持鼠标拖拽滑动,所以在移动设备上使用更加方便,你只要用手指滑动屏幕即 ...
- 【狼】unity 鼠标拖拽物体实现任意角度自旋转
主要涉及函数 Input.GetAxis(“Mouse x”) 可取得鼠标横向(x轴)移动增量 Input.GetAxis(“Mouse y”) 可取得鼠标竖向(y轴)移动增量 通过勾股定理获取拖拽长 ...
随机推荐
- 浅谈virtualenv(虚拟环境)
简介 virtualenv为应用提供了隔离的Python运行环境,解决了不同应用间多版本的冲突问题. 例如: 如果我们要同时开发多个应用程序,那这些应用程序都会共用一个Python,就是安装在系统的P ...
- 【MFC系列】MFC快速设置控件文本字体、大小、颜色、背景
以静态文本为例,分享一下怎么修改文本字体.大小.颜色.背景等参数.其他文本.控件等可参照修改. 1.修改字体.大小 这个很简单,首先在Dlg类中声明一个CFont类型的成员变量: 然后在类的初始化函数 ...
- Incorrect key file for table ' '; try to repair it
场景:为有150W的数据表增加字段时,报错 解决:在my.ini配置临时目录configure tmpdir. Where MySQL Stores Temporary Files
- APICloud常用方式
新打开一个窗口: api.openWin({ name: 'unlogin', url: 'widget://html/unlogin.html', pageParam: { } }); 新打开一个F ...
- PAT 1121 Damn Single[简单]
1121 Damn Single (25 分) "Damn Single (单身狗)" is the Chinese nickname for someone who is bei ...
- python将图片转化为字符图
最近看到将图片转化为字符图的小实验,我觉得很有趣,所以决定自己实现一下. 步骤和原理如下: 读取图片的灰度值矩阵(0-255之间),灰度值矩阵主要反映的是图片的黑白程度,越黑越接近与0,越白越接近于2 ...
- Flask之初体验
Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后 ...
- php注册审查
思路 用户注册后就有该条用户记录,你对用户表设一个“审核状态”字段,默认值设为“未审核”,然后你写几句审核代码做成一个功能,按照你们的意愿若审核通过你把审核状态改为“已审核”就行了.用户想进行各种操作 ...
- linux 下安装python3
这篇真的很好 没报错一次通过了 https://www.cnblogs.com/kimyeee/p/7250560.html
- springcloud---2
每一个都是独立的springboot工程.通过自己的ip和端口访问. Eureka是服务发现组件,Eureka里面有一个服务注册表,存的是服务消费者和服务生产者的ip和端口.Eureka集群里面每个E ...