martes, 29 de octubre de 2013

Rotar una imagen

A partir de lo que hemos aprendido en los dos posts anteriores: Transformaciones en el canvas y Guardar y restaurar el contexto del canvas vamos a escribir una función con la que rotar fácilmente una imagen.

  • drawImageR(context, image, x, y, angle)
La hemos llamado drawImageR para diferenciarla de drawImage y para dar una pista de que sirve para rotar imágenes. Los argumentos son el contexto del canvas en el que dibujar, la imagen, las coordenadas x, y en las cuales dibujar la imagen y el angulo de rotación en radianes (respecto al centro de la imagen).
La forma de usarla difiere de la función drawImage porque drawImage es un método del contexto del canvas, mientras que drawImageR no, por lo tanto, sea ctx el contexto del canvas, haremos:
ctx.drawImage(...)
o
drawImageR(ctx, ...)

La función se puede modificar y ampliar para cubrir otras necesidades específicas, como por ejemplo rotar la imagen respecto a otro punto distinto del centro o dibujar un trozo específico de la imagen, como permiten las versiones con más parametros de drawImage.

La definición de drawImageR es la siguiente:
  function drawImageR(context, image, x, y, angle){
 var w_half = image.width/2;
 var h_half = image.height/2;

 context.save();
 context.translate(x + w_half, y + h_half);
 context.rotate(angle);
 context.drawImage(image, -w_half, -h_half);
 context.restore(); 
  }

Ejemplo

Un ejemplo sencillo, suponiendo que en la carpeta /images tenemos la imagen 1.jpg (un cuadrado con la mitad izquierda roja y la mitad derecha verde) usaremos la función ya conocida loadImages para cargarla y después dibujaremos una copia rotada y otra sin rotar, en la misma posición.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
 <canvas id="my_canvas" width="300px" height="200px"
 style="border:1px solid #000000;"></canvas> 
 <script type="text/javascript">
  var canvas = document.getElementById('my_canvas');
  var ctx = canvas.getContext('2d');
  var images = loadImages('./images/1.jpg', load_done);
  var cuadrado = images[0];
      
  function drawImageR(context, image, x, y, angle){
 var w_half = image.width/2;
 var h_half = image.height/2;

 context.save();
 context.translate(x + w_half, y + h_half);
 context.rotate(angle);
 context.drawImage(image, -w_half, -h_half);
 context.restore(); 
  }
  
  function loadImages() { //images and callback
 var n = arguments.length - 1;
 var callback = arguments[n]
 var images = new Array();
 var count = 0;
 
 for (i = 0; i < n; i++) {
  images[i] = new Image();
  images[i].onload = function(){
   count++;
   if (count == n){
    callback ();
   };
  };
  images[i].src = loadImages.arguments[i];
 };
 return images;  
}

 function load_done() {
  drawImageR(ctx, cuadrado, 20, 50, 45*Math.PI/180);
  ctx.drawImage(cuadrado, 20, 50);
 }
 
 </script> 
</body>
</html>

martes, 1 de octubre de 2013

Guardar y restaurar el contexto del canvas

Esta entrada continua la entrada anterior: Transformaciones en el canvas.
El contexto del canvas tiene una pila de estados. El estado del contexto del canvas contiene los valores actuales de distintos parámetros que se han fijado para el canvas:
  • Las transformaciones: traslación, rotación, escalado
  • La región de dibujo (clipping region)
  • Los valores actuales de los atributos: strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline. 
¿Cómo recuperamos el estado del canvas después de haber hecho una serie de modificaciones? Para ello el estado del contexto se puede almacenar en una pila LIFO (Last In First Out). Lo que haremos para recuperar el estado que teníamos antes de hacer modificaciones será lo siguiente:
  1. guardar el estado
  2. hacer las modificaciones
  3. dibujar lo que queramos con los nuevos ajustes
  4. recuperar el estado
Para ello el contexto del canvas dispone de dos funciones:
  • context.save(): guarda el estado actual en la parte superior de la pila
  • context.restore(): saca (y aplica al contexto) el estado de la parte superior de la pila

Ejemplo

<!DOCTYPE html>
<html>
<head>
</head>
<body>
 <canvas id="my_canvas" width="300px" height="200px"
 style="border:1px solid #000000;"></canvas> 
 <script type="text/javascript">
  var canvas = document.getElementById('my_canvas');
  var ctx = canvas.getContext('2d');
      
  var x = 10;
  var y = 10;
  var w = 50;
  var h = 50;
  

  // estado original: 0
  ctx.fillRect(x, y, w, h);
  ctx.save();
 
  // estado 1 
  ctx.fillStyle = "#ff0000"; // rojo
  ctx.fillRect(x+w, y, w, h);
  ctx.save();
  
  // estado 2
  ctx.fillStyle = "#00ff00"; // verde
  ctx.fillRect(x+2*w, y, w, h);
  
  // recuperamos el estado 1
  ctx.restore();
  ctx.fillRect(x+3*w, y, w, h);
  
  // recuperamos el estado 0
  ctx.restore();
  ctx.fillRect(x+4*w, y, w, h);
 
 </script> 
</body>
</html>
 


En este ejemplo únicamente hemos modificado el color de relleno, pero el mismo principio se aplica a cualquiera de los parametros contenidos en el contexto.

Esta entrada continua la entrada anterior: Transformaciones en el canvas.

miércoles, 28 de agosto de 2013

Transformaciones en el canvas

Este post tiene una continuación en la entrada: Guardar y restaurar el contexto del canvas.
Las transformaciones básicas en el  canvas son 3: traslación, rotación y escalado.
La forma en que funcionan es poco intuitiva puesto que lo que hacen no es trasladar, rotar y escalar elementos en el canvas sino que actúan sobre el origen y los ejes de coordenadas del canvas, modificando su posición, orientación y escala, de forma que los elementos dibujados antes de una transformación permanecen inalterados y los que se dibujen después de aplicar la transformación son afectados por ella.
Las transformaciones se aplican sobre el contexto del canvas.

Traslación

context.translate(x,y)
Traslada el origen de cordenadas del canvas desde la esquina superior izquierda al punto x,y.

Rotación

context.rotate(radianes)
Rota los ejes de coordenadas en torno al origen, un angulo especificado en radianes, en sentido horario. Para pasar de grados a radianes:
angulo_en_radianes = angulo_en_grados * (Math.PI/180)

Escalado

context.scale(factorX, factorY)
Mutiplica las coordenadas en el eje X e Y por el factorX y el factorY.


Ejemplo

<!DOCTYPE html>
<html>
<head>
</head>
<body>
 <canvas id="my_canvas" width="300px" height="200px"
 style="border:1px solid #000000;"></canvas> 
 <script type="text/javascript">
  var canvas = document.getElementById('my_canvas');
  var ctx = canvas.getContext('2d');
      
  var x = 10;
  var y = 10;
  var w = 50;
  var h = 50;
  var factorX = 0.5;
  var factorY = 0.5;
  
  // escalado
  ctx.scale(factorX, factorY);
  
  ctx.fillStyle = "#ff0000"; // rojo
  ctx.fillRect(x, y, w, h);
  
  // traslación
  ctx.translate(100, 50);
  
  ctx.fillStyle = "#00ff00"; // verde
  ctx.fillRect(x, y, w, h);
  
  // rotación
  ctx.rotate(30 * Math.PI/180);
  
  // dibujamos el nuevo eje x
  ctx.beginPath();
  ctx.moveTo(0,0);
  ctx.lineTo(50,0);
  ctx.stroke();
  
  // y el nuevo eje Y
  ctx.beginPath();
  ctx.moveTo(0,0);
  ctx.lineTo(0,50);
  ctx.stroke();
  
  ctx.fillStyle = "#0000ff"; // azul
  ctx.fillRect(x, y, w, h);
 
 </script> 
</body>
</html>
En el ejemplo se puede probar a cambiar la escala, cambiando factorX y factorY. El ejemplo tiene factorX = 0.5 y factorY = 0.5 (mitad de escala). El tamaño normal se consigue con factorX = 1, factorY = 1 y el doble de tamaño se consigue con factorX = 2, factorY = 2.


Este post tiene una continuación en la entrada: Guardar y restaurar el contexto del canvas 

lunes, 5 de agosto de 2013

Dibujar imágenes en el canvas con drawImage

Podemos dibujar en el canvas el contenido de un archivo de imagen. Los 2 formatos de imagen más habituales en la actualidad son:
  • jpg: formato comprimido con pérdida de calidad y sin transparencia.
  • png: formato comprimido sin pérdida de calidad y con posibilidad de transparencia.
Tal vez en un futuro ambos queden relegados por un nuevo formato libre: webp, pero de momento no hay indicios de tal cosa.
En general usaremos el formato jpg por ser de tamaño más reducido, a no ser que no queramos que la imagen pierda calidad o queramos usar una imagen con transparencia, en cuyo caso usaremos el formato png.

Para dibujar una imagen en el canvas usaremos la función drawImage del contexto del canvas (context.drawImage()), que tiene varias posibilidades:
  • context.drawImage(img, x, y): dibuja la imagen entera y sin escalar en el canvas, poniendo su esquina superior izquierda en el punto x,y del canvas.
  • context.drawImage(img, x, y, ancho, alto): posiciona la imagen en el punto x,y del canvas y la reescala para que tenga la anchura y altura especificadas.
  • context.drawImage(img, ox, oy, oancho, oalto, x, y, ancho, alto): coge un trozo de la imagen a partir del punto ox,oy, de anchura oancho y altura oalto y lo coloca en el canvas en el punto x, y, reescalándolo para que tenga la anchura ancho y altura alto.

Ejemplo

usaremos la siguiente imagen, que se puede guardar con click derecho del ratón sobre ella y "Guardar imagen". La guardaremos como planeta.jpg.


En el mismo directorio en que tengamos la imagen creamos un archivo html con el siguiente contenido.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <canvas id="my_canvas" width="300px" height="200px"
           style="border:1px solid #000000;"></canvas> 
    <script type="text/javascript">
 var canvas = document.getElementById('my_canvas');
 var ctx = canvas.getContext('2d');
 var imagen = new Image();
 imagen.onload = pinta;
 imagen.src = 'planeta.jpg';

 function pinta(){     
            // pintamos la imagen en la esquina superior izquierda del
            // canvas, con el tamaño original.
     ctx.drawImage(imagen, 0, 0);
     // pintamos la imagen en en el punto 110, 0, reescalada.
     ctx.drawImage(imagen, 110, 0, 1.5*imagen.width, 
            0.5*imagen.height);
     // pintamos un trozo de imagen, el cuadrante inferior
            // derecho, en el punto 0, 110, sin reescalar.
     ctx.drawImage(imagen, 50, 50, 50, 50, 0, 110, 50, 50);
     // reescalado (doble altura)
     ctx.drawImage(imagen, 50, 50, 50, 50, 110, 110, 50, 2*50);
 }
 </script> 
</body>
</html>
Como nota interesante del ejemplo, ver que el objeto de tipo Image tiene un par de campos width y height desde los que podemos recuperar la anchura y altura de la imagen.




lunes, 22 de julio de 2013

Cargador de imágenes

En un post anterior ya vimos como cargar una imagen. El proceso incluía crear un objeto imagen para cada imagen a cargar, definir una función a ejecutar cuando termise la carga y por último, especificar la localización de la imagen. Es un proceso laborioso que puede hacerse un poco pesado. A continuación presentamos un sencillo cargador de imágenes que nos permitirá especificar todas las ubicaciones de las imágenes a cargar a la vez y una única función de callback para cuando terminen de cargarse todas ellas.
Conviene guardar el código siguiente en un archivo aparte, por ejemplo "loadImages.js" para poder incluirlo fácilmente en aquellos proyectos en los que necesitemos cargar varias imágenes de forma sencilla.
// loadImages.js
// arguments:
//  string urls with location of images to load
//  callback function
// returns:
//  array of Image objects

function loadImages() { //images and callback
 var n = arguments.length - 1; // number of images to load
 var callback = arguments[n]
 var images = new Array();
 var count = 0;
 
 for (i = 0; i < n; i++) {
  images[i] = new Image();
  images[i].onload = function(){
   count++;
   if (count == n){
    callback ();
   };
  };
  images[i].src = loadImages.arguments[i];
 };
 return images;  
}

Uso

La función loadImages devuelve un array que contiene las imágenes cargadas. Acepta un número variable de argumentos. Los argumentos serán cadenas de texto especificando la ubicación de las imagenes a cargar, excepto el último argumento, que será la función de callback, que debe especificarse sin comillas y sin los paréntesis de la llamada, como en el siguiente ejemplo:
<!DOCTYPE html>
<html>

    <head>
    <script type="text/javascript" src="./loadImages.js"></script>
    <script type='text/javascript'> 

 function load_done() {
            text = "Images loaded:<br>";
         for(var i=0; i< images.length; i++)
  {
      text += images[i].src + "<br>";
  }
  document.write(text);
 }
   
 var images = loadImages('./images/im1.jpg',
    './images/im2.jpg',
    './images/im3.jpg',
    './images/im4.jpg',
    './images/im5.jpg',
    './images/im6.jpg',
    './images/im7.jpg',
    './images/im8.jpg',
    './images/im9.jpg',
    load_done);
    </script>
    </head>

    <body>
    </body>

</html>
En este ejemplo hemos especificado las ubicaciones relativas de las imágenes a cargar, pero también se podría haber usado caminos absolutos e incluso urls como
'http:\\www.lapaginaquesea.com\imagencualquiera.jpg

miércoles, 10 de julio de 2013

Carga de imágenes

El proceso para cargar una imagen que podamos usar desde javascript consta de tres pasos:

  1. Crear un objeto Image.

var imagen = new Image();

  1. Especificar la función de callback

Es la función que se ejecuta cuando termine la carga de la imagen.
imagen.onload = callback; 
Importante! la función de callback se especifica sin encerrarla en comillas y sin poner los paréntesis.

  1. Especificar la imagen

Puede especificarse mediante un camino relativo al archivo de imagen o mediante una url. Una vez definida la fuente desde la que se debe cargar la imagen, la carga comienza inmediatamente, por lo que hay que si se quiere especificar una función de callback, debe especificarse antes de especificar la fuente de la imagen.
imagen.src="miImagen.jpg;"

Ejemplo

<!DOCTYPE html>
<html>
<head>
</head>
<body>
 <canvas height="200px" id="my_canvas" style="border: 1px
                 solid #000000;" width="300px"></canvas> 
 <script type="text/javascript">
  var canvas = document.getElementById('my_canvas');
  var ctx = canvas.getContext('2d');
  var imagen = new Image();
  imagen.onload = pinta;
  imagen.src = "http://1.bp.blogspot.com/-t9kNjyxhS_k/" +
       "UXRLc-tCXuI/AAAAAAAAAEQ/Gmn3RR06Org/s1600/canvas1.png";

  function pinta(){                
   ctx.drawImage(imagen, 0, 0);
  }
 </script> 
</body>
</html>

viernes, 17 de mayo de 2013

Medir el tiempo de ejecución

Podemos usar la consola de las herramientas para desarrolladores para ver el tiempo que tarda en ejecutarse una parte del código y comprobar su rendimiento. En Google Chrome esto se hace con 2 instrucciones:

  • console.time(nombre del timer): se coloca antes del código que queremos medir. Inicia un temporizador con el nombre que hayamos elegido, que será una cadena de texto.
  • console.timeEnd(nombre del timer): se coloca después del código que queremos medir. Termina el temporizador con el nombre asociado, que será uno de los que hayamos iniciado antes con console.time(). Además escribe a la consola el resultado.

Uso

console.time('nombre');
// código a cronometrar

console.timeEnd('nombre');

Ejemplo

Por ejemplo, lo podemos usar para medir el tiempo que tarda en pintar 10000 lineas aleatorias de colores al azar, como vimos en un post anterior:
<!DOCTYPE html>
<html>
 <head>
    <script type="text/javascript" >
        var canvas;
        var ctx; //contexto del canvas.
        
        function setup(){
            // accedemos al canvas
            canvas = document.getElementById('my_canvas');

            // si se puede acceder al contexto del canvas
            if (canvas.getContext){ 
                // accedemos al contexto del canvas 
                // y llamamos a nuestra función de dibujo.
                ctx = canvas.getContext('2d');
                draw();
            }
            else { // el canvas no está soportado
                alert('Este navegador no es compatible con canvas');
            }
        }
        
        // nuestra función de dibujo
        function draw(){                
            // lo ajustamos al tamaño de la ventana del navegador
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
            // dibujamos. En este caso, 10000 lineas aleatorias
            // y medimos lo que tarda
            console.time('tiempo que tarda en pintar');
            
            pintaLineasAleatorias(canvas.width, canvas.height, 10000);
            
            // hasta que termina
            console.timeEnd('tiempo que tarda en pintar');
        }
        
        function pintaLineasAleatorias(width, height, n)
        {
            var x1, y1, x2, y2;
   
            for (var i=0; i< n; i++)
     {
         x1 = Math.floor((Math.random()*(width + 1)));
         x2 = Math.floor((Math.random()*(width + 1)));
         y1 = Math.floor((Math.random()*(height +1)));
  y2 = Math.floor((Math.random()*(height +1)));
  ctx.strokeStyle = 'rgb('
                    + Math.floor(Math.random()*256)
                    + ',' + Math.floor(Math.random()*256)
                    + ',' + Math.floor(Math.random()*256)
                    + ')';
  ctx.beginPath();
  ctx.moveTo(x1,y1);
  ctx.lineTo(x2,y2);
                ctx.closePath();
  ctx.stroke();
      }
        }
    </script>
 </head>
 <body style="margin:0; padding:0; width:100%; height:100%;" onload="setup()" >
  <canvas id="my_canvas" style="display:block;"></canvas>
 </body>
</html>
Si abrimos el archivo html anterior en el Google Chrome y luego abrimos la consola de javascript (Ctrl+Mayús+J) veremos el tiempo que ha tardado en dibujar las 10000 lineas.

martes, 14 de mayo de 2013

Números aleatorios

La capacidad de generar números aleatorios es muy interesante en gran cantidad de juegos, con fines tan variados como simular la tirada de un dado, generar un mapa aleatoriamente, dotar de un comportamiento errático a algunos enemigos o generar eventos aleatorios.
Para generar números aleatorios nos vamos a servir del objeto Math, que sirve para realizar varios cálculos matemáticos, incluidos cálculos trigonométricos. Para este fin son necesarias 2 funciones del objeto Math:
  • Math.random(): devuelve un número aleatorio entre 0 y 1.
  • Math.floor(): redondea hacia abajo, hacia el "suelo".
Para generar un número aleatorio arbitrario usaremos una combinación de ambas, por ejemplo, para generar un número aleatorio entre 0 y 255:
Math.floor( Math.random()*(255 + 1) );
Podríamos haber usado Math.round() lugar de Math.floor() para conseguir el mismo resultado, pero aunque ambos sirven al mismo fin, Math.floor() produce un reparto de los resultados más equitativo, mientras que Math.round() produciría una desviación.

Canvas que ocupa toda la ventana del navegador

Para tener un canvas que ocupe toda la ventana del navegador debemos hacer las siguientes cosas:

  • Para que el body del HTML ocupe toda la ventana del navegador, sin dejar ningún borde, añadimos el siguiente atributo a la etiqueta body:
style="margin:0; padding:0; width:100%; height:100%;"
  • Para que el canvas no tenga barras de scroll hay que añadir el siguiente atributo al canvas:
style="display:block;"
  • Para que el canvas ocupe toda la ventana, cada vez que vayamos a volver a dibujar hay que redimensionarlo, con las siguientes instrucciones:
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
Un ejemplo de uso:
<!DOCTYPE html>
<html>
 <head>
    <script type="text/javascript" >
        var canvas;
        var ctx; //contexto del canvas.
        
        function setup(){
            // accedemos al canvas
            canvas = document.getElementById('my_canvas');

            // si se puede acceder al contexto del canvas
            if (canvas.getContext){ 
                // accedemos al contexto del canvas 
                // y llamamos a nuestra función de dibujo.
                ctx = canvas.getContext('2d');
                draw();
            }
            else { // el canvas no está soportado
                alert('Este navegador no es compatible con canvas');
            }
        }
        
        // nuestra función de dibujo
        function draw(){                
            // lo ajustamos al tamaño de la ventana del navegador
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
            // dibujamos. En este caso, 10000 lineas aleatorias
            pintaLineasAleatorias(canvas.width, canvas.height, 10000)
        }
        
        function pintaLineasAleatorias(width, height, n)
        {
            var x1, y1, x2, y2;
   
            for (var i=0; i< n; i++)
     {
         x1 = Math.floor((Math.random()*(width + 1)));
         x2 = Math.floor((Math.random()*(width + 1)));
         y1 = Math.floor((Math.random()*(height +1)));
  y2 = Math.floor((Math.random()*(height +1)));
  ctx.strokeStyle = 'rgb('
                    + Math.floor(Math.random()*256)
                    + ',' + Math.floor(Math.random()*256)
                    + ',' + Math.floor(Math.random()*256)
                    + ')';
  ctx.beginPath();
  ctx.moveTo(x1,y1);
  ctx.lineTo(x2,y2);
                ctx.closePath();
  ctx.stroke();
      }
        }
    </script>
 </head>
 <body style="margin:0; padding:0; width:100%; height:100%;" onload="setup()" >
  <canvas id="my_canvas" style="display:block;"></canvas>
 </body>
</html>


lunes, 13 de mayo de 2013

Depurar javascript

La depuración es el proceso de detectar y corregir errores y fallos en un programa. Esto es importante en javascript porque suele fallar silenciosamente, sin dar pistas de lo que puede ir mal.
Hay varias cosas que podemos hacer para evitar y corregir posibles errores:

  • Usar un detector de errores de sintaxis.
  • Incluir sentencias de depuración.
  • Usar un depurador.

Usar un detector de errores de sintaxis

En un post anterior ya hablamos de JSHint o JSLint. Cualquiera de los dos nos facilitará enormemente descubrir posibles errores de sintaxis que tan fácilmente pasan inadvertidos en javascript. Por ello, el primer paso debería ser pasar el script por uno de ellos.

Incluir sentencias de depuración

Normalmente detectamos que hay algún problema porque no ocurrió algo que esperábamos o bien alguno de los resultados del programa es diferente al esperado y sin embargo, al analizarlo con JSHint no se detecta ningún error. Esto puede ser debido a que el programa es correcto sintácticamente pero no hemos programado realmente lo que queríamos programar y el ciclo de ejecución del programa no lo lleva por los caminos que habíamos supuesto. En ese punto hay que intentar descubrir qué es lo que falló. ¿Ha pasado el programa por los puntos que esperabamos? ¿Tienen las variables los valores que suponíamos? Una técnica para detectar estos y otros problemas, sin llegar a recurrir a un depurador propiamente dicho consiste en incluir sentencias de depuración.
Las sentencias de depuración son instrucciones que se añaden al script con el objeto de ayudarnos a encontrar el punto de fallo. Un ejemplo típico es mostrar un cuadro de alerta en un punto del programa, para comprobar que la ejecución ha pasado por ahí, o bien escribir algún mensaje en el documento html.
Normalmente, las instrucciones de depuración servirán para depurar y una vez comprobado el programa y satisfechos con el resultado, se eliminarán del script, comentandolas o bien borrándolas.

Cuadro de alerta

  • alert(mensaje): muestra un cuadro de alerta con el mensaje especificado, que debe ser una cadena de texto, entre comillas simples o dobles. Por ejemplo:
if (a > 5)
{
    // hacer cosas...
    alert("a > 5");
}
else if (a < 7)
{
    // hacer cosas...
    alert("a < 5 y a < 7");
}
else
{
    // hacer cosas....
    alert("El programa ha pasado por aquí.");
}
En este ejemplo, si la variable a tiene un valor numérico, debería cumplir una de las 2 primeras condiciones (si no es mayor que 5, entonces es menor que 7, si o si). Sin embargo, si la variable a está declarada pero no tiene un valor definido, o tiene un valor que no es numérico, puede no ser mayor que 5 ni menor que 7 y, por lo tanto el programa entrará en el último else, cosa que detectaremos por el cuadro de diálogo que muestra "El programa ha pasado por aquí.".

OJO!!: como la instrucción alert provoca la aparición de un cuadro de diálogo, no conviene usarla dentro de ciclos con muchas iteraciones porque cuando se abre un cuadro de alerta la ejecución del script se interrumpe hasta que se vuelve a cerrar y luego hay que cerrarlos!!.

Escribir al documento HTML

  • document.write(mensaje): es una alternativa sencilla para mostrar información en el navegador.
OJO!!: document.write() sobreescribe TODO el DOM. Por muy compleja que sea la página web que tengamos, después de hacer un document.write() es como si sólo tuviesemos el texto del mensaje en el documento HTML. Por ejemplo, en un documento HTML con canvas y otros elementos, si hacemos:
document.write("el valor de a es: " + a);
Tendremos una página web en la que canvas y demás elementos han desaparecido y sólo queda el mensaje (suponiendo que a=2):

Escribir a un elemento HTML

Escribir a todo el documento HTML es conveniente a veces por su sencillez: es un método de depuración rápido, para comprobar algún valor de alguna variable sin liarse a abrir el depurador ni más complicaciones. Sin embargo, a veces es más conveniente escribir a un elemento HTML de la página web. El elemento puede ser uno que ya exista en la página web y otras veces lo crearemos expresamente para la ocasión, modificando el archivo HTML o bien mediante javascript.

  • Es muy fácil escribir al título de la página, cambiando el atributo title del documento. Por ejemplo, supongamos que una hipotética variable b = 8:
document.title = "la variable b vale: " + b;



  • Escribir a un elemento existente, o que creamos en el HTML.
El elemento debería tener un atributo id, para acceder fácilmente con document.getElementById(). Si no lo tiene, se lo podemos añadir en el HTML.
Por ejemplo, podríamos crear un párrafo y escribir al mismo cambiando su atributo innerHTML:

Creamos el elemento, con id="depurar" en el HTML, dentro del body:
<p id="depurar"></p>
y accedemos al mismo y escribimos la información para depuración que queramos desde javascript:
document.getElementById("depurar").innerHTML = "la variable b vale: " + b;
para conseguir lo mismo que en el ejemplo anterior, pero en un elemento párrafo en vez del título.


  • Escribir a un elemento creado mediante javascript.
Supongamos que vamos a crear el elemento párrafo del ejemplo anterior, pero mediante javascript, para no tocar el archivo HTML original. De esta forma es más sencillo eliminar el código de depuración cuando ya no sea necesario.
    var parrafo=document.createElement("p");
    document.body.appendChild(parrafo);
    parrafo.innerHTML = "la variable b vale: " + b;
En el código anterior se crea un elemento en el documento, de tipo párrafo (especificador "p" de la función createElement). Ese elemento párrafo se asigna a una variable parrafo del javascript para poder acceder al mismo, sin tener que buscarlo con getElementById, ya que no tiene id.
Una vez creado, lo añadimos al body del documento. Finalmente escribimos nuestro mensaje de depuración modificando el atributo innerHTML de la variable parrafo.


Escribir a la consola

  • console.log(mensaje): escribe el mensaje a la consola javascript del navegador Chrome. Otros navegadores funcionan de otra manera. Veremos la consola javascript al hablar del depurador en el siguiente apartado.
En Chrome se puede ver la consola javascript yendo a "Personaliza y configura Google Chrome" -> Herramientas -> Consola Javascript o bien pulsando Ctrl + Mayús + J.

Usar un depurador

Parece la opción obvia cuando hay algún problema, pero antes de recurrir al depurador es bueno pensar un poco en cuál puede ser la causa del problema y a veces es más fácil y rápido usar instrucciones de depuración en lugar de ir directamente al depurador.
El depurador nos permite ejecutar el script poniendo puntos de parada, ejecutar el script paso a paso y ver el valor que toman en cada momento las variables. Es una herramienta potente pero hay que usarla con cabeza.
En este post nos vamos a centrar en el depurador de Google Chrome.
En el ejemplo usaremos los dos archivos siguientes, que deben estar en la misma carpeta, para que el camino desde el HTML hasta el javascript sea simplemente "mi_javascript.js":

pagina.html
<!DOCTYPE html>
<html>
 <head>
    <script type="text/javascript" src="mi_javascript.js" >
    </script>
 </head>
 <body onload="mi_funcion()">
  <canvas id="my_canvas" width="200px" height="100px"
style="border:1px solid #000000;"></canvas>
 </body>
</html>
mi_javascript.js
function mi_funcion() {
    var a = 2;
             
    if (a > 5)
    {
        // hacer cosas...
        alert("a > 5");
    }
    else if (a < 7)
    {
        // hacer cosas...
        alert("a < 5 y a < 7");
    }
    else
    {
        // hacer cosas....
        alert("El programa ha pasado por aquí.");
    }
    document.write("el valor de a es: " + a);
    console.log(a);
}

Si abrimos el archivo pagina.html con el navegador Chrome, veremos lo siguiente:

Arriba a la izquierda está el canvas con borde, y también hay un cuadro de alerta con el texto "a < 5 y a < 7". La ejecución del script está bloqueada hasta que no cerremos el cuadro de alerta haciendo click en el botón "Aceptar". Después de desaparecer el cuadro de alerta, se escribe al documento HTML y se sobreescribe todo el DOM con "el valor de a es: 2":

Se aprecia que por haber sobreescrito todo el DOM, el canvas ha dejado de existir.

Las herramientas para desarrolladores de Google Chrome se sacan pinchando en "Personaliza y configura Google Chrome" -> Herramientas -> Herramientas para desarrolladores o bien pulsando Ctrl+Mayús+I.

La pantalla del navegador queda dividida en 2 zonas por la barra de herramientas para desarrolladores: la parte superior aloja la página web y la inferior la pantalla seleccionada en la barra de herramientas. De éstas, de momento, y a un nivel más básico, nos interesan Elements, Sources y Console.

Elements

Si pulsamos sobre el botón "Elements" aparece el contenido del HTML (puede ser necesario desplegarlo pulsando sobre el triángulo negro de la izquierda:

Podemos apreciar que el documento HTML ha quedado reducido al head, vacío y el elemento body, que sólo contiene el mensaje que hemos escrito desde el javascript.

Console

Si pinchamos en el botón Console, veremos la consola de javascript, en la que aparece escrito un "2", que es el valor que hemos escrito con la instrucción console.log(a).
En la consola se puede escribir javascript, que se ejecuta al instante. Por ejemplo, si escribimos a; y pulsamos Enter, que es lo que haríamos para ver el valor de la variable a, obtendremos un error: Reference Error: a is not defined. Esto es debido a que la función "mi_funcion()" ya ha terminado y la variable a, que se declara dentro de ella, ya no está en el ámbito (scope).


Elements de nuevo

Pulsemos sobre "Elements" y luego hagamos click derecho con el ratón sobre el área de la página y seleccionemos la opción "Cargar de nuevo" para recargar la página. También se puede recargar la página pulsando F5, pero en este ejemplo deberemos hacer click sobre la página antes para devolverle el foco y que se refresque correctamente.

Aparece el mensaje de alerta y vemos el elemento canvas en la web. También vemos la estructura de la página web en las herramientas para desarrolladores: tenemos el canvas dentro del body.
En cuanto cerremos el cuadro de alerta, el script continúa su ejecución y se ejecuta la instrucción document.write(), con lo que se sobreescribe todo el DOM y podemos ver que la estructura de la página web es lo más básica posible, habiendose sustituido todo el contenido del body por el texto "el valor de a es: 2".
Una de las funcionalidades más interesantes de la pantalla Elements es que se puede pasar el ratón por los elementos de la página o por la lista de elementos que aparecen en la parte inferior y ver cómo se resaltan en la parte superior de la pantalla, mostrando el espacio que ocupa el elemento. También es muy útil seleccionar algún elemento y ver sus propiedades en la parte derecha de la ventana Elements.

Sources

Pinchamos en Sources y luego en el botón Show navigator . En el navegador podremos elegir el archivo html y el archivo javascript. Lo interesante será ver el archivo javascript. Desde aquí podremos hacer varias cosas para depurar el javascript.

  • Poner puntos de parada (breakpoints): pinchando con el ratón a la izquierda de una linea del script, en la columna en la que aparecen los números de linea, se puede marcar la linea con una flecha azul, que indica un punto de parada. El punto de parada también aparece a la derecha, en la sección breakpoints.



  • Ejecutar el script: para eso pulsamos F5 para recargar la página. Si tenemos puesto algún breakpoint, el script se detendrá en el mismo y podremos ver dónde se ha detenido y el valor de las variables que estén en el ámbito (scope), como por ejemplo, la variable a.

  • Continuar la ejecución paso a paso.
Los siguienes botones  nos permiten continuar la ejecución del script, hasta el siguiente punto de parada, continuar paso a paso sin entrar en funciones, continuar paso a paso entrando en funciones o continuar hasta salir de una función y por último, desactivar todos los breakpoints.
En el ejemplo actual, si le damos un par de veces al 2º botón (continuar sin entrar en funciones), vemos que la ejecución llega a entrar en el 2º else:
Este es un ejemplo de cómo se puede seguir la pista al camino de ejecución de un script y ver si la ejecución toma las bifurcaciones esperadas.

El objetivo de este post es dar una pequeña introducción a las herramientas de depuración, pero para aprender todas sus posibilidades y a manejarse adecuadamente con ellas es necesario recurrir a otras fuentes, como por ejemplo:





sábado, 4 de mayo de 2013

JSHint: Detección de errores en javascript

Una particularidad frustrante que tiene javascript es la combinación de 2 características de su funcionamiento habitual:
  • es muy sensible al caso: no es lo mismo array que Array, ni onload que onLoad.
  • falla silenciosamente: muchas veces la única pista que tenemos de que algo va mal con nuestro script es que no hace lo que queríamos, pero nada más: no hay mensajes de error, el navegador no se queja... a veces no funciona nada de nada pero no tenemos ninguna pista de donde puede estar el fallo, a veces tan simple como una coma o un punto y coma que no están donde debieran.
Hay una herramienta que nos va a ayudar a detectar y corregir todo tipo de errores de sintaxis que tan dificiles son de detectar, sobre todo al principio. Existen dos variantes muy similares JSLint y JSHint. Personalmente prefiero JSHint, pero para gustos los colores.

Versión web

En www.jshint.com , lo único que hay que hacer es pegar nuestro código javascript en el recuadro de texto y darle al botón "Lint".

Plugin para Notepad++

Se puede descargar de la página del proyecto en sourceforge: http://sourceforge.net/projects/jslintnpp/
Para instalarlo sólo hay que descargarse el archivo zip de la página del proyecto, descomprimirlo y copiar el archivo JSLintNpp.dll en la carpeta plugins de Notepad++. Después de hacerlo hay que cerrar y volver a abrir el Notepad++ antes de poder usarlo. En Windows el camino de la instalación por defecto es C:\Archivos de programa\Notepad++\plugins.

Después de instalarlo, conviene configurar las opciones:
En Notepad++: Plugins-> JSLint-> JSLint Options

Aquí podemos elegir si queremos que sea JSLint o JSHint el programa que se encargue de analizar nuestros archivos y también podemos configurar una serie de opciones para cada uno de ellos. Yo prefiero JSHint y suelo tener marcadas por defecto: Assume  browser y assume development.



Para usarlo, lo único que debemos hacer es tener un archivo javascript abierto y elegir JSLint->JSLint Current File (Ctrl+Shift+F5).

domingo, 28 de abril de 2013

Plantilla html5 con canvas

Plantilla simple

<!DOCTYPE html>
<html>
 <head>
 </head>
 <body>
  <canvas id="my_canvas" width="200" height="100" style="border:1px
solid #000000;"></canvas>
 </body>
</html> 

Plantilla con evento onload() y javascript

<!DOCTYPE html>
<html>
 <head>
    <script type="text/javascript" >
        var canvas;
        var ctx; //contexto del canvas.
        
        function setup(){
            // accedemos al canvas
            canvas = document.getElementById('my_canvas');
            // si se puede acceder al contexto del canvas
            if (canvas.getContext){ 
                // accedemos al contexto del canvas 
                // y llamamos a nuestra función de dibujo.
                ctx = canvas.getContext('2d');
                draw();
            }
            else { // el canvas no está soportado
                alert('Este navegador no es compatible con canvas');
            }
        }
        
        // nuestra función de dibujo
        function draw(){                
        
        }
    </script>
 </head>
 <body onload="setup()">
  <canvas id="my_canvas" width="200px" height="100px"
        style="border:1px solid #000000;"></canvas>
 </body>
</html>

html5 y canvas

HTML5 es la versión más reciente de HTML a fecha de hoy. Incluye un elemento nuevo muy interesante para la programación de videojuegos: el canvas (lienzo en español).
El canvas sólo es un contenedor de gráficos en el que se puede pintar usando un script, normalmente en lenguaje javascript. El canvas tiene algunas funciones para dibujar gráficos tales como caminos (paths, para dibujar lineas), círculos, cajas, caracteres de texto y añadir imágenes desde un archivo.

Incluir un canvas

Para incluir un canvas en una página web sólo debemos incluir lo siguiente en el HTML:
<canvas id="my_canvas" width="200" height="100"> </canvas>
Si queremos que tenga borde, por ejemplo de 1px de anchura y color negro (#000000) lo podemos añadir usando el atributo style:
<canvas id="my_canvas" width="200" height="100" style="border:1px solid 
#000000;"> </canvas>

Coordenadas del canvas

En el canvas el origen de coordenadas se encuentra en la esquina superior izquierda, que es el punto 0,0 y el eje de abcisas, eje x, u horizontal aumenta de izquierda a derecha, mientras que el eje de ordenadas, eje y o vertical aumenta de arriba a abajo.


Algunos ejemplos

La plantilla básica que usamos es la siguiente:

<!DOCTYPE html>
<html>
 <head>
    <script type="text/javascript" >
        var canvas;
        var ctx; //contexto del canvas.
        
        function setup(){
            // accedemos al canvas
            canvas = document.getElementById('my_canvas');
            // si se puede acceder al contexto del canvas
            if (canvas.getContext){ 
                // accedemos al contexto del canvas 
                // y llamamos a nuestra función de dibujo.
                ctx = canvas.getContext('2d');
                draw();
            }
            else { // el canvas no está soportado
                alert('Este navegador no es compatible con canvas');
            }
        }
        
        // nuestra función de dibujo
        function draw(){                
        
        }
    </script>
 </head>
 <body onload="setup()">
  <canvas id="my_canvas" width="200px" height="100px"
        style="border:1px solid #000000;"></canvas>
 </body>
</html>
El código anterior es una página HTML con un canvas de 200 x 100 píxeles y borde negro, que está colocado en el body del documento HTML.
En el head del documento HTML hay un script de javascript. Inicialmente se declaran 2 variables, canvas y ctx, a las que asignaremos el canvas y su contexto, respectivamente.
El atributo onload="setup()" del elemento body asigna la función setup() de nuestro script al evento onload del elemento body. Cuando se cargue el elemento body de la página, se dispara su evento onload. Con onload="setup()" hacemos que al lanzarse el evento onload se llame a la función setup() de nuestro script.
En la función setup() preparamos el terreno accediendo al canvas y asignandolo a nuestra variable canvas con la instrucción canvas  = document.getElementById('my_canvas') y luego miramos a ver si podemos acceder a su contexto. Si no podemos, es porque el navegador no es compatible con el canvas y lanzamos un diálogo de alerta. Si se puede acceder al contexto, accedemos y lo asignamos a la variable ctx, con la instrucción ctx = canvas.getContext('2d'). El 2d hace referencia a que queremos un canvas para dibujar en 2 dimensiones. También existe un contexto para dibujar en 3 dimensiones, al cual accederíamos con getContext('webgl') pero ambos son muy diferentes y de momento nos vamos a restringir a las 2 dimensiones. Finalmente, desde nuestra función setup() llamamos a nuestra función draw(), en la que incluiremos las instrucciones para dibujar en el canvas. De momento la función está vacía así que no se dibujará nada en el canvas.
A continuación vamos a poner algunos ejemplos de funciones draw para dibujar distintos tipos de cosas. Los ejemplos tienen un exceso de comentarios para explicar cada una de las instrucciones.

Colores y grosor de linea

Se cambian las siguientes propiedades del contexto del canvas:
  • lineWidth, para especificar el ancho de la linea.
  • strokeStyle, para modificar el color de la linea.
  • fillStyle, para modificar el color de relleno.

Dibujando formas con lineas

Usaremos las siguientes funciones del contexto del canvas:
  • beginPath(), para comenzar un recorrido.
  • moveTo(x,y), para moverse a un punto (sin dibujar).
  • lineTo(x,y), para dibujar una recta desde el punto actual al punto x,y especificado como argumento.
  • closePath(), para cerrar un camino.
  • stroke(), para aplicar trazo al camino.
  • fill(), para rellenar un camino, (cerrado o no).
function draw(){
    // ponemos el grosor de linea = 3 pixeles
    ctx.lineWidth = 3;
    // cambiamos el color de la linea, de negro,
    // que es el color por defecto, a rojo:
    // ctx.strokeStyle="#FF0000";
    // o bien de la siguiente forma equivalente,
    // sin usar notación hexadecimal.
    ctx.strokeStyle = 'rgb(255,0,0)';
    
    //cambiamos el color de relleno, de negro,
    // que es el color por defecto, a azul
    ctx.fillStyle = 'rgb(0,0,255)';
   
    // vamos a dibujar algunas lineas, formando un triangulo.
    ctx.beginPath();
    ctx.moveTo(50, 50); // la primera linea parte del punto 50,50
    ctx.lineTo(75, 25); // y va hasta 75,25
    ctx.lineTo(100, 50); // otra linea desde ese punto hasta 100,50
    ctx.closePath(); // y otra cerrando el triangulo.
    ctx.stroke(); // aplicar un trazo al camino.
    
    // ahora vamos a dibujar otro triangulo, pero en vez pintar
    // un trazo lo vamos a rellenar.
    ctx.beginPath();
    ctx.moveTo(50, 50); // la primera linea parte del punto 50,50
    ctx.lineTo(75, 75); // y va hasta 75,75
    ctx.lineTo(100, 50); // otra linea desde ese punto hasta 100,50
    //ctx.closePath(); // y otra cerrando el triangulo.
    ctx.fill(); // rellenar el camino trazado.
    // este triangulo es un poco más pequeño que el anterior
    // porque no tiene el trazo del borde.
    // además de rellenarlo, se lo podríamos añadir descomentando
    // la siguiente linea: ctx.stroke();                
}
El resultado de este ejemplo sería lo siguiente:

Dibujando rectángulos

Dibujar rectángulos funciona de forma similar a dibujar lineas, pero en lugar de dibujar linea a linea, podemos dibujar los 4 lados del rectángulo con una única instrucción:
  • rect(x, y, width, height)
x e y especifican las coordenadas de la esquina superior izquierda del rectángulo.

function draw(){
    ctx.beginPath();
    ctx.rect(15,30, 100, 50); // rectángulo de 100x50 situado en 15,30
    ctx.strokeStyle = 'rgb(255, 0, 0)'; // linea roja.
    ctx.stroke();// pintamos el borde
    ctx.fillStyle = 'rgb(128,128,128)'; // un color gris.
    ctx.fill(); // rellenamos el rectángulo    
}
El resultado de este ejemplo:


Dibujando círculos (y arcos de circunferencia o secciones de círculo)

Sólo hay una función nueva para dibujar arcos de circunferencia (si luego se usa el método stoke()) o secciones de círculo (si luego se rellena con el método fill()). Método es otra forma de llamar a las  funciones de una variable, en este caso las funciones stroke() y fill() de la variable ctx (contexto del canvas):
  • arc(x,y,r,start,stop): x e y son las coordenadas del centro, r el radio, start el ángulo de inicio del arco (en radianes) y stop el ángulo final del arco (en radianes).
function draw(){
    ctx.beginPath();
    ctx.arc(95,50,40,0,2*Math.PI);// centro en 95,50, radio 40,
    // arco desde 0 radianes a 2*pi, que es la circunferencia completa
    ctx.stroke(); // para dibujar la linea, negra por defecto.
    ctx.fillStyle = 'rgb(0,255,0)'; // color de relleno verde
    ctx.fill(); // lo rellenamos.
}
El resultado de este ejemplo sería:
Hay que tener en cuenta que el ángulo 0 radianes se correspondería con el este si hubiese una rosa de los vientos dibujada, y que el ángulo crece a partir de ese punto en el sentido de las agujas del reloj (sentido horario):

Escribir texto en el canvas

Esto puede resultar muy útil. Para escribir hay que definir las propiedades del texto y luego escribir el texto en el canvas, pudiendo elegirse entre escribir el texto relleno o sólo el trazo exterior. Las funciones son:
  • font("propiedades del texto"): donde propiedades del texto es un estilo a la manera de CSS. Por ejemplo se puede definir tamaño y tipo de fuente. Por ejemplo "15px Arial"
  • fillText(texto, x, y): dibuja el texto relleno a partir de las posiciones x,y del canvas.
  • strokeText(texto, x, y): dibuja sólo el trazo exterior del texto a partir de las posiciones x, y el canvas.
function draw(){
    ctx.font="15px Arial";
    ctx.fillText("Hola Mundo!",0,15);//como la fuente es de 15 píxeles
    // el texto aparece a partir de la esquina superior izquierda.
    ctx.font="30px Arial";// aumentamos el tamaño de la fuente
    // para que se aprecie que strokeText sólo pinta el borde
    ctx.strokeText("Hola Mundo 2!", 0, 75); // sólo trazo.
}
Y el resultado:

Incluir imágenes en el canvas

Esta es una de las funciones más útiles del canvas y por ello le vamos a dedicar un post completo específicamente para ello.

martes, 16 de abril de 2013

El DOM

El DOM es el Document Object Model, el modelo de objeto documento para un documento HTML. Es un estándar que define cómo acceder, cambiar o eliminar mediante un script un elemento en una página web.
Hay un tutorial específico para el DOM en w3schools. Aquí nos vamos a ceñir a lo mínimo que necesitaremos de momento, que es acceder a un elemento de un documento HTML por su atributo id y cambiar el contenido de un elemento HTML.
Los elementos del DOM tienen funciones (métodos) y propiedades. De momento sólo vamos a necesitar usar uno de cada: la función getElementById de la variable document, que contiene todo el documento HTMLy la propiedad innerHTML de los elementos que tienen etiqueta de apertura y de cierre, que contiene el HTMLque queda entre ambas etiquetas, el HTML"de dentro" del elemento.

Acceder a un elemento por su id con getElementById("id")

var element=document.getElementById("id_del_elemento")
Ejemplo:
si tenemos la siguiente página web con un canvas con id="my_canvas"
<html>
 <head> 
</head> 
<body>
  <canvas id="my_canvas" width="200" height="100"></canvas> 
</body>
</html>
accederíamos al canvas desde un script javascript (y lo asignaríamos a una variable llamada canvas) con :
var canvas = document.getElementById("my_canvas");

Cambiar el contenido de un elemento cambiando su propiedad innerHTML.

En particular, cambiar el contenido de texto de un elemento. Recordemos que el contenido de un elemento HTML es lo que queda entre las etiquetas de apertura y de cierre. Uno de los errores más comunes consiste en cambiar el contenido de un elemento que no tiene texto como contenido sino que contiene otros elementos. Por ejemplo el elemento <head> suele contener otros elementos HTMLen lugar de texto.

Por ejemplo, si tenemos el siguiente elemento:
<title id="titulo">Este es el viejo título de la página </title>
podríamos cambiar el texto del título de la página web mediante un script de javascript con las siguientes instrucciones:
var titulo =  document.getElementById("titulo");
titulo.innerHTML = "Nuevo Título!!!!";
Para abreviar se podrían encadenar ambas instrucciones en una sola:
document.getElementById("titulo").innerHTML = "Nuevo Título!!!!";

Esto es todo lo que necesitamos saber sobre el DOM de momento.

Introducción a javascript

Se va a hacer una muy somera introducción a javascript: qué es y cómo se incluye en una página web.Para aprenderlo hay multitud de recursos en la web, muchos de ellos gratuitos.
Javascript es un lenguaje de programación con las siguientes características principales:
  • interpretado: no se compila para generar un ejecutable, lo interpreta otro programa, normalmente un navegador web.
  • imperativo: un programa consta de instrucciones.
  • debilmente tipado: no se fuerza que las variables sean de tipos concretos. Se puede asignar cualquier tipo de datos a cualquier variable, aunque antes hubiese contenido otro tipo de datos.
  • orientado a objetos, aunque se puede pueden hacer programas que no lo aprovechen.
Sobre todo se utiliza en el lado del cliente (el navegador) para mejorar la interfaz de usuario en páginas web dinámicas. Es el lenguaje de scripting de la web más usado y extendido. Si el HTML es el contenido de la página y el CSS su apariencia, el javascript sería la interactividad (a grosso modo).

Javascript tiene una sintaxis similar al lenguaje de programación C y a pesar de su nombre, no tiene nada que ver con el lenguaje de programación Java.

En javascript, el programa en si se encuentra en la página web en forma de script (guión o secuencia de comandos). Puede estar dentro del propio HTML o bien puede estar en un archivo separado.

Incluir javascript en una página web

El programa javascript se puede incluir en una página web entre las etiquetas HTML <script> y </script>. En función de lo que vaya a  hacer el script y del diseño de la página, se puede incluir dentro del elemento <head> o del elemento <body>. Por motivos de compatibilidad con algunos navegadores y con versiones anteriores de HTML, conviene incluir el atributo type = "text/javascript".
Un ejemplo de inclusión del script dentro del elemento <head>:
<!DOCTYPE html>
<html>
 <head>
  <script type="text/javascript">
   alert("Hola mundo!");
  </script>
 </head>
 <body>
 </body>
</html> 
Este script consiste en una única instrucción que llama a la función alert con una cadena de texto (va entre comillas dobles) como argumento: "Hola mundo!". Las instrucciones deben terminar con punto y coma. La función alert hace salir un cuadro de alerta con el texto que se le haya pasado con argumento. El cuadro de alerta tiene un botón "Aceptar" para cerrarlo.

Incluir javascript desde otro archivo

Muchas veces, por motivos de claridad, reusabilidad y mejor organización del código, se separa el HTML de una página en un archivo .htm o .html y el javascript en uno o más archivos diferentes con extensión .js. Para incluir un archivo conteniendo un script javascript en un archivo HTML se usan también las etiquetas <script> y </script>, pero se lugar de poner el script entre ambas, se usa el atributo src de la etiqueta <script> para definir el archivo que se desea incluir. El atributo src puede ser un camino absoluto o un camino relativo y es un URL, así que puede inluirse en una página un archivo .js que se encuentre en una localización de internet que no tenga nada que ver con la página original, por ejemplo para incluir una librería que ha desarrollado un tercero y a la que se proporciona acceso desde internet.
Por ejemplo, para incluir la popular librería jQuery:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js">
</script>
Por otra parte, si tenemos una carpeta con un archivo miPagina.html y un archivo misFunciones.js. Para incluir el archivo .js deberíamos escribir lo siguiente en miPagina.html:
<script type="text/javascript" src="misFunciones.js"></script> 
Por motivos de orden, los archivos con javascript no se suelen poner al mismo nivel que los archivos html, supongamos que dentro de la carpeta tenemos el archivo html y otra carpeta llamada "js" donde se encuentra el archivo javascript. En ese caso:
<script src="/js/misFunciones.js"></script>
Tras esta breve presentación del lenguaje javascript, conviene ir a cualquiera de los muchos recursos que hay disponibles en internet para aprenderlo.

sábado, 6 de abril de 2013

Plantilla html

<!DOCTYPE html>
<html>
 <head>
 </head>
 <body>
 </body>
</html>

Introducción a html

Una pequeña introducción al html, que no sustituye a ninguno de los muchos recursos para aprender html que hay en la web. El html puede ser un poco intimidante por la cantidad de etiquetas y atributos y opciones de posicionado. Con esta introducción se pretende presentar lo básico que es necesario conocer para empezar a hacer cosas en html.
 
Html, hypertext markup lenguaje, lenguaje de marcado de hipertexto, es un lenguaje que sirve para describir documentos, específicamente páginas web. Es parte del un lenguaje más extenso y general XML o XHTML (la X viene de eXtendido) que sirve para describir todo tipo de documentos.
En html un documento está formado por elementos. Cada elemento se escribe mediante etiquetas (o marcas, de ahí lo de lenguaje de marcado).

Etiquetas html (tags)

Las etiquetas constan de una o más palabras rodeadas por corchetes angulares(<,>). Pueden ser de apertura o de cierre. Las de cierre comienzan por una barra / dentro de los corchetes angulares.

Ejemplo:
Etiqueta de apertura: <html>
Etiqueta de cierre: </html>

Elementos html

Hay 2 tipos de elementos en cuanto al número de etiquetas:
  • Elementos con 2 etiquetas, una de apertura y otra de cierre.
  • Elementos con 1 etiqueta. El ejemplo más claro es <br>, que sirve para marcar un salto de linea.
Los elementos pueden tener 2 tipos de componentes:
  • atributos: suelen seguir al identificador del tipo de etiqueta y proporcionan información adicional acerca del elemento. Vienen en forma de pares nombre_de_atributo = "valor"
  • contenido: Es lo que queda entre las etiquetas de apertura y cierre.
Ejemplo:
<a href="http://www.w3schools.com"> buena página para aprender html</a>

Cómo se vé en un navegador web:   buena página para aprender html

En este ejemplo tenemos un elemento html que es un hipervinculo o enlace. Los enlaces se marcan con la etiqueta <a>. El hipervínculo tiene un atributo href que se utiliza para especificar la página a la que apunta el hipervinculo. Este hipervinculo apunta a http://www.w3schools.com. El enlace tiene un contenido, que es el texto: buena página para aprender html. El enlace termina con una etiqueta de cierre de hipervínculo: </a>

Hay elementos y etiquetas html para marcar todo tipo de elementos que pueden incluirse en un documento:
distintos niveles de encabezado: h1, h2, h3, h4...
hipervinculos: <a>
saltos de linea: <br>
párrafos: <p>
imágenes: <im>
párrafos pre-formateados: <pre>
y una larga lista más, que no tiene sentido repetir aquí.

Algunas particularidades del html

  • El html no es sensible al caso: las etiquetas, atributos, etc se pueden escribir en mayúsculas, minúsculas o cualquier combinación de las mismas. A pesar de ello conviene seguir un estilo consistente por claridad. En particular yo prefiero escribir todo en minúsculas.
  • En un documento html el formato viene especificado en el propio documento, da igual el formato que se le dé al archivo en si. Por ejemplo:
<p>
Esto es un párrafo con una primera linea
y una segunda linea,
y una tercera, pero como no se han especificado los saltos de linea con
etiquetas, el texto sale todo seguido en un navegador web, ocupando el
espacio que tenga que ocupar.
</p>

En un navegador web eso se ve:

Esto es un párrafo con una primera linea y una segunda linea, y una tercera, pero como no se han especificado los saltos de linea con etiquetas, el texto sale todo seguido en un navegador web, ocupando el espacio que tenga que ocupar.

Para especificar los saltos de linea habría que haberlos marcado con etiquetas <br>:
<p>
Esto es un párrafo con una primera linea <br>
y una segunda linea, <br>
y una tercera, pero como no se han especificado los saltos de linea con
etiquetas, el texto sale todo seguido en un navegador web, ocupando el 
espacio que tenga que ocupar.
</p> 

o bien haber usado la etiqueta <pre> en lugar de <p>, que sirve para marcar texto preformateado, que es texto que se mostrará tal cual está escrito en el archivo html.
<pre>
Esto es un párrafo con una primera linea
y una segunda linea,
y una tercera, pero como no se han especificado los saltos de linea con 
etiquetas, el texto sale todo seguido en un navegador web, ocupando el 
espacio que tenga que ocupar.
</pre>

  • Los caracteres barra de espacio consecutivos se eliminan, hasta dejar sólo uno. Así:
esto es un texto con muchos              espacios en blanco en el medio

Si no se usa la etiqueta <pre> se vé en un navegador como:
esto es un texto con muchos espacios en blanco en el medio
  •  Los comentarios (notas explicativas o similar que se escriben en un archivo pero que no se quiere que interprete el navegador web y que es como si no estuvieran escritas) se abren con <!-- y se cierran con -->

Orden y colocación de elementos

Cómo se ordenan y colocan los elementos en una página es un tema complicado y daría para un curso en sí mismo. Como sólo pretendemos dar unas nociones muy básicas de html se aconseja ir a una buena página para aprender html para esa y otras cuestiones.

Un documento html5 mínimo

A continuación se presenta el esqueleto mínimo de documento html. Estrictamente podría tener menos elementos, pero lo más común es que tenga al menos un elemento<html> y dentro de ellos un elemento <head> y un elmento <body>. Además el elemento <!DOCTYPE html> especifica que se trata de un documento html5. Para el elemento DOCTYPE es el único para el que me salto la norma de escribir las etiquetas en minúscula.

<!DOCTYPE html>
<html>
 <head>
 </head>
 <body>
 </body>
</html>

Eso es un documento html válido. Si se escribe en un archivo en un editor de texto y se guarda con extensión .html o .htm y luego se abre ese archivo con un navegador web se vé..... nada :D porque aparte de declarar los elementos básicos no hemos incluido ningún contenido en ellos. Lo normal será incluir un <title> en el <head> y algún encabezado y texto en el <body>. Por ejemplo:

<!DOCTYPE html>
<html>
 <head>
  <title> El título de la página sale en la pestaña del navegador </title>
 </head>
 <body>
   <h1> Encabezado de primer nivel <h1>
  <p> Texto.....................</p>
 </body>
</html>

Para trastear con html

Un par de opciones sencillas:
  • usar un editor de texto y crear un archivo con extensión .htm o .html y abrirlo con un navegador web.
  • usar el editor interactivo de w3schools. En un lado se escribe y en el otro aparece el resultado tras presionar el botón "Submit code".

viernes, 5 de abril de 2013

Recursos para aprender html, html5 y javascript

Cursos, tutoriales, hojas de referencia y guías online... hay gran cantidad de recursos disponibles en la web para aprender y consultar cosas acerca de HTML5 y javascript y una búsqueda en google arroja un montón de resultados en los que los primeros resultados seguramente sean una buena opción. Como hay tanta oferta sólo voy a poner aquí las que me han gustado. Iré actualizando esta lista a medida que vaya encontrando cosas interesantes.

Generales

  • w3schools: web gratuita, con cursos, tutoriales y referencia de HTML, HTML5, javascript y muchos otros temas relacionados con el desarrollo web. Aunque hay gente a la que no le gusta y dicen que tiene algún fallo, a mi me parece de las mejores, tanto para aprender desde 0 como para usar de referencia.
  • Desarrollo Web para no iniciados, en 5 partes, de cartuchoGL.
  • Varios libros de programación de O'Reily para leer online, en O'Reilly Atlas.

HTML5

Canvas

Javascript

Depuración

Herramientas

Para programar en html5 y javascript lo único estrictamente necesario es un editor de texto sencillo y un navegador web.

Editor de texto

Se podría usar el bloc de notas de Windows o cualquiera de los editores de Linux, pero recomiendo un editor un poco más avanzado, que sin perder simplicidad de uso, tenga características básicas como el resaltado de la sintaxis. Cualquiera de los 2 siguientes es buena opción:

  • Notepad++: de código libre y gratuito. Muy sencillo de usar y bastante completo. Si no tienes práctica con el Sublime Text 2 usa éste.
  • Sublime Text 2: de código cerrado y de pago, pero con versión de prueba sin límites de uso. Con prestaciones bastante más avanzadas pero por ello más dificil de usar bien. Se puede descargar la versión de prueba para Windows 32 y 64 bit, Linux 32 y 64 bit y Mac OS X en la página web oficial.

Navegador Web

Podría valer cualquiera, en principio, pero cada uno de ellos y cada versión va implementando cada vez más características del estándar de html5 y de javascript, así que lo recomendable es usar la última versión de un navegador que tenga una buena compatibilidad con html5 y javascript. Además hay ciertas incompatibilidades entre unos navegadores y otros, así que lo recomendable es usar uno que se ciña bastante bien al estándar, por ejemplo:


Hojas de referencia

Esas son las herramientas necesarias, pero como complemento no está de más tener un par de hojas de referencia rápida para consultar la sintaxis, tanto de html5 como de javascript:
  • Html5 Quick Reference Guide: descargable en pdf desde esta página del sitio web de Veign.
  • Javascript Reference Card: descargable en pdf desde esta página de Addison-Wesley.
  • Html5 Canvas Cheat Sheet: pdf.

Otras hojas de referencia (para gustos los colores):


Detección de errores en javascript

  • JSHint: en versión web y también disponible como plugin para algunos editores de texto populares, en partitcular, JSLint para Notepad++.(El plugin JSLint para Notepad++ es compatible con JSHint).
  • JSLint: en versión web y también en el plugin JSLint para Notepad++.
Las dos herramientas son similares, JSLint es la original y JSHint surgió después. Ha habido grandes discusiones en internet acerca de ambas herramientas y sus distintas filosofías. Sin ganas de entrar en polémicas, yo prefiero JSHint porque no se queja de las declaraciones de variables en la instruccion for. Resulta que algo tan común y correcto como:

for(var i=0; i < iteraciones; i++){}

JSLint lo considera  una aberración.

Presentación

El objetivo de este blog es recopilar notas acerca de programación en html 5 y javascript y servir de sencillo tutorial de iniciación. La idea no es hacer un curso de html5 ni de javascript (ya hay muchos y buenos cursos y tutoriales sobre el tema) sino proporcionar las mínimas bases para desarrollar juegos sencillos  para ejecutar en local.