regresar a la lección

Coloca la pelota en el centro del campo.

importancia: 5

Así es como se ve el documento de origen:

¿Cuáles son las coordenadas del centro de campo?

Calcúlalos y úsalos para colocar la pelota en el centro del campo verde:

  • El elemento debe ser movido por JavaScript, no por CSS.
  • El código debería funcionar con cualquier una pelota de cualquier tamaño (10, 20, 30 pixels) y cualquier tamaño de campo, no debe estar vinculado a los valores dados.

P.S. Claro, el centrado se podría hacer con CSS, pero aquí lo queremos específicamente con JavaScript. Además, conoceremos otros temas y situaciones más complejas en las que se debe utilizar JavaScript. Aquí hacemos un “calentamiento”.

Abrir un entorno controlado para la tarea.

La pelota tiene position:absolute. Significa que sus coordenadas left/top se miden desde el elemento posicionado más cercano, es decir #field (porque tiene position:relative).

Las coordenadas inician desde el interior de la esquina superior izquierda del campo:

El interior del campo ancho/alto es clientWidth/clientHeight. Entonces el centro del campo tiene coordenadas (clientWidth/2, clientHeight/2).

…Pero si configuramos ball.style.left/top a tales valores, entonces no la pelota en su conjunto, sino el borde superior izquierdo de la pelota estaría en el centro:

ball.style.left = Math.round(field.clientWidth / 2) + 'px';
ball.style.top = Math.round(field.clientHeight / 2) + 'px';

Así es como se ve:

Para alinear la pelota al centro con el centro del campo, deberíamos mover la pelota a la mitad de su ancho a la izquierda y a la mitad de su altura hacia arriba:

ball.style.left = Math.round(field.clientWidth / 2 - ball.offsetWidth / 2) + 'px';
ball.style.top = Math.round(field.clientHeight / 2 - ball.offsetHeight / 2) + 'px';

Ahora la pelota está finalmente centrada.

Atención: ¡la trampa!

El código no funcionará seguramente mientras <img> no tenga width/height:

<img src="ball.png" id="ball">

Cuando el navegador no conoce el ancho/alto de una imagen (de un atributo o CSS), entonces este asume que es igual a 0 hasta que la imagen termine de cargarse.

Entonces el valor de ball.offsetWidth deberá ser 0 hasta que la imagen cargue. Eso conduce a coordinadas incorrectas en el código anterior.

Después de la primera carga, el navegador usualmente almacena en caché la imagen, y cuando se vuelva a cargar esta tendrá el tamaño inmediatamente. Pero en la primera carga el valor de ball.offsetWidth es 0.

Deberíamos arreglar eso agregando width/height en <img>:

<img src="ball.png" width="40" height="40" id="ball">

…O indicar el tamaño en CSS:

#ball {
  width: 40px;
  height: 40px;
}

Abrir la solución en un entorno controlado.