专栏首页Golang语言社区前端游戏编程基础-如何实现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("点击生效");
					}
				}
			}
		}
	};

本文分享自微信公众号 - Golang语言社区(Golangweb)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-05-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 前端游戏编程基础-如何实现Canvas图像的拖拽、点击等操作

    希望能对Canvas绘制出来的图像进行点击、拖拽等操作,因为Canvas绘制出的图像能很好的美化。好像是想做炉石什么的游戏,我也没玩过。 Canvas在我的理解...

    李海彬
  • Go 语言的基本数据类型

    0)变量声明 var 变量名字 类型 = 表达式 例: var num int = 10 复制代码 其中“类型”或“= 表达式”两个部分可以省略其中的一个。 1...

    李海彬
  • Golang通过socket与java通讯

    下面上代码: //server.go //客户端,主要是在9000端口创建监听程序,用于接受客户端连接 package main import ( ...

    李海彬
  • 前端游戏编程基础-如何实现Canvas图像的拖拽、点击等操作

    希望能对Canvas绘制出来的图像进行点击、拖拽等操作,因为Canvas绘制出的图像能很好的美化。好像是想做炉石什么的游戏,我也没玩过。 Canvas在我的理解...

    李海彬
  • Vitalik Buterin:Casper 权益证明与分片技术最新进展

    区块链大本营
  • 剑指Offer-链表中倒数第k个结点

    题目描述 输入一个链表,输出该链表中倒数第k个结点。 思路 为了能够只遍历一次就能找到倒数第k个节点,可以定义两个指针: 快指针从链表的头指针开始遍历向前走k-...

    武培轩
  • Hi,我们再来聊一聊Java的单例吧

    单例(Singleton)应该是开发者们最熟悉的设计模式了,并且好像也是最容易实现的——基本上每个开发者都能够随手写出——但是,真的是这样吗? 作为一个Java...

    Java团长
  • Hi,我们再来聊一聊Java的单例吧

    原文:http://www.barryzhang.com/archives/521

    好好学java
  • 开始你的第一个机器学习项目|文末送书

    大家好,关于数据挖掘或者机器学习的理论我想大家应该都已经了解很多,而数据挖掘的工具例如Pandas、NumPy、Sklearn等在历史文章都有所介绍,因此今天我...

    刘早起
  • 汇编语言从入门到精通-指令汇总

    墨文

扫码关注云+社区

领取腾讯云代金券