A main goal of interactive animation is to create a smooth user experience, where most user interaction is achieved through the mouse and touch screen.
In this blog post, I want to share some common uses of JS for moving objects, including dragging and throwing effects.
1. Using mouse events
You can decompose a mouse click event into two events: a mouse press event and a button pop-up event. Typically these two events occur simultaneously. However, sometimes after the mouse is pressed, the mouse will move for a while before popping up. This operation is called dragging, that is, pressing, moving, and releasing.
In canvas animation, mouse events can only be captured by canvas elements on the HTML DOM tree. Therefore, we need to manually calculate where the mouse event occurs on the canvas and determine whether it occurs in which Draw onto the canvas object. The mouse events that need attention are: mousedown, mousemove and mouseup. For specific details, please refer to my related blog post "Detailed Explanation of JavaScript Animation (1) - Looping and Event Monitoring".
2. Using touch events
With the popularity of touch screen devices, we are likely to need to capture the user's touch events in animations. Although a touch screen and a mouse are different devices, fortunately, capturing touch events in the DOM tree is not that different from capturing mouse events.
The touch events corresponding to the mouse events mousedown, mousemove and mouseup are touchstart, touchend and touchmove respectively.
A big difference between using fingers and a mouse is that the mouse always appears on the screen, but the fingers are not always in touch. A common approach is to introduce a custom attribute isPressed to tell us whether there is a finger touching the screen. For specific details, please refer to my related blog post "Detailed Explanation of JavaScript Animation (1) - Looping and Event Monitoring".
3. Drag event
The drag event contains three sub-events: mouse press, move, and release. By continuously updating the coordinate position of the object to follow the position of the mouse pointer, you can drag the object on the canvas element. In addition, a custom attribute isPressed is needed to indicate whether the mouse is currently pressed. The default value is false, which means the mouse is in the up state. The implementation code includes the following process:
1. Capture the mousedown event and determine whether the current mouse is within the object. When the mouse is pressed within the object, set isPressed = true;
2. Capture the mousemove event, determine in the handler when isPressed = true, and continuously update the coordinate position of the object to make it follow the mouse pointer. position to simulate the mouse dragging effect;
3. Capture the mouseup event and set isPressed to false;
HTML code is as follows:
<canvas id="canvas" width="400" height="400"></canvas>
The JavaScript code is as follows:
// 创建画球函数 function Ball() { this.x = 0; this.y = 0; this.radius = 20; this.fillStyle = "#f85455"; this.draw = function(cxt) { cxt.fillStyle = this.fillStyle; cxt.beginPath(); cxt.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, true); cxt.closePath(); cxt.fill(); } } // 获得当前鼠标位置 function getMouse(ev) { var mouse = { x: 0, y: 0 }; var event = ev || window.event; if(event.pageX || event.pageY) { x = event.x; y = event.y; }else { var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; x = event.clientX + scrollLeft; y = event.clientY + scrollTop; } mouse.x = x; mouse.y = y; return mouse; } var canvas = document.getElementById("canvas"), context = canvas.getContext("2d"), ball = new Ball(), mouse = {x: 0, y: 0}, isPressed = false; ball.x = 20; ball.y = 20; // 渲染小球 ball.draw(context); // 小球拖拽事件 canvas.addEventListener("mousedown", mouseDown, false); canvas.addEventListener("mousemove", mouseMove, false); canvas.addEventListener("mouseup", mouseUp, false); function mouseDown(ev) { // 判断当前鼠标是否在小球内 mouse = getMouse(ev); if(Math.pow(mouse.x - ball.x, 2) + Math.pow(mouse.y - ball.y, 2) <= Math.pow(ball.radius, 2)) { isPressed = true; } } function mouseMove(ev) { if(isPressed) { mouse = getMouse(ev); ball.x = mouse.x; ball.y = mouse.y; context.clearRect(0, 0, canvas.width, canvas.height); ball.draw(context); } } function mouseUp(ev) { // 标示鼠标弹起事件 isPressed = false; }
However, this example has bugs! You will soon find that when dragging, the center of the ball is at the mouse position. Especially when the mouse clicks on the edge of the ball, you will see that the center of the ball suddenly jumps to the position of the mouse cursor. On. Obviously, this seems a bit abrupt.
We can make a slight improvement:
Record the offset between the current mouse position and the center point of the ball when the mouse is pressed;
// 记录鼠标按下时,鼠标与小球圆心的偏移量 dx = mouse.x - ball.x; dy = mouse.y - ball.y;
When the mouse moves, subtract the offset recorded when the mouse is pressed from the current position of the mouse
ball.x = mouse.x - dx; ball.y = mouse.y - dy;
4. Throwing event
How to express throwing in animation? Use the mouse to select an object and drag it to move in a certain direction. After releasing the mouse, the object continues to move in the dragged direction.
When throwing an object, the velocity vector of the object must be calculated during the dragging process, and this velocity vector must be assigned to the object when the object is released. In fact, the process of calculating the velocity vector of an object while dragging is exactly the opposite of applying the velocity vector to the object. When applying a velocity vector to an object, the velocity is added to the original position of the object to calculate the new position of the object. This formula can be written as: old position + velocity vector = new position, that is Velocity vector = new position – old position.
In order to implement the throwing behavior, some changes need to be made to the previous code. First, check whether the mouse is pressed. If it is pressed, use the oldX and oldY variables to save the old x and y coordinate positions of the ball, and update the dragging speed of the ball.
The specific JavaScript code is implemented as follows:
// 创建画球函数 function Ball() { this.x = 0; this.y = 0; this.radius = 20; this.fillStyle = "#f85455"; this.draw = function(cxt) { cxt.fillStyle = this.fillStyle; cxt.beginPath(); cxt.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, true); cxt.closePath(); cxt.fill(); } } // 获得当前鼠标位置 function getMouse(ev) { var mouse = { x: 0, y: 0 }; var event = ev || window.event; if(event.pageX || event.pageY) { x = event.x; y = event.y; }else { var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; x = event.clientX + scrollLeft; y = event.clientY + scrollTop; } mouse.x = x; mouse.y = y; return mouse; } var canvas = document.getElementById("canvas"), context = canvas.getContext("2d"), ball = new Ball(), mouse = {x: 0, y: 0}, isPressed = false, oldX = 0, oldY = 0, currentX = 0, currentY = 0, vx = 0, vy = 0; ball.x = 200; ball.y = 200; // 声明鼠标按下时,鼠标与小球圆心的距离 var dx = 0, dy = 0; // 渲染小球 ball.draw(context); // 小球拖拽事件 canvas.addEventListener("mousedown", mouseDown, false); canvas.addEventListener("mousemove", mouseMove, false); canvas.addEventListener("mouseup", mouseUp, false); function mouseDown(ev) { // 判断当前鼠标是否在小球内 mouse = getMouse(ev); if(Math.pow(mouse.x - ball.x, 2) + Math.pow(mouse.y - ball.y, 2) <= Math.pow(ball.radius, 2)) { isPressed = true; // 记录鼠标按下时,鼠标与小球圆心的距离 dx = mouse.x - ball.x; dy = mouse.y - ball.y; // 获得小球拖拽前的位置 mouse = getMouse(ev); oldX = mouse.x; oldY = mouse.y; } } function mouseMove(ev) { if(isPressed) { mouse = getMouse(ev); ball.x = mouse.x - dx; ball.y = mouse.y - dy; context.clearRect(0, 0, canvas.width, canvas.height); ball.draw(context); } } function mouseUp(ev) { // 标示鼠标弹起事件 isPressed = false; // 把鼠标与圆心的距离位置恢复初始值 dx = 0; dy = 0; // 获得小球拖拽后的位置 mouse = getMouse(ev); currentX = mouse.x; currentY = mouse.y; // 更新速度向量:速度向量 = 新的位置 - 旧的位置 vx = (currentX - oldX) * 0.05; vy = (currentY - oldY) * 0.05; drawFrame(); } // 缓动动画 function drawFrame() { animRequest = window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, canvas.width, canvas.height); if(ball.x >= canvas.width - 30 || ball.x <= 30 || ball.y >= canvas.height - 30 || ball.y <= 30) { window.cancelAnimationFrame(animRequest); } ball.x += vx; ball.y += vy; ball.draw(context); }
There are still some bugs in the boundary judgment of this Demo, which will be fixed in a few days.
5. Summary
Object movement events can have many forms of total movement, but they can all be decomposed into three separate events for control: press, move, release , which correspond to mousedown, mousemove and mouseup respectively in mouse events, and touchstart, touchmove and touchend respectively in touch events. By constantly updating the coordinate position of the object so that it follows the position of the mouse pointer, the effect of dragging and throwing on the canvas element can be achieved.
The above is the detailed content of Implement moving object code through JavaScript. For more information, please follow other related articles on the PHP Chinese website!

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

SublimeText3 Linux new version
SublimeText3 Linux latest version

Notepad++7.3.1
Easy-to-use and free code editor

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

Dreamweaver CS6
Visual web development tools
