如何实现Canvas图像的拖拽、点击等操作
上一篇Canvas的博文写完后,有位朋友希望能对Canvas绘制出来的图像进行点击、拖拽等操作,因为Canvas绘制出的图像能很好的美化。好像是想做炉石什么的游戏,我也没玩过。
Canvas在我的理解中就好像在一张画布上绘制图像,它只能看到却“摸”不到,那要如何进行操作呢。我不知道网上是怎么做的,这里用自己的想法做了个DEMO分享给大家。
思路:
虽然Canvas不能拖拽,但div可以拖拽,那怎么把二者结合起来呢。初步想法是将一个与Canvas图像大小差不多的div覆盖在其上,在拖拽div时将获取的光标坐标修正后传给Canvas绘制函数并刷新图像的位置。
既然要覆盖,先做些准备工作:
1.将div与Canvas画布均position:absolute,否则无法重叠。
2.将div的z-index值设置大点,保证其在Canvas画面之上。
准备工作完成后,我们先来看div的拖拽:
var divObj=document.getElementById("cover");
var moveFlag=false; divObj.onmousedown=function(e){
moveFlag=true;
var clickEvent=window.event||e;
var mwidth=clickEvent.clientX-divObj.offsetLeft;
var mheight=clickEvent.clientY-divObj.offsetTop;
document.onmousemove=function(e){
var moveEvent=window.event||e;
if(moveFlag){
divObj.style.left=moveEvent.clientX-mwidth+"px";
divObj.style.top=moveEvent.clientY-mheight+"px";
divObj.onmouseup=function(){
moveFlag=false;
}
}
}
};
来解读下这段代码:首先获取div对象,设置拖拽标志moveFlage,当onmousedown时为true表示可以拖动,当onmouseup时为false表示不能拖动了。
var clickEvent=window.event||e;
var mwidth=clickEvent.clientX-divObj.offsetLeft;
var mheight=clickEvent.clientY-divObj.offsetTop;
这三行代码是为了修正光标位置。当点击时,记录下光标在div上的位置。mwidth和mheight表示光标落点相对于div左边和上边的距离。如果不加修正:
这就是不加修正的结果,当光标点下时,div的坐标即左上角会与光标坐标一致。
修正后:
点击时光标总会“粘”在div某点上。
接下来绘制图片:
首先定义全局变量X和Y,它们是为了实时更新图像的绘制坐标。
var ctx=document.getElementById("myCanvas").getContext("2d");
var img=document.getElementById("myImg");
function drawImg(){
ctx.clearRect(0,0,1000,500);
ctx.beginPath();
ctx.drawImage(img,X,Y);
ctx.closePath();
ctx.stroke();
} window.onload=function(){
setInterval(drawImg,1);
}
获取“画笔”,获取图片对象。这里setInterval循环执行绘制图片的函数,以刷新图片的位置,setInterval的间隔值越小,拖拽起来越“流畅”。
同时别忘了clearRect,当图片移动到下一个位置时,清除上一个位置的图片,参数为Canvas画布的坐标和尺寸。
在拖拽时将修正后的光标坐标传给X、Y:
X=moveEvent.clientX-mwidth;
Y=moveEvent.clientY-mheight;
最后加上div和图像的活动范围:
if(moveEvent.clientX<=mwidth){
divObj.style.left=0+"px";
X=0;
}
if(parseInt(divObj.style.left)+divObj.offsetWidth >=1000){
divObj.style.left=1000 - divObj.offsetWidth+"px";
X=1000 - divObj.offsetWidth;
}
if(moveEvent.clientY<=mheight){
divObj.style.top=0+"px";
Y=0;
}
if(parseInt(divObj.style.top)+divObj.offsetHeight>=500){
divObj.style.top=500-divObj.offsetHeight+"px";
Y=500-divObj.offsetHeight;
}
这个就看个人的要求了,注意是要同时限定div和图片的活动范围。1000与500为本例的画布大小,如果是在整个页面里活动就换成innerWidth或innerHeight。
彻底隐藏div看看效果:
最后说下点击事件,这里要注意的是在拖拽的过程中onmousedown与onmouseup二者就构成了一个click过程,但我们不希望在拖拽结束后触发点击事件。
这里有个比较简单的办法,定义一个clickFlag默认为false,当onmousedown时设为true,若进行了onmousemove事件时设为false。
在最后onmouseup时判断clickFlag的值,为true时才触发点击事件。也就是说当你按下鼠标时,只有不发现移动,松开鼠标时才会触发点击事件。
整理后的JS代码:
// 绘制图片坐标
var X=0;
var Y=0;
// js部分
var divObj=document.getElementById("cover");
var moveFlag=false;
//区别moueseup与click的标志
var clickFlag=false;
// 拖拽函数
divObj.onmousedown=function(e){
moveFlag=true;
clickFlag=true;
var clickEvent=window.event||e;
var mwidth=clickEvent.clientX-divObj.offsetLeft;
var mheight=clickEvent.clientY-divObj.offsetTop;
document.onmousemove=function(e){
clickFlag=false;
var moveEvent=window.event||e;
if(moveFlag){
divObj.style.left=moveEvent.clientX-mwidth+"px";
divObj.style.top=moveEvent.clientY-mheight+"px";
//// 将鼠标坐标传给Canvas中的图像
X=moveEvent.clientX-mwidth;
Y=moveEvent.clientY-mheight;
//// 下面四个条件为限制div以及图像的活动边界
if(moveEvent.clientX<=mwidth){
divObj.style.left=0+"px";
X=0;
}
if(parseInt(divObj.style.left)+divObj.offsetWidth >=1000){
divObj.style.left=1000 - divObj.offsetWidth+"px";
X=1000 - divObj.offsetWidth;
}
if(moveEvent.clientY<=mheight){
divObj.style.top=0+"px";
Y=0;
}
if(parseInt(divObj.style.top)+divObj.offsetHeight>=500){
divObj.style.top=500-divObj.offsetHeight+"px";
Y=500-divObj.offsetHeight;
}
divObj.onmouseup=function(){
moveFlag=false;
if(clickFlag){
alert("点击生效");
}
}
}
}
};
本例到此结束,更多功能大家有兴趣可以自己开发,感谢您的浏览,也感谢每个对我这菜鸟提意见的人。
如何实现Canvas图像的拖拽、点击等操作的更多相关文章
- 拼图 canvas分割 dom拖拽 pc 移动端
参考:Canvas drag 实现拖拽拼图小游戏 参考的案例,不支持手机端.总结下实现过程中遇到的小坑. gitHub:https://github.com/WppFrontEnd/puzzle 大概 ...
- canvas实现鼠标拖拽矩形移动改变大小
项目的一个新需求,动态生成矩形框,鼠标点击拖动改变矩形框的位置,并可以调整大小. 之前做过一个小demo,需求类似,但是在canvas内只有一个矩形框,拖动移动,当时记得是用isPointInPath ...
- canvas drag 实现拖拽拼图小游戏
博主一直心心念念想做一个小游戏- 前端时间终于做了一个小游戏,直到现在才来总结,哈哈- 以后要勤奋点更新博客! 实现原理 1.如何切图? 用之前的方法就是使用photoshop将图片切成相应大小的图 ...
- QTGraphics-View拖拽以及鼠标指针操作
因为QGraphicsView继承自QWidget,它也提供了像QWidget那样的拖拽功能. 另外,为了方便,Graphics View框架也为场景以及每个item提供拖拽支持.当视图接收到拖拽事件 ...
- HTML5 -canvas拖拽、移动 绘制图片可操作移动,拖动
关于canvas 的基础知识就不多说了,可以进这个网址学习 http://www.w3school.com.cn/html5/html_5_canvas.asp 对于canvas 和 SVG 其实一开 ...
- HTML5实战与剖析之原生拖拽(一拖拽历史概述)
提起拖拽,我就想起了在JavaScript培训的时候一个非常好玩的效果,那就是拖拽了.可以用鼠标任意拖拽着一个物体到任何你想去的地方. 最早拥有JavaScript拖拽功能的是IE4浏览器.当时,网页 ...
- 使用 Jquery-UI 实现一次拖拽多个选中的元素操作
项目需要,实现一个拖放操作,要求每次可以拖拽选中的多个元素,释放到目标容器后可排序.考虑了一下,觉得jquery-ui比较合适,毕竟它提供了项目需要的交互性事件机制.拖拽.释放.排序.选择等效果.而在 ...
- JS组件系列——Bootstrap Table 表格行拖拽
前言:之前一直在研究DDD相关知识,好久没更新JS系列文章了.这两天做了一个简单的业务需求,觉得效果还可以,今天在这里分享给大家,欢迎拍砖~~ 一.业务需求及实现效果 项目涉及到订单模块,那天突然接到 ...
- 前端vue拖拽
工作上遇到的需求:页面上需要拖拽一个小方块div拷贝至保存的容器中. 一.可拖拽 那么我们需要对小方块div进行授权,设置draggable="true"允许其被拖动 二.定义拖拽 ...
随机推荐
- Hadoop HBase概念学习系列之HBase里的高表设计概念(表设计)(二十八)
在下面这篇博文里,我给各位博客们,分享了创建HBase表,但这远不止打好基础. HBase编程 API入门系列之create(管理端而言)(8) 在关系型数据库里,表的高表和宽表是不存在的.在如HBa ...
- 获取索引--------用range()和len()
a = ['Google', 'Baidu', 'Runoob', 'Taobao', 'QQ'] for i in range(len(a)): print(i+1,a[i])
- 【CF917D】Stranger Trees
题目 看题解的时候才突然发现\(zky\)讲过这道题啊,我现在怕不是一个老年人了 众所周知矩阵树求得是这个 \[\sum_{T}\prod_{e\in T}w_e\] 而我们现在的这个问题有些鬼畜了, ...
- 【转】 Android中selector的使用
引言 selector中文的意思选择器,在Android中常常用来作组件的背景,这样做的好处是省去了用代码控制实现组件在不同状态下不同的背景颜色或图片的变换.使用十分方便. selector的定义 s ...
- Java并发编程--6.Exchanger线程间交换数据
在两个线程之间定义同步点,当两个线程都到达同步点时,他们交换数据结构,因此第一个线程的数据结构进入到第二个线程中,第二个线程的数据结构进入到第一个线程中 在生产者-消费者情境模式中它包含了一个数缓冲区 ...
- Java基础加强之并发(二)常用的多线程实现方式
概述 常用的多线程实现方式有2种: 1. 继承Thread类 2. 实现Runnable接口 之所以说是常用的,是因为通过还可以通过JUC(java.util.concurrent)包中的线程池来实现 ...
- [XML123] XSLT
XSLT简介 http://www.w3school.com.cn/xsl/index.asp XSLT测试 http://www.veryhuo.com/down/html/54703.html
- Android攻城狮学习笔记-进阶篇一
点击快速抵达: 第1章 AndroidManifest配置文件 第2章 使用ListView显示信息列表 第3章 使用DatePicker及TimePicker显示当前日期和时间 第4章 使用Grid ...
- openshift 入门 部署 openshift-origin-server-v3.7.0
OpenShift是一个基于容器技术的云平台,这里的容器技术指的就是docker和kubernetes. Openshift 错误解决 错误信息 failed to run Kubelet: fail ...
- 第8章 自己写库-构建库函数雏形—零死角玩转STM32-F429系列
第8章 自己写库—构建库函数雏形 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fi ...