-
Notifications
You must be signed in to change notification settings - Fork 0
Sesion 6 Animaciones
- Tiempo: 2h (50 + 50 min)
- Fecha: Martes, 8-Marzo-2022
-
Objetivos de la sesión:
- Manejo básico del canvas
- Animaciones en el canvas
- Introducción
- Animaciones
- Elemento Canvas: Dibujando gráficos 2D
-
Programando animaciones en Javascript
- Bucle principal: requestAnimationFrame()
- Actualización de elementos: Física
- Borrado del canvas
- Ejemplo 8: Animando un objeto en reposo
- Ejemplo 9: Movimiento horizontal de un rectángulo
- Ejemplo 10: Rebote del rectángulo
- Ejemplo 11: Rectángulo confinado horizontalmente
- Ejemplo 12: Movimiento rectilíneo uniforme bidimensional
- Ejemplo 13: Rectángulo rebotando dentro del canvas en 2D
- El Rincón Friki
- Autor
- Licencia
- Enlaces
Las animaciones se realizan dibujando elementos en cada fotograma. Si estos fotogramas se muestran con una frecuencia suficientemente alta, se obtendrá una animación suave. Si la frecuencia no es tan alta, la animación irá "a saltos".
Seguro que alguna vez has hecho una animación en las hojas de un cuaderno. Basta con pintar en cada una de ellas un dibujo, y que entre dos hojas consecutivas el personaje o elemento cambie ligeramente de posición. Luego al pasar las hojas rápidamente se nos genera la ilusión de la animación
En este (cutre) vídeo puedes ver un ejemplo
Esto mismo lo podemos hacer digitalmente. Basta con hacer una serie de dibujos, generar las imágenes correspondientes y visualizarlas una detrás de otra. Por ejemplo, podemos tener la siguiente secuencia de imágenes:
A partir de ellas podemos tener un gif animado, o las podemos reproducir manualmente
El proceso para hacer animaciones, y que se aprecie cómo los objetos se mueven suavemente por la pantalla consiste en estos pasos:
- Actualizar las posiciones de los objetos. Cada objeto móvil tendrá unas coordenadas que van evolucionando con el tiempo. Hay que calcular sus nuevas posiciones
- Borrar la pantalla
- Pintar en la pantalla todos los objetos visibles
- Repetir
Este proceso se debe realizar al menos 60 veces por segundo (frecuencia de 60Hz). Es decir, que se dispone de unos 17ms para realizar los cálculos y pintar el nuevo frame
Si nuestra escena a animar requiere de muchos cálculos (hay muchos elementos que se mueven), podría ocurrir que se no se tenga suficiente tiempo con 17ms para recalcularlo todo y pintarlo. Si eso ocurre la frecuencia de la animación (frames/seg) será menor de 60 y el movimiento no se verá tan fluido
Un juego programado en javascript tarda los siguientes tiempos en realizar una serie de acciones:
- Cálculo de la física del juego: posiciones, velocidades y acelaraciones de los objetos: 10ms
- Borrado de la pantalla: 4ms
- Pintar cada frame: 6ms
¿Cuáles será la frecuencia de referesco? (fps)
El tiempo total que se requiere para obtener cada frame es de: 10 + 4 + 6 = 20ms. Por tanto, la frecuencia de refresco será de 1/20ms = 0.05Khz = 50Hz
En HTML disponemos de un elementos para hacer dibujos en él: El canvas (Lienzo). Dentro de un canvas podemos realizar el dibujo que queramos, incluir texto, figuras geométricas, rectas, curvas, imágenes...
Aprenderemos a usarlo mediante ejemplos
Comenzaremos creando un canvas vacío. Como siempre, lo definimos en el documento HTML, dándole un identificador (display en nuestro ejemplo). En el documento HTML situamos el elemento y su identificador, pero NO establecemos su tamaño ni su estilo. El canvas se define mediante la etiqueta <canvas>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="canvas-01.js" defer></script>
<link rel="stylesheet" href="canvas-01.css">
<title>Canvas 01</title>
</head>
<body>
<h2>Canvas</h2>
<canvas id="canvas"></canvas>
</body>
</html>
En el fichero canvas-01.css definimos su estilo: lo bordeamos con una línea negra y establecemos el color de su fondo a azul, para distinguirlo. También redondeamos sus esquinas
/* Estilo del canvas
Lo bordeamos con una línea negra y le damos fondo
azul para distinguirlo
*/
canvas {
background-color: lightblue;
border-style: solid;
border-width: 1px;
border-color: black;
border-radius: 5px;
}
En el código javascript obtenemos el elemento canvas y fijamos sus dimensiones a 200x100
console.log("Ejecutando JS...");
const canvas = document.getElementById("canvas");
//-- Definir el tamaño del convas
canvas.width = 300;
canvas.height = 100;
Esto es lo que nos aparece al abrirlo en el navegador:
Vamos a dibujar un rectángulo en el interior del canvas. Utilizaremos el mismo HTML y CSS que en el ejemplo anterior, pero cambiamos el código javascript
Para poder dibujar en el canvas hay que obtener un objeto HTML especial que permite hacer dibujos, que denominamos el contexto. El contexto lo obtenemos mediante el método getContext("2d") del canvas:
const ctx = canvas.getContext("2d");
Ahora ya podemos dibujar usando los métodos del contexto. Cada una de los objetos a dibujar los delimitaremos por los métodos ctx.beginPath()
y ctx.closePath()
. Para definir un rectángulo invocamos al método rect(), pasándole como parámetros las cordenadas x,y de la esquina superior izquierda, su anchura y su altura. En este ejemplo pintaremos el trazado de un rectángulo de dimensiones 100x50, y cuya esquina superior izquierda está situada en la coordenada (5,5). El origin de coordenadas (0,0) está situado en la esquina superior izquierda del canvas
ctx.rect(5,5, 100, 50);
Cada elemento tiene una parte interna: el relleno (fill) y un trazo (stroke). Para mostrar el interior usamos el método ctx.fill()
y para mostrar el trazo el método ctx.stroke()
El código javascript completo es el siguiente:
console.log("Ejecutando JS...");
const canvas = document.getElementById("canvas");
//-- Definir el tamaño del convas
canvas.width = 200;
canvas.height = 100;
//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");
//-- Cada objeto a dibujar lo delimitaremos
//-- por los métodos beginPath() y closePath()
ctx.beginPath();
//-- Definir un rectangulo de dimensiones 100x50,
//-- cuya esquina superior izquierda está en (5,5)
ctx.rect(5,5, 100, 50);
//-- Color de relleno del rectángulo
ctx.fillStyle = 'blue';
//-- Mostrar el relleno
ctx.fill();
//-- Mostrar el trazo del rectángulo
ctx.stroke();
ctx.closePath();
Y al ejecutarlo en el navegador nos aparece el rectángulo dentro del canvas:
Es posible dibujar tanto el relleno como el trazo, y cambiar sus propiedades. En este ejemplo modificamos el grosor del trazo para que sea mayor, utilizando la propiedad lineWidth
//-- Cambiar el tamaño de la linea del trazo
ctx.lineWidth = 4;
El programa completo es el siguiente. Primero se dibuja el relleno, con el método fill() y luego el contorno, con el método stroke()
//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");
ctx.beginPath();
//-- Definir un rectangulo de dimensiones 100x50,
//-- cuya esquina superior izquierda está en (5,5)
ctx.rect(5,5, 100, 50);
//-- Dibujar
ctx.fillStyle = 'red';
//-- Cambiar el tamaño de la linea del trazo
ctx.lineWidth = 4;
//-- Rellenar
ctx.fill();
//-- Dibujar el trazo
ctx.stroke()
ctx.closePath()
El resultado es este:
Para dibujar líneas en el canvas se usan los métodos moveTo() y lineTo(). Con el primero se define el punto inicial de la línea. Y con el segundo se pinta la línea hasta el punto destino. El grosor de los trazos de las líneas se define con la propiedad lineWidth y el color con strokeStyle
En este ejemplo se tiran 3 líneas. La primera es una horizontal. La siguiente es una horizontal seguida de una vertical, unidas
console.log("Ejecutando JS...");
const canvas = document.getElementById("canvas");
//-- Definir el tamaño del convas
canvas.width = 200;
canvas.height = 100;
//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");
ctx.beginPath();
//-- Línea horizontal
ctx.moveTo(10, 20);
ctx.lineTo(100, 20);
//-- Línea horizontal y vertical, unidas
ctx.moveTo(10, 80);
ctx.lineTo(150,80);
ctx.lineTo(150,20);
ctx.strokeStyle = 'blue';
//-- Cambiar el tamaño de la linea del trazo
ctx.lineWidth = 4;
//-- Dibujar el trazo
ctx.stroke()
ctx.closePath()
Este es el resultado:
Para dibujar círculos, circunferencias y arcos usamos el método arc(). Primero hay que invocar el método beginPath(), y luego se dibujan las curvas. En este ejemplo se dibuja un círculo con relleno amarillo y trazo azul
console.log("Ejecutando JS...");
const canvas = document.getElementById("canvas");
//-- Definir el tamaño del convas
canvas.width = 200;
canvas.height = 100;
//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");
ctx.beginPath();
//-- Dibujar un circulo: coordenadas x,y del centro
//-- Radio, Angulo inicial y angulo final
ctx.arc(100, 50, 10, 0, 2 * Math.PI);
ctx.strokeStyle = 'blue';
ctx.lineWidth = 3;
ctx.fillStyle = 'yellow';
//-- Dibujar el trazo
ctx.stroke()
//-- Dibujar el relleno
ctx.fill()
ctx.closePath()
El resultado es:
En el canvas podemos colocar dos tipos de texto, igual que el resto de objetos: Texto sólido (que está rellenado) y texto definido sólo por su trazo exterior (sin rellenado). En este ejemplo se escriben en el canvas ambos texto. Usamos los métodos fillText() y strokeText(). Con la propiedad font establecemos el tamaño y el tipo de letra
console.log("Ejecutando JS...");
const canvas = document.getElementById("canvas");
//-- Definir el tamaño del convas
canvas.width = 200;
canvas.height = 100;
//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");
//-- Texto solido
ctx.font = "25px Arial";
ctx.fillStyle = 'yellow'
ctx.fillText("Texo sólido", 10, 30);
//-- Texto trazo
ctx.strokeStyle = 'blue';
ctx.font = "35px Arial";
ctx.strokeText("Texto trazo", 5, 80);
Este es el resultado:
Dentro del canvas también podemos meter imágenes. Las imágenes las colocamos dentro del fichero HTML, pero cambiamos sus propiedades de estilo modificadas para que estén deshabilitadas y NO se muestren. Desde el programa javascript accedemos a esas imágenes y las insertamos en el canvas. En este ejemplo insertamos una única imágen. El fichero HTML es el siguiente:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="canvas-07.js" defer></script>
<link rel="stylesheet" href="canvas-07.css">
<title>Canvas 07</title>
</head>
<body>
<h2>Canvas</h2>
<canvas id="canvas"></canvas>
<img src="logo-urjc.png" alt="No encontrada" id="logo-urjc">
<p>Texto de prueba</p>
</body>
</html>
En el fichero de estilo hemos cambiado la propiedad display de la imagen a none, para que no aparezca:
/* Estilo del canvas
Lo bordeamos con una línea negra y le damos fondo
azul para distinguirlo
*/
canvas {
background-color: lightblue;
border-style: solid;
border-width: 1px;
border-color: black;
border-radius: 5px;
}
/* Imagen deshabilitada
Se usa para leerla desde js y
meterla en el canvas */
#logo-urjc {
display: none;
}
Desde el fichero javascript accedemos al elemento imagen y usando el método drawImage() lo insertamos en el canvas, haciendo que la esquina superior izquierda de la imagen esté en la coordenada (15, 18)
console.log("Ejecutando JS...");
const canvas = document.getElementById("canvas");
//-- Definir el tamaño del canvas
canvas.width = 500;
canvas.height = 250;
//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");
//-- Leer la imagen del documento html
//-- Esta deshabilitada
var logo = document.getElementById("logo-urjc");
logo.onload = ()=> {
//-- Insertar la imagen en el canvas, una vez que
//-- ya esté cargada!
ctx.drawImage(logo, 15,18);
};
Este es el resultado en el navegador:
Como ya sabemos pintar en el canvas, podemos empezar a hacer animaciones, y mover objetos por el canvas
En el bucle principal de la animación se tienen que realizar las tareas comentadas en el apartado inicial, que recordamos aquí:
- Actualizar las posiciones de los elementos: Cálculos relativos a la fisica del movimiento
- Borrar el canvas
- Pintar los elementos visibles
- Repetir
En el objeto window que nos proporciona la interfaz del navegador existe un método llamado requestAnimationFrame()
al que se le pasa como parámetro la función que hace de bucle principal, que típicamente la denominamos la función de update (actualización)
Este método se encarga de garantizar que la actualización se hace a una frecuencia de 60Hz (siempre que sea posible)
El esqueleto de nuestros programas de animación será siempre así:
//-- Declaración de variables y objetos
//-- Obtención del canvas y de los elementos HTML a usar
//-- Función principal de actualización
function update()
{
//-- Implementación del algoritmo de animación:
//-- 1) Actualizar posicion de los elementos
//-- 2) Borrar el canvas
//-- 3) Pintar los elementos en el canvas
//-- 4) Repetir
requestAnimationFrame(update);
}
//-- Otras funciones....
//-- ¡Que comience la fiesta! Hay que llamar a update la primera vez
update();
Para tener elementos móviles en nuestra animación, y que parezcan reales, utilizamos las ecuaciones de la cinemática de partículas. En cada itración del bucle principal estas ecuacioens se deben recalcular para obtener las variables de estado de nuestros elementos: posiciones, velocidades, etc...
El movimiento más sencillo de implementar es el rectilínea uniforme. Si nuestro elemento se está moviendo horizontalmente hay que actualizar su posición x sumándole la velocidad, que será una constante. Si la velocidad está definida en la constante VELX
, el cálculo a realizar es una simple suma:
//-- Fisica del movimiento rectilíneo uniforme horizontal
x = x + VELX;
El signo de la velocidad determina hacia dónde se desplaza el elemento: En el sentido positivo del eje de las Xs o en el negativo
En el caso del movimiento rectilíneo uniforme bidimensional (y no sólo en línea recta) bastará con incrementar de manera independientes sus variables x,y con las velocidades en el eje vertical y horizontal: VELX, VELY:
//-- Física del movimiento rectilineo uniforme bidimensional
x = x + VELX;
y = y + VELY;
Si lo que queremos implementar es un movimiento rectilíneo uniformemente acelerado, necesitamos una constante nueva: la aceleración en los ejes X e Y: ACCELX, ACCELY. Ahora las velocidades NO son constantes, sino que van aumentando debido a la aceleración. Los cálculos a realizar son los siguientes:
//-- Física del movimiento uniformemente acelerado bidimensional
//-- Actualizar las posiciones según la velocidad actual
x = x + velx;
y = y + vely;
//-- Actualizar las velocidades según las aceleraciones
velx = velx + ACCELX;
vely = vely + ACCELY;
Mezclando ambos tipos de movimientos: el uniformemente acelerado y el rectilíneo uniforme obtenemos otros, como el tiro parabólico
Además de las ecuaciones que describen el tipo de movimiento, necesitamos condiciones especiales adicionales para detectar colisiones y realizar rebotes
La física del rebote es también muy sencilla de programar: basta con comprobar la posición del elemento, y si ha llegado a la pared límite hay que cambiar el signo de su velocidad. Así por ejemplo si hay una bola que se mueve horizontalmente hacia una pared situada en la derecha, con velocidad velx, al llegar a la posición de la pared deberemos cambiar el signo de la velocidad en el eje horizontal:
//-- Rebote en pared vertical: cambiar el signo de la velocidad x
velx = -velx;
El borrado del canvas, para poder pintar el siguiente frame, se realiza con el método ctx.clearRect()
al que le pasamos como argumentos la posición del origen y de la esquina inferior derecha. Este método se usa para borrar un área del cavas, pero si le pasamos el área completa lo borrará todo. La instrucción a ejecutar siempre será esta:
ctx.clearRect(0, 0, canvas.width, canvas.height);
Donde canvas es el elemento HTML del canvas
En este primer ejemplo mostraremos el esquema de animación, pero aplicado a un objeto que está en reposo, es decir, con velocidad 0, por lo que no se mueve. Sin embargo el bucle principal de la animación sí está activo. La posición del elemento la podemos cambiar manualmente, desde la consola del navegador
En los ficheros html y css tenemos lo mismo que en los ejemplos anteriores:
- Fichero Ej-08.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="anim-01.js" defer></script>
<link rel="stylesheet" href="anim-01.css">
<title>Ejemplo 8: Animación</title>
</head>
<body>
<h2>Canvas</h2>
<canvas id="canvas"></canvas>
</body>
</html>
- Fichero anim-01.css
/* Estilo del canvas
Lo bordeamos con una línea negra y le damos fondo
azul para distinguirlo
*/
canvas {
background-color: lightblue;
border-style: solid;
border-width: 1px;
border-color: black;
border-radius: 5px;
}
- Fichero anim-01.js
console.log("Ejecutando JS...");
const canvas = document.getElementById("canvas");
//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;
//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");
//-- Posición del elemento a animar
let x = 0;
let y = 0;
//-- Funcion principal de animacion
function update()
{
console.log("test");
//-- Algoritmo de animacion:
//-- 1) Actualizar posiciones de los elementos
//-- Por hacer
//-- 2) Borrar el canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//-- 3) Dibujar los elementos visibles
ctx.beginPath();
ctx.rect(x, y, 20, 20);
//-- Dibujar
ctx.fillStyle = 'red';
//-- Rellenar
ctx.fill();
//-- Dibujar el trazo
ctx.stroke()
ctx.closePath();
//-- 4) Volver a ejecutar update cuando toque
requestAnimationFrame(update);
}
//-- ¡Que empiece la función!
update();
Se definen las variables x,y para almacenar la posición del elemento. En la función principal (update) se imprime un mensaje en la constola (test) para comprobar que está funcionando. Como el elemento está en reposo, no se actualiza su posición. O visto de otra manera, al ser la velocidad 0 la actualización de sus coordenadas sería:
//-- El objeto está en reposo (velocidad = 0)
x = x + 0;
y = y + 0;
El elemento a animar está constantemente siendo redibujado, pero siempre en la misma posición, por eso no vemos movimiento:
Al ejecutarlo observamos en la consola que efectivamente el mensaje de test está siendo constantemente actualizado. Si ahora desde la consola cambiamos las coordenadas del objeto, asignando valores a x,y, veremos cómo efectivamente cambia de posición, aunque sigue en reposo, sin moverse
Para lograr que el rectángulo se mueva con movimiento rectilinea uniforme, horizontalmente, sólo hay que asignarle una velocidad en x, e implementar su física correspondiente dentro de la función update()
Los cambios son los siguientes. Primero definimos la variable de la velocidad: velx
//-- Velocidad horizontal del objeto
let velx = 1;
Y ahora implementamos su física:
//-- (física del movimiento rectilineo uniforme)
x = x + velx;
Este es el código completo:
console.log("Ejecutando JS...");
const canvas = document.getElementById("canvas");
//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;
//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");
//-- Coordenadas del objeto
let x = 0;
let y = 10;
//-- Velocidad horizontal del objeto
let velx = 1;
//-- Funcion principal de animacion
function update()
{
console.log("test");
//-- Algoritmo de animacion:
//-- 1) Actualizar posicion del elemento
//-- (física del movimiento rectilineo uniforme)
x = x + velx;
//-- 2) Borrar el canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//-- 3) Dibujar los elementos visibles
ctx.beginPath();
ctx.rect(x, y, 20, 20);
//-- Dibujar
ctx.fillStyle = 'red';
//-- Rellenar
ctx.fill();
//-- Dibujar el trazo
ctx.stroke()
ctx.closePath();
//-- 4) Volver a ejecutar update cuando toque
requestAnimationFrame(update);
}
//-- ¡Que empiece la función!
update();
Al recargar la página veremos cómo el rectángulo rojo se mueve hacia la derecha
Desde la consola podemos controlar su física. Asignamos el valor x = 0 para volver al inicio, y cambiamos la velocidad a diferentes valores para comprobar que efectivamente se mueve más rápidamente: velx = 2, velx = 5,...
¡Ya tenemos nuestra primera animación! 😀️
Vamos a modificar la física para que cuando el rectángulo alcance la posición de la derecha del canvas, rebote y vuelva hacia atrás. Para lograr este rebote hay que detectar primero cuándo se alcanza el borde derecho y luego cambiar de signo su velocidad
Añadimos esto en la física:
//-- Comprobar colisión con borde derecho
//-- Si se alcanza la anchura del canvas, se cambia la velocidad
//-- de signo (rebote)
if (x >= canvas.width) {
velx = -velx;
}
También modificamos la velocidad inicial a 2, para que vaya más rápido. El código final que nos queda es este:
console.log("Ejecutando JS...");
const canvas = document.getElementById("canvas");
//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;
//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");
//-- Coordenadas del objeto
let x = 0;
let y = 10;
//-- Velocidad horizontal del objeto
let velx = 2;
//-- Funcion principal de animacion
function update()
{
console.log("test");
//-- Algoritmo de animacion:
//-- 1) Actualizar posicion del elemento
//-- (física del movimiento rectilineo uniforme)
//-- Comprobar colisión con borde derecho
//-- Si se alcanza la anchura del canvas, se cambia la velocidad
//-- de signo (rebote)
if (x >= canvas.width) {
velx = -velx;
}
//-- Actualizar la posición
x = x + velx;
//-- 2) Borrar el canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//-- 3) Dibujar los elementos visibles
ctx.beginPath();
ctx.rect(x, y, 20, 20);
//-- Dibujar
ctx.fillStyle = 'red';
//-- Rellenar
ctx.fill();
//-- Dibujar el trazo
ctx.stroke()
ctx.closePath();
//-- 4) Volver a ejecutar update cuando toque
requestAnimationFrame(update);
}
//-- ¡Que empiece la función!
update();
Al recargar la página vemos su funcionamiento. Efectivamente ahora el rectángulo rebota al llegar al extremo derecho del canvas:
Para que nuestro rectángulo se quede confinado dentro del canvas, rebotando a izquierda y derecha indefinidamente, sólo hay que añadir la condición de comprobación de que el borde izquierdo se ha alcanzado. Esto ocurre cuando su posición x sea menor que 0
//-- Condicion de rebote en extremos del canvas
if (x < 0 || x >= (canvas.width - 20) ) {
velx = -velx;
}
- Código completo:
console.log("Ejecutando JS...");
const canvas = document.getElementById("canvas");
//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;
//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");
//-- Coordenadas del objeto
let x = 0;
let y = 10;
//-- Velocidad horizontal del objeto
let velx = 3;
//-- Funcion principal de animacion
function update()
{
console.log("test");
//-- Algoritmo de animacion:
//-- 1) Actualizar posicion del elemento
//-- (física del movimiento rectilineo uniforme)
//-- Condicion de rebote en extremos del canvas
if (x < 0 || x >= (canvas.width - 20) ) {
velx = -velx;
}
//-- Actualizar la posición
x = x + velx;
//-- 2) Borrar el canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//-- 3) Dibujar los elementos visibles
ctx.beginPath();
ctx.rect(x, y, 20, 20);
//-- Dibujar
ctx.fillStyle = 'red';
//-- Rellenar
ctx.fill();
//-- Dibujar el trazo
ctx.stroke()
ctx.closePath();
//-- 4) Volver a ejecutar update cuando toque
requestAnimationFrame(update);
}
//-- ¡Que empiece la función!
update();
En esta animación vemos el funcionamiento. Ahora nuestro rectángulo está confinado dentro de los límites del canvas...
Para que nuestro rectángulo se mueva en línea recta pero en cualquier dirección, y no sólo horizontalmente, hay que superponer el movimiento en el eje y. Tenemos que definir ambas velocidades: la horizontal y la vertical. Vamos a darle un valor bajo a la vertical:
//-- Velocidades del objeto
let velx = 3;
let vely = 0.2;
Y su física hay que añadir la actualización de la variable y:
//-- Actualizar la posición
x = x + velx;
y = y + vely;
- Código completo:
console.log("Ejecutando JS...");
const canvas = document.getElementById("canvas");
//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;
//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");
//-- Coordenadas del objeto
let x = 0;
let y = 10;
//-- Velocidades del objeto
let velx = 3;
let vely = 0.2;
//-- Funcion principal de animacion
function update()
{
console.log("test");
//-- Algoritmo de animacion:
//-- 1) Actualizar posicion del elemento
//-- (física del movimiento rectilineo uniforme)
//-- Condicion de rebote en extremos del canvas
if (x < 0 || x >= (canvas.width - 20) ) {
velx = -velx;
}
//-- Actualizar la posición
x = x + velx;
y = y + vely;
//-- 2) Borrar el canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//-- 3) Dibujar los elementos visibles
ctx.beginPath();
ctx.rect(x, y, 20, 20);
//-- Dibujar
ctx.fillStyle = 'red';
//-- Rellenar
ctx.fill();
//-- Dibujar el trazo
ctx.stroke()
ctx.closePath();
//-- 4) Volver a ejecutar update cuando toque
requestAnimationFrame(update);
}
//-- ¡Que empiece la función!
update();
En la animación vemos el resultado. Nuestro objeto se mueve también verticalmente, pero con velocidad más lenta
Para terminar, haremos que nuestro rectángulo se quede confinado dentro del canvas, rebotando tanto en los límites verticales como horizontales del canvas. Basta con añadir las condiciones para la coordenada y:
//-- Condición de rebote en extremos horizontales del canvas
if (y <= 0 || y > 80) {
vely = -vely;
}
Además cambiamos los valores de las velocidades, para que se mueva más rápido por el eje y:
//-- Velocidades del objeto
let velx = 3;
let vely = 1;
El código completo queda así:
console.log("Ejecutando JS...");
const canvas = document.getElementById("canvas");
//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;
//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");
//-- Coordenadas del objeto
let x = 0;
let y = 10;
//-- Velocidades del objeto
let velx = 3;
let vely = 1;
//-- Funcion principal de animacion
function update()
{
console.log("test");
//-- Algoritmo de animacion:
//-- 1) Actualizar posicion del elemento
//-- (física del movimiento rectilineo uniforme)
//-- Condicion de rebote en extremos verticales del canvas
if (x < 0 || x >= (canvas.width - 20) ) {
velx = -velx;
}
//-- Condición de rebote en extremos horizontales del canvas
if (y <= 0 || y > 80) {
vely = -vely;
}
//-- Actualizar la posición
x = x + velx;
y = y + vely;
//-- 2) Borrar el canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//-- 3) Dibujar los elementos visibles
ctx.beginPath();
ctx.rect(x, y, 20, 20);
//-- Dibujar
ctx.fillStyle = 'red';
//-- Rellenar
ctx.fill();
//-- Dibujar el trazo
ctx.stroke()
ctx.closePath();
//-- 4) Volver a ejecutar update cuando toque
requestAnimationFrame(update);
}
//-- ¡Que empiece la función!
update();
Y este es el resultado:
Jesús Parrado Alameda (jesusgpa)
- Creado a partir del contenido generado por el profesor Jose María Cañas
- Creado a partir del contenido generado por el profesor Juan Gonzalez-Gomez
- S0: Presentación
- S1: Introducción a las tecnologías web
- S2: HTML
- S3: CSS
- S4: Javascript
- S5: Javascript II
- S6: Animaciones 2D
- S7: HTML (Parte-2)
- S8: Codif. Multimedia I
- S9: Codif. Multimedia (II)
- S10: Com. Multimedia I
- S11: Comunicac. Multimedia (II)
- L12: Realizador de TV
- L13: Laboratorio / Tutorías
- 2018-Mayo-18: Ordinario: (Enunciado), (Soluciones)
- 2019-Mayo-09: Ordinario: (Enunciado), (Soluciones)
- 2019-Junio-20: Extra: (Enunciado),(Soluciones)
- 2021-Abril-13: Parcial 1 Ordinario (Enunciado y Soluciones)
- 2021-Junio-01: Parcial 2 Ordinario (Enunciado y Soluciones)
- 2021-Junio-29: Extra (Enunciado y Soluciones)
- [2022 - 15 de Marzo: Parcial 1 ]
- [2022 - 19 de Mayo: Parcial 2 ]
- [2022 - 2 de Julio: Final. Conv. extraordinaria ]