inegicomponentes-grafica
Version:
Componentes de visualizacion 2023 - Graficas
604 lines (575 loc) • 23 kB
JavaScript
/*
Defaults.js
@descripcion: Objetos con valores por defecto.
> OpcionesHighcharts: opciones globales para Highcharts
> OpcionesGrafica: objeto de opciones de configuracion del gráfico
> ParametrosUsuario: objeto con los parametros de entrada del usuario aceptados por el componente
*/
import { GRAFICAS } from '../Utilidades/Constantes'
import Helper from '../Utilidades/Helper';
// Inicializa Highcharts
const OpcionesHighcharts = {
time: {
timezone: 'America/Mexico'
},
title:{text:""},
credits:{
enabled:true,
href:"https://www.inegi.org.mx",
position:{},
text:"INEGI"
},
lang:{
contextButtonTitle:"Opciones",
decimalPoint:".",
downloadCSV:"Descarga CSV",
downloadJPEG:"Descarga JPEG",
downloadPDF:"Descarga PDF",
downloadPNG:"Descarga PNG",
downloadSVG:"Descarga SVG",
downloadXLS:"Descarga XLS",
exitFullscreen:"Salir de pantalla completa",
exportInProgress:"Exportando...",
hideData:"Ocultar tabla de datos",
loading:"Cargando...",
months:["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"],
noData:"No hay datos para mostrar",
numericSymbolMagnitude:1000,
numericSymbols:["k", "M", "G", "T", "P", "E"],
playAsSound:"Escuchar sonido",
printChart:"Imprimir gráfica",
resetZoom:"Reiniciar Zoom",
resetZoomTitle:"Zoom 1:1",
shortMonths:["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"],
shortWeekdays:undefined,
thousandsSep:"\u0020",
viewData:"Ver tabla de datos",
viewFullscreen:"Ver pantalla completa",
weekdays:["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sabado"]
}
}
let OpcionesGrafica = {
chart:{
style:{
fontFamily:'"Lucida Grande", Verdana',
fontSize:'14px'
},
height:400,
type:"column",
animation:true,
backgroundColor:"",
borderColor:"#d71d2a",
inverted:false,
panning:{
enabled:true,
type:"xy"
},
zooming:{zoomType:"xy", pinchType:"xy"},
},
colors:["#264653", "#2a9d8f","#e9c46a","#457b9d","#f9844a","#9e2a2b","#f08080","#3a5a40","#f15bb5","#a3b18a","#f8961e", "#ffe66d", "#55a630", "#2b9348", "#a44a3f", "#a68a64", "#723d46", "#87986a", "#a53860", "#450920", "#f4e285", "#4a5759", "#55828b", "#004e89", "#f2d0a9", "#bfd8bd", "#b2ff9e", "#ece2d0", "#56ab91", "#c81d25", "#ff5400"],
// opciones para la carga de datos desde difentes metodos usando la propiedad DATA
data: {
// >>> grafica dede un archivo csv desde url:
// csvURL: 'https://demo-live-data.highcharts.com/vs-load.csv',
// enablePolling: true,
// dataRefreshRate: 5,
// >>> Desde una tabla html definida (solo usar su id en <table id="idHtmlDatatable">)
// table:"idHtmlDatatable"
// >>> Definicion por columnas:
/* columns: [
[null, 'Apples', 'Pears', 'Oranges'], // categories
['Ola', 1, 4, 3], // first series
['Kari', 5, 4, 2] // second series
] */
},
legend:{
accessibility:{
enabled:true,
},
sonification:{
},
enabled:true,
alignColumns:true,
verticalAlign:"bottom",
align:"left",
layout:"horizontal", // horizontal = leyenda debajo | vertical = leyenda izq-der (depende de align)
itemDistance:20,
itemHiddenStyle:{color:"#ccc"},
itemWidth:0,
backgroundColor:"",
borderColor: "#f1f1f1",
borderWidth: 0,
reversed:false, // invertir los items de orden
labelFormatter:function(){
return this.name
},
symbolHeight:10,
symbolWidth:10,
symbolRadius:0,
labelFormat:"{name}",
labelFormatter:undefined,
useHTML:true
},
exporting:{
enabled:false,
},
/* plotOptions:{
}, */
tooltip:{
enabled:true,
useHTML:true,
animation:true,
crosshairs:false, // agrega una banda vertical sobre el punto donde se posiciona el cursor
backgroundColor:"#FFFFFF",
borderColor:"#DADADA",
displayErrors:true,
borderWidth:1,
borderRadius:0,
followPointer:false,
hideDelay:200,
outside:true, // renderizar tooltip fuera del svg o dentro
shadow:false,
shared:false, // si es true se necesita modificar formatter callback o desactivarlo (una etiqueta que agrupa las series)
split:false, // si es true se necesita modificar formatter callback o desactivarlo (separa en etiquetas separadas por serie)
stickOnContact:false, // Si es true el tt se mostrara cuando se pase el cursor por el punto o marcador de la serie
nullFormatter: function(p){
return "Es un valor null"
},
formatter:undefined
},
/* responsive:{
rules:[
{
chartOptions:{},
conditions:{
callback:undefined,
maxHeight:undefined,
maxWidth:undefined,
minHeight:0,
minWidth:0
}
}
]
}, */
xAxis: {
alignTicks:true, // alineacion de ticks cuando hay multiples axes
accessibility:{},
categories: ['<strong>Aguascalientes</trong>','Durango','Nuevo Leon','Chiapas','San Luis','Zacatecas','Baja California Sur','Oaxaca','Quintana Roo'],
crosshair:{
color:"#cccccc",
dashStyle:"dot",
snap:true,
width:1
},
events:{},
gridLineColor:"#f1f1f1",
gridLineDashStyle:"Solid",
gridLineInterpolation:undefined,
gridLineWidth:1,
lineColor:"#d7d7d7",
lineWidth:1,
labels:{
align:undefined,
allowOverlap:true,
autoRotation:[-80],
enabled:true,
rotation:undefined, // si rotation tiene valores, autorotation se ignora
reserveSpace:true,
step:0, // cada cuantos mostrara la categoria
style:{
color:"#525252",
fontSize:"0.8em"
},
useHTML:true,
// formatter:function(){}
},
// Plot & bands: coloreado de zonas especificas segun el rango especificado
/* plotBands:[{
color:"#FCFFC5",
from:2,
to:4,
}], */
// Plot & bands: Linea para indicar una zona dentro del plot segun el value especificado
/* plotLines:[{
color:"#FF0000",
dashStyle:"Solid",
zIndex:5,
width:2,
value:5,
label:{
text:"Etiqueta plotline",
align:"left",
textAlign:"left",
rotation:0,
style:{
color:"#FF0000",
fontWeigth:"bold"
}
}
}], */
reversed:false, // invierte el orden de las categorias
tickWidth:1,
tickLength:8,
tickColor:"#d7d7d7",
tickPosition:"outside",
tickmarkPlacement:"on", // on = centrado en la etiqueta | between = entre las etiquetas
title:{
align:"high", // low = left | middle = center | high = right
enabled:true,
margin:20,
style:{
color:"#666666",
fontSize:"0.8em"
},
useHTML:true,
text:"",
},
visible:true, // oculta / muestra el eje X
},
yAxis:{
accessibility:{},
crosshair:{
color:"#cccccc",
dashStyle:"dot",
snap:true,
width:1
},
gridLineColor:"#f1f1f1",
gridLineDashStyle:"Solid",
gridLineInterpolation:undefined,
gridLineWidth:1,
lineColor:"#d7d7d7",
lineWidth:1,
labels:{
align:undefined,
allowOverlap:true,
autoRotation:[-80],
enabled:true,
rotation:undefined, // si rotation tiene valores, autorotation se ignora
reserveSpace:true,
step:0, // cada cuantos mostrara la categoria
style:{
color:"#525252",
fontSize:"0.8em"
},
useHTML:true,
// formatter:function(){}
},
max:undefined, // Maximo valor especificado del eje Y, undefined = lo toma de los datos de entrada
minTickInterval:1, //Intervalo de saltos en los valores del eje Y
opposite:false,
// Plot & bands: coloreado de zonas especificas segun el rango especificado
/* plotBands:[{
color:"#ffe8a3",
from:0,
to:2,
}], */
// Plot & bands: Linea para indicar una zona dentro del plot segun el value especificado
/* plotLines:[{
color:"#d8a408",
dashStyle:"Solid",
zIndex:5,
width:2,
value:4,
label:{
text:"Etiqueta plotline",
align:"left",
textAlign:"left",
rotation:0,
style:{
color:"#d8a408",
fontWeigth:"bold"
}
}
}], */
reversed:false,
stackLabels:{}, // para graficas stack
startOnTick:true, // comienda desde el punto del eje X ( punto 0)
tickWidth:1,
tickLength:8,
tickColor:"#d7d7d7",
tickPosition:"outside",
tickmarkPlacement:"on", // on = centrado en la etiqueta | between = entre las etiquetas
title:{
align:"high", // low = left | middle = center | high = right
enabled:true,
margin:20,
style:{
color:"#666666",
fontSize:"0.8em"
},
useHTML:true,
text:"",
},
visible:true, // mostrar / ocultar el eje Y
},
plotOptions:{
},
series: [{
name:"2023",
data:[
{indicador:"Población total", area:"Aguascalientes", periodo:2022,value:10, y:10},
{indicador:"Población total", area:"Durango", periodo:2022,value:20, y:20},
{indicador:"Población total", area:"Nuevo Leon", periodo:2022,value:30, y:30},
{indicador:"Población total", area:"Chiapas", periodo:2022,value:40, y:40},
{indicador:"Población total", area:"San Luis", periodo:2022,value:null, y:null},
{indicador:"Población total", area:"Zacatecas", periodo:2022,value:20, y:20},
{indicador:"Población total", area:"Baja California", periodo:2022,value:70, y:70},
{indicador:"Población total", area:"Oaxaca", periodo:2022,value:50, y:50},
{indicador:"Población total", area:"Quintana Roo", periodo:2022,value:90, y:90},
]
}]
}
let ParametrosUsuario = {
id:"",
// _chartRef:null, // guarda la referencia del obj DOM donde se genera el svg de highcharts
// _chartOptions:{}, // objeto de configuracion para generar la gráfica de Highcharts
exe:true,
tipo:"linea",
titulo:"",
alto:400,
mostrar:true,
herramientas:{
id:"",
mostrar:true,
exportarCsv:true,
exportarXls:true
},
color:"Tema.Azul",
margen_derecho:10,
margen_izquierdo:10,
margen_superior:10,
margen_inferior:10,
// alto:400,
grid:{
x:true,
y:true
},
ejeY:{
mostrar:true,
texto:"",
posicion:"l",
},
ejeX:{
mostrar:true,
texto:"",
posicion:"b"
},
leyenda: {
mostrar:true,
columnas:true,
ancho_item:100,
posicion:"", // valores posibles: inferior, superior, izquierda, derecha [default = inferior]
},
series:{
mostrar:true,
// curva:true,
// puntos:true,
// linea_guia_x:true,
// linea_guia_y:true,
// punto_guia:true,
// etiquetas:{
//}
},
tooltip:{
mostrar:true,
// seguir_puntero:false, // seguimiento del cursor
// formato:function(){}
}
}
const generaJsonGrafica = (parametros, dataset) => {
let {offsetWidth} = parametros.refContainer.current; // referencia del contenedor <section> del gráfico
/* console.group("## Parametros del usuario")
console.log(parametros)
console.groupEnd() */
// Objeto que concentra todas las opciones con valores finales
let CHART = {};
// Segmentos del objeto de opciones: Permite modificarlos y asignar los valores introducidos por el usuario
let {
chart,
colors,
data,
exporting,
legend,
plotOptions,
tooltip,
xAxis,
yAxis,
series,
responsive
} = OpcionesGrafica;
// Se valida que el tipo de grafica solicitado por el usuario exista en el proyecto.
// de lo contrario regresa el objeto vacio y mensaje de error
const tipoGrafica = Helper.buscaTipoGrafica(parametros.tipo)
// console.log("tipoGrafica: ",tipoGrafica)
if(tipoGrafica !== null && tipoGrafica !== undefined){
/** ########## CONFIGURACION DEL BJETO CHART */
chart.type = tipoGrafica.nombre;
chart.height = parametros.alto;
if(parametros.animaciones){
chart.animation = parametros.animaciones
}
CHART.chart = chart;
/** ########## CONFIGURACION LEGEND */
const parametrosLeyenda = parametros.leyenda;
if(parametrosLeyenda !== undefined){
/* console.group("## parametros leyenda:")
console.log(parametrosLeyenda)
console.groupEnd() */
// Mostrar u ocultar la layenda
if(parametrosLeyenda.mostrar !== undefined && typeof parametrosLeyenda.mostrar === "boolean"){
legend.enabled = parametrosLeyenda.mostrar;
}
// Mostrar en columnas on inline
if(parametrosLeyenda.columnas !== undefined && typeof parametrosLeyenda.columnas === "boolean"){
legend.alignColumns = parametrosLeyenda.columnas;
}
// Define el ancho de cada item siempre y cuando la propiedad sea columnas = true y ancho_item > 0
if(legend.alignColumns === true && parametrosLeyenda.ancho_item !== undefined && typeof parametrosLeyenda.ancho_item === "number"){
legend.itemWidth = parametrosLeyenda.ancho_item;
}
// Posicion de la leyenda
if(parametrosLeyenda.posicion !== undefined && typeof parametrosLeyenda.posicion === "string"){
const getPosicion = (param) => {
var posiciones = {
'superior': () => {return {verticalAlign:"top", layout:"horizontal"};},
'inferior': () => {return {verticalAlign:'bottom', layout:'horizontal'};},
'izquierda': () => {return {verticalAlign:'top', layout:'vertical'};},
'derecha': () => {return {align:'right', verticalAlign:'top', layout:'vertical'};},
'default': () => { return {verticalAlign:'bottom', layout:'horizontal'}; }
};
return (posiciones[param] || posiciones['default'])();
}
let l;
const pos = getPosicion(parametrosLeyenda.posicion);
legend.align = pos.align || legend.align;
legend.verticalAlign = pos.verticalAlign;
legend.layout = pos.layout;
}
// Formato de los items de la leyenda (por defecto)
legend.labelFormat = undefined;
legend.labelFormatter = function(e){
const {name} = this;
return `<div title="${name}">${name}</div>`;
}
CHART.legend = legend;
}
/** ########## CONFIGURACION TOOLTIP */
if(parametros.tooltip !== undefined){
const parametrosTooltip = parametros.tooltip;
console.group("## parametros tooltip:")
console.log(parametrosTooltip)
console.groupEnd()
// Mostrar u oculta el tooltip
if(parametrosTooltip.mostrar !== undefined && typeof parametrosTooltip.mostrar === "boolean"){
tooltip.enabled = parametrosTooltip.mostrar;
}
// Modo de visualizacion del tooltip
let modoTip = {};
if(parametrosTooltip.modo === undefined){
modoTip = Helper.buscaTooltip("");
} else {
modoTip = Helper.buscaTooltip(parametrosTooltip.modo);
}
// Modo tooltip: por defecto normal
if(modoTip.alias === "normal"){
tooltip.shared = false;
tooltip.split = false;
tooltip.formatter = function(p){
const point = this.point;
// const options = point.options;
const series = this.series;
// const cat = this.key;
const color = this.color;
const template = `
<div class="sdg-tooltip" style="width:${Math.ceil(offsetWidth/3)+'px'}">
<div><strong>${series.name}</strong></div>
<div>
<i class="sdg-tooltip-color" style="background-color:${color};"></i>
<span><strong>${point.category}</strong></span>
<span>${point.y}</span>
</div>
</div>
`;
return template;
}
// Modo tooltip: compartido / shared
} else if(modoTip.alias === "compartido"){
tooltip.shared = true;
// Modo tooltip: dividido / split
} else if(modoTip.alias === "dividido"){
tooltip.split = true;
tooltip.formatter = function(){
const points = this.points;
return [`<strong class="sdg-tooltip">${this.x}</strong>`].concat(
points?
points.map((p) => {
return `
<div class="sdg-tooltip" style="width:${Math.ceil(offsetWidth/3)+'px'}">
<i class="sdg-tooltip-color" style="background-color:${p.color};"></i>
<span><strong>${p.series.name}</strong></span>
<span>${p.y}</span>
</div>
`;
})
: []
)
/* return [""].concat(
points?
points.map((p) => {
return `
<div><strong>${p.series.name}</strong></div>
<div>
<i style="background-color:${p.color};width:10px;height:10px;display:inline-block;padding:0 4px 0 0"></i>
<span><strong>${p.point.category}</strong></span>
<span>${p.y}</span>
</div>
`;
})
: []
) */
};
}
CHART.tooltip = tooltip;
}
/** ########## CONFIGURACION SERIES */
// console.log(dataset);
xAxis.categories = dataset.categorias.map((c) => c.nombre);
let aSeries = [];
aSeries = dataset.datos.map((s) => {
let oData = {};
let serie_data = s.data.map((d) => {
let nVal = Helper.stringANumero(d.valor)
d.valor = nVal
d.y = nVal;
return d;
})
oData.data = serie_data
oData.name = s.grupo;
return oData;
})
CHART = OpcionesGrafica;
CHART.xAxis.categories = xAxis.categories;
CHART.series = aSeries;
// console.log(CHART)
}
// if(GRAFICAS.tipos[paramUsuario.tipo])
// Primero configurar todos los parametros generales
// chart, colors, legend, tooltip, exporting, plotOptions
// Segundo configurar los ejex
// xAxis, yAxis
// Tercero configurar los ajustes de responsivo
// responsive
// Cuarto configura los datos
// series
// Quinto asignar todas las propiedades en un objeto y retornarlo
// CHART
console.log(CHART)
return CHART;
}
export {
OpcionesHighcharts,
OpcionesGrafica,
ParametrosUsuario,
generaJsonGrafica
}