Está en la página 1de 24

1.

- Notación de Objetos JavaScript


2.- Estructura del JSON
3.- Arreglos como JSON

1.- Notación de Objetos JavaScript


JavaScript Object Notation (JSON) es un formato basado en texto estándar
para representar datos estructurados en la sintaxis de objetos de JavaScript.
Es comúnmente utilizado para transmitir datos en aplicaciones web (por
ejemplo: enviar algunos datos desde el servidor al cliente, así estos datos
pueden ser mostrados en páginas web, o viceversa).
JSON es un formato de datos basado en texto que sigue la sintaxis de objeto
de JavaScript, popularizado por Douglas Crockford. Aunque es muy parecido a
la sintaxis de objeto literal de JavaScript, puede ser utilizado
independientemente de JavaScript, y muchos ambientes de programación
poseen la capacidad de leer (analizar; parse) y generar JSON.
Los JSON son cadenas. Cuando se quiere transmitir datos a través de una red
se deben convertir a un objeto nativo de JavaScript para poder acceder a esos
datos. Ésto no es un problema, dado que JavaScript posee un objeto global

Nota: Convertir una cadena a un objeto nativo se denomina


parsing, mientras que convertir un objeto nativo a una cadena
para que pueda ser transferido a través de la red se denomina
stringification.

JSON que tiene los métodos disponibles para convertir entre ellos.
Un objeto JSON puede ser almacenado en su propio archivo, que es
básicamente sólo un archivo de texto con una extension .json, y una MIME type
de application/json.

2.- Estructura del JSON


Como se describió previamente, un JSON es una cadena cuyo formato
recuerda al de los objetos literales JavaScript. Es posible incluir los mismos
tipos de datos básicos dentro de un JSON que en un objeto estándar de
JavaScript - cadenas, números, arreglos, booleanos, y otros literales de objeto.
La siguiente figura representa la estructura de un objeto en JSON

Como puedes ver, es una secuencia de parejas propiedad-valor separadas por


una coma.

Empezamos creando un fichero JSON con cualquier editor de texto plano (Te
aconsejo utilizar ALTOVA). El fichero está guardado como alumnos.JSON y su
contenido es el siguiente

Cuyo equivalente en XML es el siguiente


Como podemos ver, el objeto json no tiene nombre, simplemente es una
colección de datos sin estructura alguna. Cuando lo leemos desde algún
lenguaje como javascript o PHP tendremos que cargarlo en alguna variable con
nombre. Al pasarlo a XML, el root de la estructura se asigna directamente como
<json>.
El segundo elemento esencial en la estructura de un JSON es el array. Su
sintaxis es la siguiente:

Un array es una secuencia de valores separados por una coma y encerrados


en un par de corchetes.

Para entender el empleo de arrays veamos el siguiente ejemplo

Se trata de un objeto con un par de variable (libro) y valor. La diferencia es que


aquí, el valor es a su vez un array que tiene objetos nuevos definidos como
parejas de variable-valor llamadas autor-título.
Su equivalente en XML sería el siguiente
En el cual, al igual que en el caso anterior, el root se asigna por defecto como
<json>

Podemos resumir indicando que en la estructura de un json aparecen parejas


de variable-valor junto con seis caracteres estructurales que son los indicados
en la figura.
Esto permite construir una jerarquía de datos, como ésta:

Cuyo fichero json (superhéroes.json) es el siguiente

{
"squadName": "Super hero squad",
"homeTown": "Metro City",
"formed": 2016,
"secretBase": "Super tower",
"active": true,
"members": [
{
"name": "Molecule Man",
"age": 29,
"secretIdentity": "Dan Jukes",
"powers": [
"Radiation resistance",
"Turning tiny",
"Radiation blast"
]
},
{
"name": "Madame Uppercut",
"age": 39,
"secretIdentity": "Jane Wilson",
"powers": [
"Million tonne punch",
"Damage resistance",
"Superhuman reflexes"
]
},
{
"name": "Eternal Flame",
"age": 1000000,
"secretIdentity": "Unknown",
"powers": [
"Immortality",
"Heat Immunity",
"Inferno",
"Teleportation",
"Interdimensional travel"
]
}
]
}

Si se carga este objeto en un programa de JavaScript, traducido (parsed) en


una variable llamada superHeroes por ejemplo, se podría acceder a los datos
que contiene utilizando la misma notación de punto/corchete que se revisó en
el tema JavaScript object basics. Por ejemplo:
superHeroes.homeTown
superHeroes['active']

Para acceder a los datos que se encuentran más abajo en la jerarquía,


simplemente se debe concatenar los nombres de las propiedades y los índices
de arreglo requeridos. Por ejemplo, para acceder al tercer superpoder del
segundo héroe registrado en la lista de miembros, se debería hacer esto:

superHeroes['members'][1]['powers'][2]

1. Primero el nombre de la variable — superHeroes.


2. Dentro de esta variable para acceder a la propiedad members utilizamos
["members"].
3. members contiene un arreglo con varios objetos. Para acceder al
segundo objeto dentro de este arreglo se utiliza [1].
4. Dentro de este objeto, para acceder a la propiedad powers utilizamos
["powers"].
5. Dentro de la propiedad powers existe un arreglo que contiene los
superpoderes del héroe seleccionado. Para acceder al tercer superpoder se
utiliza [2].

.
3.- Arreglos como JSON
Anteriormente se mencionó que el texto JSON básicamente se parece a un
objeto JavaScript, y esto es en gran parte cierto. La razón de esto es que un
arreglo es también un JSON válido, por ejemplo:

[
{
"name": "Molecule Man",
"age": 29,
"secretIdentity": "Dan Jukes",
"powers": [
"Radiation resistance",
"Turning tiny",
"Radiation blast"
]
},
{
"name": "Madame Uppercut",
"age": 39,
"secretIdentity": "Jane Wilson",
"powers": [
"Million tonne punch",
"Damage resistance",
"Superhuman reflexes"
]
}
]

Éste es un JSON perfectamente válido. Para acceder a esta version traducida


se debe comenzar con un índice de arreglo, por ejemplo[0]["powers"][0].
Otras notas
Sección
• JSON es sólo un formato de datos — contiene sólo propiedades, no
métodos.
• JSON requiere usar comillas dobles para las cadenas y los nombres de
propiedades. Las comillas simples no son válidas.
• Una coma o dos puntos mal ubicados pueden producir que un archivo
JSON no funcione. Se debe ser cuidadoso para validar cualquier dato que se
utilizar (aunque los JSON generados por computador tienen menos
probabilidades de tener errores, mientras el programa generador trabaje
adecuadamente). Es posible validar JSON utilizando una aplicación como
JSONLint.
• JSON Puede tomar la forma de cualquier tipo de datos que sea válido
para ser incluido en un JSON, no sólo arreglos u objetos. Asi, por ejemplo, una
cadena o un número único podrían ser objetos JSON válidos.
• A diferencia del código JavaScript en que las propiedades del objeto
pueden no estar entre comillas, en JSON, sólo las cadenas entre comillas
pueden ser utilizadas como propiedades.
Aprendizaje activo: Trabajando a través de un ejemplo de JSON
Sección
A continuación se muestra un ejemplo de cómo podemos utilizar algunos datos
JSON en un sitio web.
Para comenzar
Sección
Haga una copia local de los archivos heroes.html y style.css. El último contiene
un CSS simple para dar estilo a la página, mientras el primero contiene un
HTML muy sencillo:
<header>
</header>

<section>
</section>
Además de un elemento <script> que contiene el código JavaScript que se
escribirá en este ejercicio. En este momento sólo contiene dos líneas, que
hacen referencia a los elementos <header> y <section> y los almacena en
variables:
var header = document.querySelector('header');
var section = document.querySelector('section');
Los datos JSON se encuentran disponibles en GitHub en el siguiente enlace
https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json.
Los datos se cargarán en esta página, y se desplegarán a través de la
manipulación del DOM, como ésta:

Obteniendo el JSON
Sección
Para obtener el JSon, se utilizara un API llamado XMLHttpRequest (a menudo
llamado XHR). Éste en un objeto JavaScript muy útil que permite realizar
solicitudes de red para recuperar recursos desde un servidor vía JavaScript
(por ejemplo: imágenes, texto, JSON, incluso pequeños HTML), con lo que es
posible actualizar pequeñas secciones de contenido sin tener que volver a
cargar la página entera. Con ello se obtienen páginas web más interactivas,
pero está fuera del alcance de este artículo, para ser enseñado con mucho
detalle.
1. Para empezar, se debe almacenar la URL del JSON que se quiere
recuperar en una variable. Agregue lo siguiente al final del código JavaScript:
var requestURL = 'https://mdn.github.io/learning-
area/javascript/oojs/json/superheroes.json';
• • Para crear una solicitud, se necesita crear una nueva instancia de objeto
de solicitud desde el constructorXMLHttpRequest, utilizando la palabra clave
new. Agregue lo siguiente a continuación de la última línea:
var request = new XMLHttpRequest();
• • Ahora es necesario abrir una nueva solicitud utilizando el método open().
Agregue la siguiente línea:
request.open('GET', requestURL);
• Esto toma al menos dos parámetros — Existen otros parámetros opcionales
disponibles. Sólo se requieren los dos mandatorios para este ejemplo:
• El método HTTP a usar cuando se hace una solicitud en red. En este
caso GET es adecuado, dado que sólo se estan recuperando algunos datos
simples.
• La URL a la que se realiza la solicitud — esta es la URL del archivo que
se almacenó antes.
• Luego, agregue las siguientes dos lineas — acá se está programando el
responseType al JSON, de esta forma ese XHR sabe que el servidor estará
retornando JSON, y que esto debería ser convertido en segundo plano en un
objeto JavaScript. Entonces se envía la solicitud con el método send():
request.responseType = 'json';
request.send();
• • La última parte de esta sección comprende la espera por la respuesta a
retornar desde el servidor y luego, manejarla. Agregue el siguiente código bajo
el código previo:
request.onload = function() {
var superHeroes = request.response;
populateHeader(superHeroes);
showHeroes(superHeroes);
}
5.
En este punto se está almacenando la respuesta a la solicitud (disponible en la
propiedad response) en una variable llamada superHeroes; esta variable ahora
contendrá el objeto JavaScript basado en el JSON. Luego se pasa el objeto a
dos llamadas de función — la primera llenara el <header> con los datos
correctos, mientras la segunda creará una tarjeta de información para cada
héroe en el equipo, y la insertará en <section>.
Se ha contenido el código en un manejador de eventos que se activa cuando el
evento carga gatilla el objeto solicitud (ver onload) — esto es porque el evento
carga gatilla cuando la respuesta ha sido retornada de forma exitosa; de esta
manera se garantiza que request.response estará definitivamente disponible
cuando se intente hacer algo con ella.
Poblando el encabezado
Sección
Se han obtenido los datos desde el JSON y convertidos en un objeto de
JavaScript. Ahora, se utilizarán estos datos escribiendo las dos funciones que
fueron referenciadas previamente. Antes que todo, agregue la siguiente
definición de función a continuación del código previo:
function populateHeader(jsonObj) {
var myH1 = document.createElement('h1');
myH1.textContent = jsonObj['squadName'];
header.appendChild(myH1);

var myPara = document.createElement('p');


myPara.textContent = 'Hometown: ' + jsonObj['homeTown'] + ' // Formed: ' +
jsonObj['formed'];
header.appendChild(myPara);
}
Se ha llamado al parámetro jsonObj, para recordar que este es un objeto
JavaScript originado desde un JSON. Primero se crea un elemento <h1> con
createElement(), se asigna su textContent igual a la propiedad squadName del
objeto, luego se agrega al encabezado utilizandoappendChild(). A continuación
se realiza una operación muy parecida en un párrafo: se crea, se asigna su
contenido de texto y se agrega al encabezado. La única diferencia es que su
texto se asigna a una cadena concatenada que contiene las propiedades
homeTown y formed del objeto.
Creación de las tarjetas de información del héroe
Sección
Luego, agregue la siguiente función al final del código, que crea y muestra las
tarjetas de los superhéroes:
function showHeroes(jsonObj) {
var heroes = jsonObj['members'];

for (var i = 0; i < heroes.length; i++) {


var myArticle = document.createElement('article');
var myH2 = document.createElement('h2');
var myPara1 = document.createElement('p');
var myPara2 = document.createElement('p');
var myPara3 = document.createElement('p');
var myList = document.createElement('ul');

myH2.textContent = heroes[i].name;
myPara1.textContent = 'Secret identity: ' + heroes[i].secretIdentity;
myPara2.textContent = 'Age: ' + heroes[i].age;
myPara3.textContent = 'Superpowers:';

var superPowers = heroes[i].powers;


for (var j = 0; j < superPowers.length; j++) {
var listItem = document.createElement('li');
listItem.textContent = superPowers[j];
myList.appendChild(listItem);
}

myArticle.appendChild(myH2);
myArticle.appendChild(myPara1);
myArticle.appendChild(myPara2);
myArticle.appendChild(myPara3);
myArticle.appendChild(myList);

section.appendChild(myArticle);
}
}
Para empezar, se almacena la propiedad members del objeto JavaScript en
una nueva variable. Este arreglo contiene múltiples objetos que contienen la
información para cada héroe.
A continuación, se utiliza un ciclo for para recorrer cada objeto en el arreglo.
Para cada uno:
1. Se crean varios elementos nuevos: un<article>, un <h2>, tres <p>s, y
una <ul>.
2. Se asigna al <h2> para que muestre el name del héroe.
3. Se completan los tres párrafos con su secretIdentity, age, y una línea
que diga "Superpowers:" para introducir la información de la lista.
4. Se almacena la propiedad powers en otra variable nueva llamada
superPowers — que contiene un arreglo que lista los superpoderes del héroe
actual.
5. Para recorrer los superpoderes del héroe, se utiliza otro ciclo for — para
cada uno se crea un elemento <li>, se asigna el superpoder a él, y luego se
pone el listItem dentro del elemento <ul> (myList) utilizando appendChild().
6. Lo último es agregar los <h2>, <p>s, y <ul> dentro del <article>
(myArticle), luego se agrega <article> dentro de <section>. El orden en que las
cosas son agregadas es importante, dado que este es el orden en ell que
aparecerán dentro del HTML.
Nota: Si tiene problemas en lograr que el ejemplo funcione, intente con el
código fuente heroes-finished.html (vea también running live.)
Nota: Si encuentra dificultades en seguir la notacion de punto/corchete que se
utiliza para acceder a los objetos de JavaScript, puede ser útil tener el archivo
superheroes.json abierto en otra pestaña o en su editor de texto, y revisarlo
mientras observa el código JavaScript. También puede referirse al artículo
JavaScript object basics para mayor información sobre la notación de punto y
corchete.
Conversiones entre objetos y texto
Sección
El ejemplo anterior era simple en términos de acceder al objeto JavaScript,
porque se programó la solicitud XHR para convertir el JSON de respuesta
directamente en un objeto de JavaScript utilizando:
request.responseType = 'json';
En algunas ocasiones, se recibirá una cadena JSON sin procesar, y será
necesario convertirla en un objeto. Y cuando sea necesario enviar un objeto
Javascript a través de la red, será necesario convertirlo a un JSON (una
cadena) antes de ser enviado. Afortunadamente, estos dos problemas son muy
comunes en el desarrollo web por lo que un objeto JSON integrado está
disponible en los navegadores, que contiene los siguientes dos métodos:
• parse(): Acepta una cadena JSON como parámetro, y devuelve el objeto
JavaScript correspondiente.
• stringify(): Acepta un objeto como parámetro, y devuelve la forma de
cadena JSON equivalente.
El primer método se puede observar en el ejemplo heroes-finished-json-
parse.html (vea el código fuente) — que realiza exactamente lo mismo que el
ejemplo que se construyó previamente, excepto porque se determinó que el
XHR devolviera el texto JSON sin procesar, luego se utiliza parse() para
convertirlo en un objeto JavaScript. El extracto del código es el siguiente:
request.open('GET', requestURL);
request.responseType = 'text'; // now we're getting a string!
request.send();

request.onload = function() {
var superHeroesText = request.response; // get the string from the response
var superHeroes = JSON.parse(superHeroesText); // convert it to an object
populateHeader(superHeroes);
showHeroes(superHeroes);
}
Como es de suponer, stringify() trabaja de la forma opuesta. Intente ingresar
las siguientes líneas en la consola de JavaScript de su navegador para verlo en
acción:
var myJSON = { "name": "Chris", "age": "38" };
myJSON
var myString = JSON.stringify(myJSON);
myString
En este caso, se ha creado un objeto JavaScript, luego se comprueba lo que
contiene, y entonces se convierte en una cadena JSON utilizando stringify() —
guardando el valor retornado en una variable nueva — y comprobándolo
nuevamente.
Resumen
Sección
En este artículo, se ha entregado una guía simple para utilizar JSON en sus
programas, incluyendo cómo crear y leer JSON, y cómo acceder a los datos
almacenados en él. En el artículo siguiente, se verá JavaScript orientado a
objetos.
Ejercicio práctico de construcción de objetos

• •
• Editar
• •
Esta traducción está incompleta. Por favor, ayuda a traducir este artículo del
inglés.
Anterior Overview: Objects Siguiente

En los artículos anteriores se explicó lo fundamental de la teoría de los objetos


en JavaScript asi como su sintaxis, para que Usted tenga un punto de partida
sólido. En ste artículo, desarrollaremos un ejercicio práctico para ganar
experiencia en la programación de objetos en JavaScript, con un resultado
divertido y colorido.
Pre-requisitos: Conocimientos básicos de computadores. Entendimiento
básico de HTML y CSS. Familiaridad con los conceptos básicos de JavaScript
(vea First steps y Building blocks) y OOJS (vea Introduction to objects).
Objetivos: Ganar experiencia en el uso de objetos y el uso de programación
orientada a objetos en un contexto realista.
Lanzemos algunas pelotas
Sección
Es éste artículo escribiremos un programa demo del juego clásico de pelotas
que rebotan para mostrar la gran útilidad de los objetos en JavaScript. En éste
demo las pelotas rebotaran en la pantalla y cambiaran de color cuando
choquen unas con otras. Así, al final del ejemplo tendremos algo como esto:

En este ejemplo se utilizará Canvas API para dibujar las pelotas en la pantalla
y la API requestAnimationFrame para animar todo el contenido de la pantalla.
No es necesario que conozca estas funciones previamente. Esperamos que al
final de este artículo, quizás pueda estar interesado en explorar su uso y
capacidades más en detalle. Durante este desarrollo usaremos objetos y
algunas técnicas para hacer que las pelotas puedan rebotar en los bordes y
comprobar cuando choquen entre ellas (ésto se conoce como detección de
colisiones).
Primeros pasos
Sección
Para comenzar haga una copia en su computador de los archivos: index.html,
style.css, y main.js. Estos contienen:
1. Un documento HTML sencillo con un elemento <h1>, un elemento
<canvas> en el que podamos dibujar los gráficos y otros elementos para aplicar
los estilos CSS y el código JavaScript.
2. Algunos estilos sencillos que servirán para ubicar el elemento <h1>,
ocultar la barra de desplazamiento y los margenes del borde de la página (para
que luzca mejor).
3. Un archivo JavaScript que sirve para definir el elemento <canvas> y las
funciones que vamos a usar.
La primera parte del script es:
var canvas = document.querySelector('canvas');

var ctx = canvas.getContext('2d');

var width = canvas.width = window.innerWidth;


var height = canvas.height = window.innerHeight;
Este script obtiene una referencia del elemento <canvas>, luego llama al
método getContext() para definir un contexto en el cual se pueda comenzar a
dibujar. La resultado de la variable (ctx) es el objeto que representa
directamente el área de dibujo del <canvas> y permite dibujar elementos 2D en
él.
A continuación se da valor a las variables width and height que corresponden al
ancho y alto del elemento canvas (representado por las propiedades
canvas.width y canvas.height), de manera que el alto y ancho coincidan con el
alto y ancho del navegador (viewport) cuyos valores se obtienen directamente
de las propiedades window.innerWidth y window.innerHeight.
Puede ver que en el código se encadenan varias asignaciones, para obtener
valores más rápidamente. Esto se puede hacer.
La última parte del script, es la siguiente:
function random(min, max) {
var num = Math.floor(Math.random() * (max - min + 1)) + min;
return num;
}
Esta función recibe dos números como argumentos de entrada (valor mínimo y
maximo) y devuelve un número aleatorio entre ellos.
Modelando una pelota en nuestro programa
Sección
Nuestro programa tendrá montones de pelotas rebotando por toda la pantalla.
Ya que todas las pelotas tendrán el mismo comportamiento, tiene sentido
representarlas con un objeto. Empezamos definiendo un constructor para el
objeto pelota (Ball), en nuestro código.
function Ball(x, y, velX, velY, color, size) {
this.x = x; //posición horizontal
this.y = y; //posición vertical
this.velX = velX; //velocidad horizontal
this.velY = velY; //velocidad vertical
this.color = color; //color
this.size = size; //tamaño
}
Aquí incluimos algunos parámetros que serán las propiedades que cada pelota
necesita para funcionar en nuestro programa:
• las coordenadas x e y— correspondientes a la posición horizontal y
vertical de la pelota. Estas pueden variar entre un valor 0 (el la esquina superior
izquierda) hasta el valor del ancho y alto del navegador ( esquina inferior
derecha).
• velocidad horizontal y vertical (velX y velY) — cada pelota tiene una
velocidad vertical y horizontal; en la parte práctica, estos valores se añadirán a
las coordenadas x e y cuando animemos el movimiento de las pelotas, así en
cada incremento de visualización de frame, se desplazarán esta cantidad.
• color — cada pelota posee un color.
• size — cada pelota tiene un tamaño, este será su radio en pixels.
Con esto se resuelven las propiedades del objeto, ¿pero qué hacemos con los
métodos? Ya que queremos que las pelotas realicen algo en nuestro programa.
Dibujando las pelotas
Sección
Para dibujar, añadiremos el siguiente método draw() al prototipo del objeto
Ball():
Ball.prototype.draw = function() {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fill();
}
Con esta función cada objeto pelota Ball() puede dibujarse en la pantalla
utilizando el contexto 2D definido anteriormente (ctx)
• Primero usamos beginPath() para declarar que empezaremos a dibujar
una forma en el canvas.
• A continuación usamos el fillStyle para definir el color de la forma.
Haremos que coincida con la propiedad color.
• A continuación con el método arc() se traza un arco. Sus parámetros
son:
o La posición x e y del centro del arco. Corresponderán a las coordenadas
del centro de la pelota.
o El radio del arco - que vendrá dado por la propiedad de tamaño size de
la pelota.
o Los últimos dos parámetros especifican el comienzo y final del arco en
radianes. En este caso se especifican 0 y 2*PI . Que corresponden a 0 y 360
grados. Esto es un circulo completo. Si se quisiese especificar únicamente
medio círculo, 180 grados, se especificaría PI.
• Por último con el método fill() se finaliza el dibujo, y rellena el área de la
curva especificada, según se indico con el fillStyle.
Ya se puede empezar a testear el objeto.
1. Guarde el código hasta ahora, y cargue el archivo HTML en un
navegador.
2. Abra la consola de JavaScript en el navegador, y refresque la página,
para que el tamaño del canvas modifique sus dimensiones adaptándose al
viewport con la consola abierta.
3. Teclee lo siguiente en la consola para crear una nueva pelota.
var testBall = new Ball(50, 100, 4, 4, 'blue', 10);
• • Pruebe a llamar a las variables miembro:
testBall.x
testBall.size
testBall.color
testBall.draw()
4.
5. Al teclear la última línea, debería ver que la pelota se dibuja en alguna
parte del canvas.
Actualizando los datos de la pelota
Sección
Ahora podemos dibujar una pelota en una posición dada, pero para empezar a
moverla, se necesita una función de actualización de algún tipo. Podemos
añadir el código a continuación, al final del archivo de JavaScript, para añidir un
método de actualización update() en el prototipo de la clase Ball()
Ball.prototype.update = function() {
if ((this.x + this.size) >= width) {
this.velX = -(this.velX);
}

if ((this.x - this.size) <= 0) {


this.velX = -(this.velX);
}

if ((this.y + this.size) >= height) {


this.velY = -(this.velY);
}

if ((this.y - this.size) <= 0) {


this.velY = -(this.velY);
}

this.x += this.velX;
this.y += this.velY;
}
Las cuatro primeras partes de la función verifican si la pelota a alcanzado el
borde del canvas. Si es así, se invierte la dirección de la velocidad, para que la
pelota se mueva en la dirección contraria. Así, si la pelota va hacia arriba, (velY
positiva) , entonces la velocidad vertical es cambiada, para que se mueva hacia
abajo (velY negativa).
Los cuatro posibles casos son:
• Verificar si la coordenada x es mayor que el ancho del canvas (la pelota
está saliendo por el borde derecho).
• Verificar si la coordenada x es menor que la coordenada 0 (la pelota está
saliendo por el borde izquierdo)
• Verificar si la coordenada y es mayor que la altura del canvas (la pelota
está saliendo por el borde inferior).
• Verificar si la coordenada y es menor que la coordenada 0 ( la pelota
está saliendo por el borde superior).
En cada caso, se ha tenido en cuenta el tamaño (size) de la pelota en los
cálculos, ya que las coordenadas x e y corresponden al centro de la pelota,
pero lo que queremos ver es el borde de la pelota cuando choca con el
perímetro del canvas — que la pelota rebote, cuando está a medio camino
fuera de el —.
Las dos últimas líneas de código, suman la velocidad en x (velX) al valor de la
coordenada x , y el valor de la velocidad en y (velY) a la coordenada y — con
esto se consigue el efecto de que la pelota se mueva cada vez que este
método es llamado.
Llegados a este punto: ¡continuemos, con las animaciones!
Animando las pelotas
Sección
Hagamos esto divertido! Ahora vamos a empezar a añadir pelotas al canvas, y
animándolas.
1. Primero, necesitamos algún sitio donde guardas las pelotas. El siguiente
arreglo hará esta función — añádela al final de tu código.
var balls = [];
Todos los programas que generan animaciones normalmente tienen un bucle
de animación, que sirve para actualizar los datos del programa, para entonces
generar la imagen correspondiente; esta es la estrategia básica para la mayor
parte de juegos y programas similares.
2. Añadamos las siguientes instrucciones al final del código:
function loop() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';
ctx.fillRect(0, 0, width, height);

while (balls.length < 25) {


var size = random(10,20);
var ball = new Ball(
// la posición de las pelotas, se dibujará al menos siempre
// como mínimo a un ancho de la pelota de distancia al borde del
// canvas, para evitar errores en el dibujo
random(0 + size,width - size),
random(0 + size,height - size),
random(-7,7),
random(-7,7),
'rgb(' + random(0,255) + ',' + random(0,255) + ',' + random(0,255) +')',
size
);
balls.push(ball);
}

for (var i = 0; i < balls.length; i++) {


balls[i].draw();
balls[i].update();
}

requestAnimationFrame(loop);
}
Nuestra función de bucle: loop(), hace lo siguiente:
• Define el color de relleno del canvas como negro semi-transparente,
entonces dibuja un rectángulo en todo el ancho y alto del canvas, usando
fillRect(), (los cuatro parámetros definen las coordenadas de origen, el ancho y
el alto del rectángulo). Esto es para cubrir el dibujo del instante anterior antes
de actualizar el nuevo dibujo. Si no se realiza este paso, resultará en las
imágenes se irán apilando y veremos una especie de serpientes según se
mueven por el canvas en vez de las pelotas moviéndose! El color de relleno se
define como semitransparente, rgba(0,0,0,0.25), lo que nos permite que
podamos intuir algunos de los dibujos de instantes anteriores, con lo que
podremos recrear un poco el efecto de estelas detrás de las pelotas, según se
mueven. Pruebe a variar este número para ver como resulta el efecto.
• Se crea una nueva instancia de la pelota Ball() usando un número
aleatorio mediante la función random(), entonces se añade este elemento al
final del arreglo de las pelotas, push(), pero unicamente si el número de
pelotas es menor que 25. Así cuando tengamos 25 pelotas en la pantalla, no
crearemos nuevas pelotas. Pruebe a variar el número de pelotas en el código:
balls.length < 25. Dependiendo de la capacidad de procesamiento del
navegador, un número de pelotas muy alto podría ralentizar significativamente
la animación. ¡asi que cuidado!
• Se recorre el bucle por todo el conjunto de pelotas balls y se ejecuta el
método para dibujar, draw(), cada una de las pelotas, y actualizar sus datos,
update(), en cada una de ellas, así se conservarán las nuevas posiciones y
velocidades para el siguiente intervalo de animación.
• Se ejecuta la función de nuevo mediante el método
requestAnimationFrame() - cuando este método está continuamente
ejecutándose y llama a la misma función, esto ejecutará la función de
animación un determinado número de veces por segundo para crear una
animación fluida. Esto se realiza normalmente de forma recursiva — lo que
quiere decir que la función se llama a sí misma cada vez que se ejecuta, de
esa manera se ejecutará una y otra vez de forma continua.
3. Por último, pero no menos importante, añadimos la siguiente línea, al final
del código.-- es necesario llamar a la función inicialmente para que la
animación comience.
loop();
Eso es todo para la parte básica — pruebe a guardar el código y refrescar el
navegador para comprobar si aparecen las pelotas rebotando!
Añadiendo la detección de colisiones
Sección
Ahora, un poco de diversión, añadamos la detección de colisiones a nuestro
código. Así las pelotas, sabrán cuando chocan unas contra otras.
1. El primer paso, será añadir el código a continuación a continuación de
donde se definió el método update(). (en código de Ball.prototype.update)
2. Ball.prototype.collisionDetect = function() {
3. for (var j = 0; j < balls.length; j++) {
4. if (!(this === balls[j])) {
5. var dx = this.x - balls[j].x;
6. var dy = this.y - balls[j].y;
7. var distance = Math.sqrt(dx * dx + dy * dy);
8.
9. if (distance < this.size + balls[j].size) {
10. balls[j].color = this.color = 'rgb(' + random(0, 255) + ',' + random(0,
255) + ',' + random(0, 255) +')';
11. }
12. }
13. }
}
• Esta función es un poco complicada, así que no hay que preocuparse mucho
si de momento no se comprende del todo.
• Para cada pelota, necesitamos comprobar si chocará con cada una de
las otras pelotas. Para esto, en un bucle for para recorrer todas las pelotas.
• Dentro del bucle, usamos un if para comprobar si la pelota que estamos
mirando en ese ciclo del bucle for es la pelota que estamos mirando. No
queremos mirar si una pelota ha chocado consigo misma. Para esto miramos si
la pelota actual (es decir la pelota que está invocando al método que resuelve
la detección de colisiones) es la misma que la indicada por el bucle. Usamos un
operador ! para indicar una negación en la comparación, así que el código
dentro de la condición solo se ejecuta si estamos mirando dos pelotas
distintas.
• Usamos un algoritmo común para comprobar la colisión de los dos
pelotas. Básicamente miramos si el área de dos círculos se superponen. Esto
se explica mejor en el enlace detección de colision 2D.
• En este caso, únicamente se define la propiedad de color para las dos
pelotas, cambiándolas a un nuevo color aleatorio. Se podría haber hecho cosas
más complicadas, como que las pelotas rebotasen una con la otra de forma
realista, pero esto habría supuesto un desarrollo más complejo. Para
desarrollar esos efectos de simulación física, los desarrolladores tienden a usar
librerías de física como PhysicsJS, matter.js, Phaser, etc.
• También es necesario llamar este método en cada instante de la animación.
balls[i].update(); en la línea:
balls[i].collisionDetect();
2.
3. Guardar y refrescar la demo de nuevo y podrá ver como las pelotas
cambian de color cuando chocan entre ellas.
Nota: Si tiene problemas para hacer funcionar este ejemplo, puede comparar
su código JavaScript, con el código de la version_final (y también ver como
funciona al ejecutarla).
Resumen
Sección
Esperamos que se haya divertido escribiendo su propio mundo de pelotas que
chocan aleatoriamente, usando objetos y programación orientada a objetos.
Esto debería haberle dado una práctica útil y haber sido un buen ejemplo.
Añadiendo características a nuestra demo de bouncing balls

• •
• Editar
• •
Saltar a:
1. Punto de partida
2. Resumen del proyecto
3. Pasos para completar
4. Consejos
5. Evaluación
6. En este módulo
Esta traducción está incompleta. Por favor, ayuda a traducir este artículo del
inglés.
Anterior Overview: Objects

En esta evaluación, se espera que use la demo de bouncing balls del artículo
anterior como punto de partida y le agregue algunas características nuevas e
interesantes.
Prerrequisitos: Antes de intentar esta evaluación, debería haber revisado
todos los artículos de este módulo.
Objetivo: Para probar la comprensión de objetos JavaScript y
construcciones orientadas a objetos.
Punto de partida
Sección
Para iniciar esta evaluación, haz una copia local de index-finished.html,
style.css, y main-finished.js de nuestro último artículo en un nuevo directorio en
tu ordenador.
Nota: Alternativamente, puede usar un sitio como JSBin o Thimble para hacer
su evaluación. Puede pegar el HTML, CSS y JavaScript en uno de estos
editores en línea. Si el editor en línea que está utilizando no tiene paneles
JavaScript / CSS separados, sientase libre de poner en linea elementos
<script>/<style> dentro de la página.
Resumen del proyecto
Sección
Nuestra demostración de la pelota hinchable es divertida, pero ahora queremos
que sea un poco más interactiva agregando un círculo maligno controlado por
el usuario, que se los comería si los atrapa. Tambien queremos testar nuestras
destrezas como constructores de objetos creando un objeto Shape() genérico
de que puedan heredar nuestra pelota y el círculo maligno. Finalmente,
queremos añadir una puntuación para seguir el número de bolas que quedan
por capturar.
La siguiente captura de pantalla te da una idea de cómo debería verse el
programa final.

Para darle una idea eche un vistazo al ejemplo final (¡no mire el código fuente!)
Pasos para completar
Sección
Las siguientes secciones describen lo que debe hacer.
Creando nuestro nuevos objetos
Sección
Primero de todo, cambia la constructora existente de Ball() para que se
convierta en un constructor Shape() y añade un nuevo constructor Ball():
1. El constructor Shape() debe definir las propiedades x, y, velX, y velY del
mismo modo que lo hacía el constructor Ball() constructor original, pero no las
propiedades color y size.
2. También debe definir una nueva propiedad exists, que se utiliza para
realizar un seguimiento de si existen las bolas en el programa (no se han
comido por el círculo maligno). Debe ser un boolean (true/false).
3. El constructor Ball() debe heredar las propiedades x, y, velX, velY, y
exists del constructor Shape().
4. También debe definir propiedades color y size, como el constructor
original Ball() hacía.
5. Recuerda configurar el prototype del constructor Ball() correctamente.
Los métodos de la pelota draw(), update(), y collisionDetect() deben ser
capaces de permanecer exactamente igual que antes.
También necesitas añadir un parámetro nuevo a la llamada del constructor new
Ball() ( ... ) — El parámetro exists debe ser el quinto parámetro y debe tener un
valor true.
En este punto, intente volver a cargar el código; debería funcionar igual que
antes, con nuestros objetos rediseñados.
Definiendo EvilCircle()
Sección
Ahora es el momento de conocer al chico malo: ¡el EvilCircle()! Nuestro juego
solo involucrará un círculo malvado, pero lo vamos a seguir definiendo usando
un constructor que hereda de Shape() para que tengas algo de práctica. Es
posible que desee agregar otro círculo a la aplicación más adelante que pueda
ser controlado por otro jugador o tener varios círculos malvados controlados
por computadora. Probablemente no vas a dominar el mundo con un solo
círculo maligno, pero servirá para esta evaluación.
El constructor EvilCircle() debe heredar x, y, velX, velY, y exists from Shape(),
pero velX y velY debe ser igual a 20.
Debería hacer algo como Shape.call(this, x, y, 20, 20, exists);
Debe definir también sus propias propiedades, como las siguientes:
• color — 'white'
• size — 10
Otra vez, recuerda definir tus propiedades heredadas como parámetros en el
constructor, y configura las propiedades prototype y constructor properties
correc.tamente
Definiendo los métodos de EvilCircle()
Sección
EvilCircle() debe tener cuatro métodos como se desciben a continuación.
draw()
Este método tiene el mismo propósito que el método draw()de Ball(): Se
encarga de dibujar la instancia del objeto en el lienzo. Funcionarán de una
forma muy similar, así que puedes empezar copiando la definición de
Ball.prototype.draw. Luego deberías hacer los siguientes cambios.:
• Queremos que el círculo del mal no se complete, sino que simplemente
tenga una línea exterior (trazo). Puedes lograr esto actualizando fillStyle y fill()
a strokeStyle y stroke().
• También queremos que el trazo sea un poco más grueso, para que
puedas ver el círculo malvado con mayor facilidad. Podemos lograr esto
configurando un valor para lineWidth en algún lugar después de la llamada
beginPath() (3 hará).
checkBounds()
Este método hara lo mismo que la primera parte de la función update() de Ball()
— mire para ver si el círculo maligno va a salir del borde de la pantalla y evite
que lo haga. De nuevo, puede copiar la mayoría de la definición de
Ball.prototype.update, hay algunos cambios que debe hacer:
• Deshazte de las dos últimas líneas: no queremos actualizar
automáticamente la posición del círculo maligno en cada cuadro, porque lo
moveremos de alguna otra manera, como verás a continuación.
• Dentro de las declaraciones if(), si el test devuelve true no queremos
actualizar velX/velY; queremos cambiar el valor de x/y por lo que el círculo del
mal se rebota en la pantalla ligeramente. Agregar o restar (según corresponda)
la propiedad de tamaño del círculo maligno (size) tendría sentido.
setControls()
Este método agregará un detector de eventos onkeydown al objeto window
para que cuando se presionen ciertas teclas del teclado, podamos mover el
círculo maligno. El siguiente bloque de código debe colocarse dentro de la
definición del método:
var _this = this;
window.onkeydown = function(e) {
if (e.keyCode === 65) {
_this.x -= _this.velX;
} else if (e.keyCode === 68) {
_this.x += _this.velX;
} else if (e.keyCode === 87) {
_this.y -= _this.velY;
} else if (e.keyCode === 83) {
_this.y += _this.velY;
}
}
Por tanto cuando se presiona una tecla, el evento del objeto keyCode se
consulta para averiguar que tecla se ha presionado. Si es uno de los cuatro
representados por los códigos clave especificados, entonces el círculo maligno
se moverá a la izquierda / derecha / arriba / abajo.
• Para obtener un punto de bonificación, avísenos a qué teclas se asignan
los códigos de clave especificados.
• Para otro punto de bonificación, ¿nos podrías decir por qué tenemos que
configurar var _this = this; en la posición en la que está? Es algo que se hace
en la función scope.
collisionDetect()
Este método actuará de una forma muy similar al método collisionDetect() de
Ball(), así que puede usar una copia de eso como una base para el nuevo
método. Pero hay algunas diferencias:
• En el exterior de la declaración if, ya no es necesario comprobar si la
bola actual en la iteración es la misma que la bola que está haciendo la
comprobación, porque ya no es una bola, ¡es el círculo del mal! En su lugar,
debe hacer una prueba para ver si existe la bola que se está verificando (¿con
qué propiedad podría hacerlo?). Si no existe, ya ha sido devorado por el círculo
maligno, por lo que no es necesario volver a comprobarlo.
• En el interior de la declaración if, ya no desea que los objetos cambien
de color cuando se detecta una colisión; en cambio, desea que no existan más
bolas que colisionen con el círculo maligno (una vez más, ¿cómo cree que
haría eso?).
Trayendo el círculo del mal al programa.
Sección
Ahora que hemos definido el círculo maligno, debemos hacerlo aparecer en
nuestra escena. Para hacerlo, necesitas hacer alguno cambios a la función
loop().
• Primero de todo, crea una nueva instancia del círculo maligno (especifica
los parámetros necesarios ), entonces llama al método setControls() . Solo
necesita hacer estas dos cosas una vez, no en cada iteración del bucle.
• En el punto en el que intera por todas las pelotas y llama a las funciones
draw(), update(), ycollisionDetect() para cada una, hazlo para que estas
funciones solo sean llamadas si la bola actual existe.
• Llama a los métodos de la instancia de la pelota maligna draw(),
checkBounds(), ycollisionDetect() en cada iteración del bucle.
Implementando el contador de puntuación.
Sección
Para implementar el contador de puntuación sigue estos pasos:
1. En tu archivo HTML añade un elemento <p> justo debajo del elemento
<h1> que contiene el texto "Ball count: ".
2. En tu archivo CSS, agregue la siguiente regla en la parte inferior:
3. p{
4. position: absolute;
5. margin: 0;
6. top: 35px;
7. right: 5px;
8. color: #aaa;
}
2.
3. En su JavaScript, realice las siguientes actualizaciones:
o Cree una variable que almacene una referencia al párrafo.
o Mantenga un recuento de la cantidad de bolas en la pantalla de alguna
manera.
o Incrementa el conteo y muestra el número actualizado de bolas cada vez
que se agrega una bola a la escena.
o Disminuye el conteo y muestra el número actualizado de bolas cada vez
que el círculo maligno se come una bola (hace que no exista).
Consejos
Sección
• Esta evaluación es bastante desafiante. Da cada paso despacio y con
cuidado.
• Puede ser una idea mantener una copia separada de la demostración
después de que cada etapa esté funcionando, para que pueda consultarla si se
encuentra en problemas más adelante.

También podría gustarte