Entrada destacada

Como usar enums en Android, kotlin

Cómo crear una cuadrícula de dibujo en Canvas (HTML y JavasScript)

En este tutorial veremos como crear una cuadrícula de dibujo básica utilizando JavaScript y HTML el resultado que obtendremos se puede ver en la siguiente imagen.


La idea general es dibujar la cuadrícula usando líneas y guardar cada uno de los cuadritos dibujados en un arreglo de dos dimensiones para que al pulsar dentro del canvas con el mouse podamos comprobar dentro de que cuadro se ha hecho click y rellenar el cuadro según el color seleccionado del input tipo "color", también agregaremos un input tipo "range" para cambiar el tamaño de los cuadros de la cuadrícula.



La parte HTML

Empecemos creando la estructura html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Cuadrícula</title>
  <link rel="stylesheet" href="css/style.css">
  <script src="js/app.js"></script>
</head>
<body>
  <div id="Contenedor">
    <h1><p>Grid Canvas</p></h1>
    <div id="contenedorCanvas">
      <canvas id="canvas1" width="600" height="580">
        Tu navegador no soporta canvas
      </canvas>
    </div>
    <div id="herramientas">
      Color: <input type="color" id="color" value="#FF0000"/>
      Tamaño <input type="range" id="sizeCuadros" value="20" min="5" max="100">
    </div>
  </div>
</body>
</html>

Como podemos darnos cuenta el código html necesarios no es mucho ya que sólo necesitamos el elemento <canvas> y los elementos <input> para elegir el color de relleno y el tamaño de los cuadros de la cuadrícula, la mayoría del código que utilizaremos será javascript.

La parte CSS

Ahora utilizaremos un poco de estilos css para hacer que nuestra aplicación tenga una mejor presentación.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
body {
  background: rgba(25, 100, 120, 0.5);
}
h1 {
  font-family: Pacifico, serif ;
  color: #FF3333;
  font-size: 2.5em;
  text-align: center;
  transition: all 0.5s;
  margin: 0;
  padding: 0;
}
p {
  margin: 0 0 6px 0;
  padding: 0;
}
h1:hover {
  animation: neon2 1.5s ease-in-out infinite alternate;
}
canvas {
  background-color: #FFF;
  border: dotted 3px yellow;
  border-radius: 2px;
}
@keyframes neon2 {
  from {
    text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #228DFF, 0 0 70px #228DFF, 0 0 80px #228DFF, 0 0 100px #228DFF, 0 0 150px #228DFF;
  }
  to {
    text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #fff, 0 0 20px #228DFF, 0 0 35px #228DFF, 0 0 40px #228DFF, 0 0 50px #228DFF, 0 0 75px #228DFF;
  }
}
#contenedorCanvas{
  text-align: center;
}
#herramientas {
  margin: 10px 60px 10px 60px;
  padding: 20px;
  border: 4px solid #FF4444;
  border-radius: 3px;
  background: #FFE94A;
}

Está parte también no es tan compleja incluso no afectaría en nada el funcionamiento si no se usa, no obstante, no nos cuesta mayor esfuerzo el darle algunos colores de bordes o de fondo a los elementos <div> que contienen a los elementos necesarios para poder visualizar con mayor detalle las partes importantes de la página.


Ahora sí, el código JavaScript

Veamos parte por parte del código javascript que es necesario para dibujar la cuadrícula y poder dibujar sobre ella.

Comenzamos definiendo alguna variables para el control de la aplicación en general, tal como el estado del mouse, el elemento <canvas> y el <div> contenedor de todos los elementos para poder acceder a sus propiedades de tamaño y ajustar el tamaño del canvas según sea el tamaño de la ventana, la variable cuadritos almacenará las coordenadas y tamaño de cada uno de los cuadros de la cuadrícula, la variables sizeCuadro es un objeto en el cual se define el tamaño inicial que tendrán todos los cuadros, la variable color almacenará el color que se elija y finalmente iputColor y inputSizeCuadros representan los elementos <input> de color y tamaño. Después en las líneas 11 a 13 se comprueba que el contexto del canvas se cargue correctamente antes de empezar a dibujar.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
window.onload = function() {
    var mouse = false;
    var canvas = document.getElementById("canvas1");
    var contenedor = document.getElementById("Contenedor");
    var cuadritos = [];
    var sizeCuadro = {ancho: 25, alto: 25};
    var color = "";
    var inputColor = document.getElementById("color");
    var inputSizeCuadros = document.getElementById("sizeCuadros");

    if (canvas && canvas.getContext) {
        var ctx = canvas.getContext("2d");
        if (ctx) {

Para dibujar la cuadrícula utilizamos la función dibujarGrid, la cual recibe como parámetros el tamaño de los cuadros que en realidad son la distancia en 'x' entre la líneas verticales y la distancia en 'y' para las líneas horizontales. Primeramente configuramos el estilo de las líneas, el cual es ajustado con el parámetro color y el ancho de línea, el arreglo columnas almacena las coordenadas generadas en el eje x y el arreglo filas es usado para las coordenadas en el eje y. 

Bien ahora a partir de la línea 19 iteramos hasta llegar al ancho total del canvas empezando a partir del ancho de un cuadro, suponiendo que las medidas de cada cuadro son ancho=20 y alto=20, entonces el primer valor de i será 20 y cada iteración aumentara 20 pixeles. El primer bucle for dibujará líneas verticales, en canvas para dibujar líneas usamos paths, con moveTo(x,y) definimos el inicio de la línea y con lineTo(x,y) el punto final.


Con el segundo bucle for hacemos lo mismo pero para dibujar líneas horizontales.


14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
            function dibujaGrid(disX, disY, anchoLinea, color){
                ctx.strokeStyle = color;
                ctx.lineWidth = anchoLinea;
                var columnas = [];
                var filas = [];
                for (i = disX; i < canvas.width; i += disX) {
                    ctx.beginPath();
                    ctx.moveTo(i, 0);
                    ctx.lineTo(i, canvas.height);
                    ctx.stroke();
                    columnas.push(i);
                }
                for (i = disY; i < canvas.height; i += disY) {
                    ctx.beginPath();
                    ctx.moveTo(0, i);
                    ctx.lineTo(ctx.canvas.width, i);
                    ctx.stroke();
                    filas.push(i);
                }
                columnas.push(0);
                filas.push(0);
                for (x = 0; x < columnas.length; x++) {
                    for (y = 0; y < filas.length; y++) {
                        cuadritos.push([columnas[x], filas[y], disX, disY]);
                    }
                }
            }

Una vez terminado de dibujar las líneas unimos los valores de los dos arreglos (filas y columnas) en un sólo arreglo que representará todos los cuadros de la cuadrícula.

Cuando se dibujan todas la líneas (verticales y horizontales) la cuadrícula es dibujada.


La función fillCell recibe las coordenadas de la posición del mouse que podemos obtener al hacer click sobre el canvas o al mantener pulsado el botón del mouse y arrastrarlo sobre la pantalla. Antes de poder rellenar algún cuadro configuramos el estilo del relleno el cual será un color solido que obtendremos del <input> de tipo color. 
Para rellenar un espacio de la cuadrícula comprobamos si las coordenadas del mouse están dentro de alguno de los cuadros del arreglo cuadritos, mediante un bucle for recorremos el arreglo y uno a uno comprobamos dentro de que cuadro se encuentra el cursor del mouse, cuando es localizado se dibuja un rectángulo relleno con las medidas del cuadro que ha sido seleccionado.

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
            
            function fillCell(x, y) {
                color = inputColor.value;
                ctx.fillStyle = color;
                for (i = 0; i < cuadritos.length; i++) {
                    var cuadro = cuadritos[i];
                    if (
                        x > cuadro[0] &&
                        x < cuadro[0] + cuadro[2] &&
                        y > cuadro[1] &&
                        y < cuadro[1] + cuadro[3]
                    ) {
                        ctx.fillRect(cuadro[0], cuadro[1], sizeCuadro.ancho, sizeCuadro.alto);
                    }
                }
                dibujaGrid(sizeCuadro.ancho, sizeCuadro.alto, 0.4, "#44414B");
            }

Después de rellenar el espacio podemos usar la sentencia break para optimizar la aplicación, finalmente llamamos a la función dibujaGrid para que la rejilla siempre se visualice. 

Para completar la aplicación implementamos los eventos onclick y onmousemove sobre canvas, obtendremos la coordenadas al detectar que el mouse se mueve sólo si algún botón del mouse está pulsado. Para detectar en que estado se encuentran los botones usamos onmousedown para cuando es pulsado y onmouseup cuando el botón es liberado. Al obtener las coordenadas del mouse mediante e.clientX y e.clienteY debemos ajustar estas coordenadas mediante las coordenadas en que se encuentra el canvas en el documento, ya que clientX y clientY son coordenadas relativas al documento y no al canvas.


59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
            canvas.onmousemove = function(e) {
                if(mouse){
                    var canvaspos = canvas.getBoundingClientRect();
                    fillCell(e.clientX - canvaspos.left, e.clientY - canvaspos.top);
                }
            };

            canvas.onclick = function(e){
                var canvaspos = canvas.getBoundingClientRect();
                fillCell(e.clientX - canvaspos.left, e.clientY - canvaspos.top)
            };

            canvas.onmousedown = function() {
                mouse = true;
            };

            canvas.onmouseup = function() {
                mouse = false;
            };

Finalmente para poder cambiar el tamaño de los cuadros de la cuadrícula detectamos cuando el valor del <input> tipo range cambia, pasamos el nuevo valor a las medidas de los cuadros, a la vez limpiamos el arreglo cuadritos, limpiamos todo lo que se ha dibujado en el contexto y volvemos a dibujar el grid.

En la línea 87 asignamos una medida para el ancho del canvas, esto hará que se ajuste a las medidas de la ventana y finalmente en la línea 88 se dibuja inicialmente la cuadrícula.

79
80
81
82
83
84
85
86
87
88
            inputSizeCuadros.addEventListener('change', function () {
                cuadritos = [];
                sizeCuadro.ancho = parseInt(this.value);
                sizeCuadro.alto = parseInt(this.value);
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                dibujaGrid(sizeCuadro.ancho, sizeCuadro.alto, 1, "#44414B");
            }, false);

            canvas.width = contenedor.offsetWidth - 400;
            dibujaGrid(sizeCuadro.ancho, sizeCuadro.alto, 1, "#44414B");

Código fuente completo


See the Pen Cuadricula en Canvas by Jesus Tepec (@JesusTepec) on CodePen.


O también puedes descargar los archivos visitando el repositorio GridCanvas.

Comenta tus dudas en la sección de comentarios.

Comentarios

  1. Respuestas
    1. Hola, qué código no te funciona? haciendo paso a paso o descargando los archivos de github?

      Eliminar
  2. Muy interesante tuto, solo estaba buscando para las pruebas de The Odin Project como pintar los divs dentro de un contenedor DIV con js y me consigo con un tuto de lo más completo; gracias por tu aporte.

    ResponderEliminar

Publicar un comentario