En esta serie de dos partes, combinaremos el versátil elemento de lienzo con la robusta biblioteca jQuery para crear un complemento de gráficos de barras. En esta primera parte, vamos a codificar la lógica central del complemento como una versión independiente.
Hoy vamos a crear un plugin de gráficos de barras. No es un plugin ordinario, fíjate. Mostraremos un poco de amor por jQuery al elemento del lienzo para crear un complemento muy robusto..
En este artículo de dos partes, comenzaremos desde el principio implementando la lógica del complemento como una secuencia de comandos independiente, refactorizándolo en un complemento y, finalmente, agregando todos los complementos adicionales al código del complemento. En esta primera parte, vamos a tratar únicamente con la implementación de la lógica central.
¿Necesitas un ejemplo antes de empezar? Aqui tienes!
¿Satisfecho? ¿Interesado ya? Empecemos.
Nuestro complemento necesita lograr algunas cosas básicas mientras que no hace otras cosas. Déjame aclarar:
A medida que nos adentramos en el mundo de la tecnología de vanguardia, aún no totalmente especificada, tenemos algunas dependencias. Para que el elemento lienzo funcione, la mayoría de los navegadores modernos son suficientes. Pero como hacemos uso de la nueva API de representación de texto, necesitamos compilaciones más nuevas. Los navegadores que utilizan el motor Webkit r433xx y superior o el motor Gecko 1.9.1 y superior deben ser plataformas excelentes para el complemento. Recomiendo agarrar una compilación nocturna de Chromium o Firefox.
Me gustaría mencionar que nuestro plugin es solo para propósitos de aprendizaje. Este complemento no pretende de ninguna manera reemplazar otros complementos gráficos completos como Flot, Plotr y similares. Además, el código será lo más detallado posible. Usted podría escribir lejos, lejos Código más eficiente, pero por el bien del aprendizaje, todo va a ser lo más sencillo posible. Siéntase libre de refactorizarlo a favor de la eficiencia en su código de producción.
OMG WTF HAX
Año | Ventas |
---|---|
2009 | 130 |
2008 | 200 |
2007 | 145 |
2006 | 140 |
2005 | 210 |
2004 | 250 |
2003 | 170 |
2002 | 215 |
2001 | 115 |
2000 | 135 |
1999 | 110 |
1998 | 180 |
1997 | 105 |
Nada especial en el marcado. Voy a hacer una visión general rápida de todos modos.
Antes de iniciar el Javascript, permítanme explicar el sistema de coordenadas del lienzo. La esquina superior izquierda actúa como el origen, es decir (0, 0). Los puntos se miden con respecto al origen, con x aumentando a lo largo de la derecha e y aumentando a lo largo de la izquierda. Para los inclinados matemáticamente, estamos trabajando efectivamente en el cuarto cuadrante, excepto que tomamos el valor absoluto de y en lugar de su valor negativo. Si ha trabajado con gráficos en otros idiomas, debería estar en casa aquí..
La rutina de renderización del rectángulo de Canvas se utilizará ampliamente en todo el artículo para representar las barras, la cuadrícula y algunos otros elementos. Con eso en mente, echemos un vistazo a esas rutinas.
De las tres rutinas disponibles, usaremos el fillRect y strokeRect metodos los fillRect El método en realidad llena el rectángulo renderizado mientras que el strokeRect El método solo traza los rectángulos. Aparte de eso, ambos métodos toman los mismos parámetros.
Como siempre, te recomiendo que descargues el código fuente y lo tengas en el lado como referencia. Es más fácil mirar la imagen general y analizar cada función una por una que mirar cada función individualmente y luego crear la imagen grande en su mente.
var barSpacing = 20, barWidth = 20, cvHeight = 220, numYlabels = 8, xOffset = 20, gWidth = 550, gHeight = 200; var maxVal, gValues = [], xLabels = [], yLabels = []; var cv, ctx;
Estas variables contienen valores codificados para ayudarnos a posicionar y diseñar el gráfico y las barras individuales..
Con el potente motor de selección de jQuery, nos resulta muy fácil obtener los datos que necesitamos. Aquí tenemos varias formas de acceder a los elementos necesarios. Permítanme explicarles a continuación:
$ ("tr"). children ("td: odd"). each (function () // code here);
La forma más sencilla de acceder a las filas necesarias. Busca un tr elemento y luego accede a todos los demás td elemento. Falla miserablemente cuando tienes más de una tabla en tu página.
$ ("# data"). find ("td: odd"). each (function () // code here);
Un camino mucho más directo. Pasamos el ID de la tabla y luego accedemos a cada otra fila.
$ ("# data tr td: odd"). each (function () // code here);
Igual que el anterior, excepto que solo usamos la sintaxis del selector de estilo CSS.
$ ("# data tr td: nth-child (2)"). each (function () // code here);
La versión que vamos a utilizar hoy. De esta manera es mucho mejor si necesitamos capturar datos de una fila diferente o, si es necesario, varias filas.
La versión final se ve así:
function grabValues () // Acceda a la celda de la tabla requerida, extraiga y agregue su valor a la matriz de valores. $ ("# data tr td: nth-child (2)"). each (function () gValues.push ($ (this) .text ());); // Acceda a la celda de la tabla requerida, extraiga y agregue su valor a la matriz xLabels. $ ("# data tr td: nth-child (1)"). each (function () xLabels.push ($ (this) .text ()););
Nada complicado aquí. Usamos el fragmento de código mencionado anteriormente para agregar el valor de la celda de la tabla a la gValores formación. A continuación, hacemos lo mismo, excepto que accedemos a la primera celda de la tabla para extraer la etiqueta necesaria para el eje x. Hemos encapsulado la lógica de extracción de datos en su propia función para la reutilización y legibilidad del código..
function initCanvas () // Intente acceder al elemento del lienzo y lanzar un error si no está disponible cv = $ ("# graph"). get (0); if (! cv) return; // Trate de obtener un contexto 2D para el lienzo y arroje un error si no puede ctx = cv.getContext ('2d'); if (! ctx) return;
Inicialización de lienzo de rutina. Primero intentamos acceder al propio elemento del lienzo. Lanzamos un error si no podemos. A continuación, tratamos de obtener una referencia al contexto de representación 2d a través de getContext Método y lanzar un error si no podemos hacerlo.
Antes de pasar a la representación real del gráfico en sí, necesitamos ver una serie de funciones de utilidad que nos ayudan mucho en el proceso. Cada uno de ellos es pequeño por sí mismo, pero se utilizará ampliamente en todo nuestro código..
función maxValues (arr) maxVal = 0; para (i = 0; iUna pequeña función que recorre la matriz pasada y actualiza la maxVal variable. Tenga en cuenta que inflamos el valor máximo en un 10% para fines especiales. Si el valor máximo se deja como está, entonces la barra que representa el valor más alto tocará el borde del elemento de lienzo que no deseamos. Con eso en mente, se emite un incremento del 10%..
Normalizando el valor
escala de funciones (param) return Math.round ((param / maxVal) * gHeight);Una pequeña función para normalizar el valor extraído con respecto a la altura del elemento del lienzo. Esta función se usa ampliamente en otras funciones y directamente en nuestro código para expresar el valor como una función de la altura del lienzo. Toma un solo parámetro.
Devolviendo la coordenada X
función x (param) return (param * barWidth) + ((param + 1) * barSpacing) + xOffset;Devuelve la ordenada x al fillRect Para ayudarnos en el posicionamiento de cada barra individual. Explicaré esto un poco más en detalle cuando se use..
Devolviendo la coordenada Y
función y (param) return gHeight - scale (param);Devuelve la ordenada y al fillRect Método para ayudarnos en el posicionamiento de cada barra individual. Más explicaciones un poco más tarde..
Devolviendo el Ancho
ancho de la función () return barWidth;Devuelve el ancho de cada barra individual..
Volviendo la altura
función altura (param) retorno escala (param);Devuelve la altura de la barra a dibujar. Utiliza el escala función para normalizar el valor y luego lo devuelve a la persona que llama.
Dibujando las etiquetas del eje X
función drawXlabels () ctx.save (); ctx.font = "10px 'arial'"; ctx.fillStyle = "# 000"; para (índice = 0; índiceUna función simple para renderizar las etiquetas del eje x. Primero guardamos el estado actual del lienzo, incluyendo todas las configuraciones de renderización, de modo que cualquier cosa que hagamos dentro de las funciones nunca se filtre. Luego establecemos el tamaño y la fuente de las etiquetas. A continuación, iteramos a través de la xLabels array y llama al fillText Método cada vez para hacer la etiqueta. Usamos el X Función que nos ayuda en el posicionamiento de las etiquetas..
Dibujando las etiquetas del eje Y
función drawYlabels () ctx.save (); para (índice = 0; índiceUna función algo más verbosa. Primero guardamos el estado actual del lienzo y luego procedemos. A continuación dividimos maxVal's Valor en n elementos donde la variable NumYlabels dicta n. Estos valores se agregan a la yLabels formación. Ahora, como se muestra arriba, la fillText Se llama método para dibujar las etiquetas individuales con el y Función que nos ayuda en el posicionamiento de cada etiqueta individual..
Hacemos un cero en la parte inferior del lienzo para terminar de dibujar las etiquetas Y.
Dibujando la gráfica
función drawGraph () for (index = 0; indexLa función que dibuja las barras reales en el gráfico de barras. Iteriza a través de la gValores Arreglo y renderiza cada barra individual. Usamos el fillRect Método para dibujar las barras. Como se explicó anteriormente, el método toma cuatro parámetros, cada uno de los cuales está a cargo de nuestras funciones de utilidad. El índice actual del bucle se pasa a nuestras funciones como parámetros junto con el valor real mantenido en la matriz, según sea necesario.
los X La función devuelve la coordenada x de la barra. Cada vez, se incrementa por el valor de la suma de barwidth y barra espaciadora variables.
los y La función calcula la diferencia entre la altura del elemento del lienzo y los datos normalizados y lo devuelve. Sé que esto suena un poco al revés, pero esto se debe al hecho de que los valores de y en la cuadrícula del lienzo aumentan al moverse hacia abajo, mientras que en nuestro gráfico los valores de y aumentan al ascender. Por lo tanto, tenemos que hacer un poco de trabajo para que funcione como deseamos..
los anchura La función devuelve el ancho de las barras individuales..
los altura La función simplemente devuelve el valor normalizado que se usará como la altura de la barra que se dibujará..
Resumen
En esta primera parte, hemos implementado la lógica base de nuestro complemento como una versión independiente con aspectos y características simples. Revisamos el sistema de coordenadas del lienzo, los métodos de renderización de rectángulos, algunos extraños datos extraídos utilizando el asombro innato de jQuery [¿He mencionado cuánto me gusta jQuery?], Observamos cómo se dibujan las etiquetas y finalmente observamos la lógica detrás de la renderización de la gráfica misma.
Al final de este artículo, la salida debería verse así.
Siguiente!
Nuestra implementación actual es bastante deficiente. Parece insípido, no puede crear múltiples gráficos en la misma página, y admitámoslo, es bastante espartano en el frente de características. Vamos a abordar todo eso la próxima semana. En el siguiente artículo vamos a:
- Refactoriza nuestro código para convertirlo en un complemento de jQuery completo.
- Añadir un poco de dulce de ojos.
- Incluye algunas pequeñas características ingeniosas.
Preguntas? Criticas? Alabanzas Siéntase libre de golpear los comentarios. Gracias por leer y, cuando esté listo, pase a la segunda parte!
- Síganos en Twitter o suscríbase a la Fuente RSS de NETTUTS para obtener más artículos y artículos de desarrollo web diarios.