龙空技术网

前端图形学(十五)——小球的拖拽和投掷

畅哥聊技术 180

前言:

此刻你们对“js小球与边框碰撞反弹”大约比较看重,小伙伴们都想要分析一些“js小球与边框碰撞反弹”的相关知识。那么小编同时在网摘上搜集了一些关于“js小球与边框碰撞反弹””的相关文章,希望姐妹们能喜欢,朋友们快快来了解一下吧!

欢迎来到【畅哥聊技术】前端图形学相关技术文章,更多精彩内容持续更新中,敬请关注。

上一章节我们给小球添加了事件处理逻辑,那么本章节我们来实现两个关于事件的深入应用。

在传统的dom操作中,我们也经常会用到拖拽的相关操作,那么应用到Canvas中来,原理也是一样的。

拖拽

如上图,我们可以把一个小球拖来拖去的。看似有些无聊乏趣。但是拖拽却是我们很多实际项目开发的最基础的知识点。比如移动端的滑动事件,大名鼎鼎的ISroll库等,他们实现的的滑动都有着拖拽的影子。

原理:鼠标在小球上按下,然后鼠标移动,小球跟随移动,鼠标抬起,拖拽结束。那么在拖拽的过程中,我们会发现有一个是恒定不变的,那就是鼠标的位置和小球的圆心的位置的距离。那么我们可以很容易的获取到鼠标的位置,那么要求出小球的位置就很容易了。

给Canvas画布添加mousedown mousemove mouseout事件。在鼠标按下的时候,我们先要判断是否点中了小球,如果没有点中,后续的操作终止在mousedown事件中获取鼠标相对于画布的起始坐标并且计算出鼠标和小球中心点的坐标差值。在mousemove中我们获取到鼠标的相对画布的坐标,然后再减去我们在mousedown中小球和鼠标的坐标差值,将得到的结果赋值给小球的x,y属性,在mouseup事件中去清除mousemove 和mouseup事件。

核心代码:

canvas.onmousedown = function(e){				var mouseX = e.pageX - canvas.offsetLeft;				var mouseY = e.pageY - canvas.offsetTop;				ball.render(context,mouseX,mouseY);				if(!ball.isPointInPath){					return;				}				var startX = mouseX - ball.x;				var startY = mouseY - ball.y;				canvas.onmousemove = function(e){					context.clearRect(0,0,width,height);					var disX = e.pageX - canvas.offsetLeft - startX;					var disY = e.pageY - canvas.offsetTop -startY;					ball.x = disX;					ball.y = disY;					ball.render(context);					canvas.style.cursor = 'pointer';				}				canvas.onmouseup = function(){					canvas.onmousemove = null;					canvas.onmouseup = null;				}			}

完整代码:

投掷

相信大家对体育项目铅球一定不陌生,我们接下来就用canvas来模拟一个铅球的投掷效果吧。

很明显,这个是在拖拽的基础上进行扩展。这一效果像小球的越界处理,重力,摩擦力等这些知识点在前面都有介绍到。

我们接下来分析一下这个投掷的效果的核心原理。从效果图上可以看出来,鼠标按下小球,然后移动小球,最后松开小球,松开的时候,小球会继续沿着鼠标最后移动的方向和速度进行运动。那么怎么确定最后一点的速度尤为重要。

先来看下mousemove事件的特性:

我在mousemove事件中不断的去绘制小圆,我们发现了一个问题,这个mousemove事件的触发是有时间间隔的,我鼠标移动的速度慢的时候,绘制的小圆密集,鼠标移动的速度快,则小球绘制的就比较稀疏了。

换句话说,如果我们找到了最后两个点的差值,那么我们就有求出鼠标松开的那一个刹那的速度了。

在mousedown事件中,定义好起始位置的坐标,并设置循环动画中不要再去渲染小球的一切动画了。在mousemove中不断的计算小球的速度,并且,我们在在最后把小球的最终位置赋值给上一个坐标。mouseup事件中清除mousemove事件和mouseup事件,然后要告诉循环函数,可以去绘制小球的动画了。

核心代码:

canvas.onmousedown = function(e){	var mouseX = e.pageX - canvas.offsetLeft;	var mouseY = e.pageY - canvas.offsetTop;	ball.render(context,mouseX,mouseY);	if(!ball.isPointInPath){		return;	}	var startX = mouseX - ball.x;	var startY = mouseY - ball.y;	var lastX = 0,//上一次小球的X坐标		lastY = 0;//上一次小球的Y坐标	canvas.onmousemove = function(e){		isMoving = true;		context.clearRect(0,0,width,height);		var disX = e.pageX - startX;		var disY = e.pageY - startY;		ball.x = disX;		ball.y = disY;		ball.render(context);		canvas.style.cursor = 'pointer';		ball.vx = disX - lastX;//计算X方向速度		ball.vy = disY - lastY;//计算Y方向速度		lastX = disX;//重新赋值上一次的X坐标		lastY = disY;//重新赋值上一次的Y坐标	}	canvas.onmouseup = function(){		isMoving = false;		canvas.onmousemove = null;		canvas.onmouseup = null;		canvas.style.cursor = 'default';	}};

在事件循环函数中,我们就是各种判断小球的位置速度方向的问题了,核心代码:

(function move(){	window.requestAnimationFrame(move);	context.clearRect(0,0,width,height);	if(!isMoving){		//小球顶部的判断		if( ball.y - ball.r <=0 ){			ball.vy *= k;			ball.y = ball.r;		}		//小球的底部判断		if(ball.y + ball.r >=height ){			ball.vy *= k;				ball.y = height - ball.r;		}		//小球左侧的判断		if(ball.x - ball.r <=0){			ball.x = ball.r			ball.vx *= k;		}		//小球右侧的判断		if(ball.x + ball.r >= width){			ball.x = width - ball.r;			ball.vx *= k;		}		//小球最终在y轴下停下来的条件		//1.离屏幕底部足够小。		//2.小球的速度足够小		if((height - (ball.y + ball.r) )< 7 && ball.vy < 3){			ball.y = height - ball.r;		}		ball.vy += ball.g;				ball.x += ball.vx;		ball.y += ball.vy;	}	ball.render(context);})()

(有需要完整的代码的请私信我)

总结:小球拖拽的原理:找到一个恒定不变的点,即找邮鼠标和小球之间的关系。mousemove事件的特性。投掷运动的原理。最后一个坐标的差值计算方法。很多JS库的原理都有着投掷运动的影子,比如:ISroll滑动,滑动的速度越大,那么滑动的距离就越远,这是一个原理。最后希望大家在开发过程中善于思考,发现问题,找出问题的本质。明白技术的原理

以上是今天所有的分享内容。喜欢的请点赞关注,不喜欢的解散。。。

这里是【畅哥聊技术】前端图形学相关技术文章,更多精彩内容持续更新中。。。

未完待续。。。

标签: #js小球与边框碰撞反弹