Establecer datos adicionales para series highcharts

116

¿Hay alguna forma de pasar algunos datos adicionales al objeto de la serie que se utilizará para mostrar en el gráfico 'información sobre herramientas'?

por ejemplo

 tooltip: {
     formatter: function() {
               return '<b>'+ this.series.name +'</b><br/>'+
           Highcharts.dateFormat('%b %e', this.x) +': '+ this.y;
     }

aquí solo podemos usar series.name, this.x & this.y para la serie. digamos que necesito pasar otro valor dinámico solo con el conjunto de datos y puedo acceder a través del objeto de la serie. ¿es posible?

Gracias a todos de antemano.

Sam
fuente
1
Javascript no es exigente con los objetos que transmite y, por lo general, los ignora si no se utilizan. Pueden ser eliminados por el código interno de la biblioteca, pero no necesariamente, y por lo general vale la pena intentarlo. ¿Ha intentado agregar datos adicionales a su seriesobjeto y mostrarlos en este controlador?
Merlyn Morgan-Graham
@ MerlynMorgan-Graham - Soy nuevo en 'HighCharts'. ¿Pueden publicar algún enlace que pueda encontrar algún ejemplo? Muchas gracias por ayudarme.
Sam
@Sam, mi respuesta tiene un ejemplo de trabajo completo que puede ver. Avíseme si no cumple con sus requisitos.
Nick
¿Cómo puedo agregar datos adicionales como myData en el caso de un gráfico de burbujas, ya que la matriz de datos es como datos: [[12, 43, 13], [74, 23, 44]] por ejemplo, cuáles son las claves para los valores de datos como el anterior? tiene 'y', ¿hay 'x', 'y' y 'z'? o 'tamaño'
vishal

Respuestas:

220

Sí, si configura el objeto de la serie como se muestra a continuación, donde cada punto de datos es un hash, puede pasar valores adicionales:

new Highcharts.Chart( {
    ...,
    series: [ {
        name: 'Foo',
        data: [
            {
                y : 3,
                myData : 'firstPoint'
            },
            {
                y : 7,
                myData : 'secondPoint'
            },
            {
                y : 1,
                myData : 'thirdPoint'
            }
        ]
    } ]
} );

En su información sobre herramientas puede acceder a él a través del atributo "punto" del objeto pasado:

tooltip: {
    formatter: function() {
        return 'Extra data: <b>' + this.point.myData + '</b>';
    }
}

Ejemplo completo aquí: https://jsfiddle.net/burwelldesigns/jeoL5y7s/

Mella
fuente
1
Sé que esta es una respuesta antigua, pero violín vinculado ya no muestra el ejemplo relevante.
indefinido
@undefinedvariable - hmm, parece que otros han editado esto y han establecido una nueva versión como la versión "base" en jsfiddle. Eso es lamentable. Se actualizó el violín y ahora se vincula a una versión específica en la respuesta.
Nick
@Nick, genial, gracias. Gran respuesta, por cierto. Me estaba quedando sin valores predeterminados no utilizados para infiltrar información.
variable indefinida
¿Cómo acceder a myData si es una matriz?
vishal
2
Gracias, ¿cómo puedo agregar datos adicionales como myData en el caso de un gráfico de burbujas, ya que la matriz de datos es como datos: [[12, 43, 13], [74, 23, 44]] por ejemplo, cuáles son las claves para los valores de datos? lo anterior tiene 'y', ¿hay 'x', 'y' y 'z'? o 'talla'?
vishal
17

Además, con esta solución, incluso puede colocar varios datos tanto como desee :

tooltip: {
    formatter: function () {
        return 'Extra data: <b>' + this.point.myData + '</b><br> Another Data: <b>' + this.point.myOtherData + '</b>';
    }
},

series: [{
    name: 'Foo',
    data: [{
        y: 3,
        myData: 'firstPoint',
        myOtherData: 'Other first data'
    }, {
        y: 7,
        myData: 'secondPoint',
        myOtherData: 'Other second data'
    }, {
        y: 1,
        myData: 'thirdPoint',
        myOtherData: 'Other third data'
    }]
}]

Gracias Nick.

Antoine Subit
fuente
4
¿Los 'datos adicionales' no son posibles cuando se usa el formato sin objeto [x, y]? Tenemos datetimeun valor x pero queremos agregar datos adicionales a la información sobre herramientas.
Rvanlaak
Ejemplo de datos de series temporales: var serie = {x: Date.parse (d.Value), y: d.Item, method: d.method};
Arjun Upadhyay
15

Para datos de series de tiempo, especialmente con suficientes puntos de datos para activar el umbral turbo , las soluciones propuestas anteriormente no funcionarán. En el caso del umbral turbo, esto se debe a que Highcarts espera que los puntos de datos sean una matriz como:

series: [{
    name: 'Numbers over the course of time',
    data: [
      [1515059819853, 1],
      [1515059838069, 2],
      [1515059838080, 3],
      // you get the idea
    ]
  }]

Para no perder los beneficios del umbral turbo (que es importante cuando se trata de muchos puntos de datos), almaceno los datos fuera del gráfico y busco el punto de datos en la formatterfunción de información sobre herramientas . He aquí un ejemplo:

const chartData = [
  { timestamp: 1515059819853, value: 1, somethingElse: 'foo'},
  { timestamp: 1515059838069, value: 2, somethingElse: 'bar'},
  { timestamp: 1515059838080, value: 3, somethingElse: 'baz'},
  // you get the idea
]

const Chart = Highcharts.stockChart(myChart, {
  // ...options
  tooltip: {
    formatter () {
      // this.point.x is the timestamp in my original chartData array
      const pointData = chartData.find(row => row.timestamp === this.point.x)
      console.log(pointData.somethingElse)
    }
  },
  series: [{
      name: 'Numbers over the course of time',
      // restructure the data as an array as Highcharts expects it
      // array index 0 is the x value, index 1 is the y value in the chart
      data: chartData.map(row => [row.timestamp, row.value])
    }]
})

Este enfoque funcionará para todos los tipos de gráficos.

Christof
fuente
Gracias, por la respuesta, es realmente útil para mostrar datos adicionales en gráficos de High Stock.
S Kumar
1
¿No debería data: _.map(data, row => [row['timestamp'], row['value']])ser data: chartData.map(row => [row.timestamp, row.value])? Además, no necesita lodash; puede utilizar Array.find . No es compatible con IE, pero ya está usando ES6 ( const) y MS dejó de admitir IE en 2016 .
Dan Dascalescu
Buen partido con chartData. Estoy acostumbrado a usar lodash pero tienes razón. Actualicé mi ejemplo para que sea independiente de la biblioteca. Gracias.
Christof
3

Estoy usando AJAX para obtener mis datos de SQL Server, luego preparo una matriz js que se usa como datos en mi gráfico. Código JavaScript una vez que AJAX es exitoso:

...,
success: function (data) {
            var fseries = [];
            var series = [];
            for (var arr in data) {
                for (var i in data[arr]['data'] ){
                    var d = data[arr]['data'][i];
                    //if (i < 5) alert("d.method = " + d.method);
                    var serie = {x:Date.parse(d.Value), y:d.Item, method:d.method };
                    series.push(serie);
                }
                fseries.push({name: data[arr]['name'], data: series, location: data[arr]['location']});
                series = [];
            };
            DrawChart(fseries);
         },

Ahora para mostrar metadatos adicionales en la información sobre herramientas:

...
tooltip: {
    xDateFormat: '%m/%d/%y',
    headerFormat: '<b>{series.name}</b><br>',
    pointFormat: 'Method: {point.method}<br>Date: {point.x:%m/%d/%y } <br>Reading: {point.y:,.2f}',
    shared: false,
},

Uso un DataRow para iterar a través de mi conjunto de resultados, luego uso una clase para asignar los valores antes de devolverlos en formato Json. Aquí está el código C # en la acción del controlador llamada por Ajax.

public JsonResult ChartData(string dataSource, string locationType, string[] locations, string[] methods, string fromDate, string toDate, string[] lstParams)
{
    List<Dictionary<string, object>> dataResult = new List<Dictionary<string, object>>();
    Dictionary<string, object> aSeries = new Dictionary<string, object>();
    string currParam = string.Empty;        

    lstParams = (lstParams == null) ? new string[1] : lstParams;
    foreach (DataRow dr in GetChartData(dataSource, locationType, locations, methods, fromDate, toDate, lstParams).Rows)
    {
        if (currParam != dr[1].ToString())
        {
            if (!String.IsNullOrEmpty(currParam))       //A new Standard Parameter is read and add to dataResult. Skips first record.
            {
                Dictionary<string, object> bSeries = new Dictionary<string, object>(aSeries); //Required else when clearing out aSeries, dataResult values are also cleared
                dataResult.Add(bSeries);
                aSeries.Clear();
            }
            currParam = dr[1].ToString(); 
            aSeries["name"] = cParam;
            aSeries["data"] = new List<ChartDataModel>();
            aSeries["location"] = dr[0].ToString();
        }

        ChartDataModel lst = new ChartDataModel();
        lst.Value = Convert.ToDateTime(dr[3]).ToShortDateString();
        lst.Item = Convert.ToDouble(dr[2]);
        lst.method = dr[4].ToString();
        ((List<ChartDataModel>)aSeries["data"]).Add(lst);
    }
    dataResult.Add(aSeries);
    var result = Json(dataResult.ToList(), JsonRequestBehavior.AllowGet);  //used to debug final dataResult before returning to AJAX call.
    return result;
}

Me doy cuenta de que hay una forma más eficiente y aceptable de codificar en C #, pero heredé el proyecto.

CodingSerge
fuente
1

Solo para agregar algún tipo de dinamismo:

Hizo esto para generar datos para un gráfico de columnas apiladas con 10 categorías.
Quería tener para cada serie de datos de categoría 4 y quería mostrar información adicional (imagen, pregunta, distractor y respuesta esperada) para cada una de las series de datos:

<?php 

while($n<=10)
{
    $data1[]=array(
        "y"=>$nber1,
        "img"=>$image1,
        "ques"=>$ques,
        "distractor"=>$distractor1,
        "answer"=>$ans
    );
    $data2[]=array(
        "y"=>$nber2,
        "img"=>$image2,
        "ques"=>$ques,
        "distractor"=>$distractor2,
        "answer"=>$ans
    );
    $data3[]=array(
        "y"=>$nber3,
        "img"=>$image3,
        "ques"=>$ques,
        "distractor"=>$distractor3,
        "answer"=>$ans
    );
    $data4[]=array(
        "y"=>$nber4,
        "img"=>$image4,
        "ques"=>$ques,
        "distractor"=>$distractor4,
        "answer"=>$ans
    );
}

// Then convert the data into data series:

$mydata[]=array(
    "name"=>"Distractor #1",
    "data"=>$data1,
    "stack"=>"Distractor #1"
);
$mydata[]=array(
    "name"=>"Distractor #2",
    "data"=>$data2,
    "stack"=>"Distractor #2"
);
$mydata[]=array(
    "name"=>"Distractor #3",
    "data"=>$data3,
    "stack"=>"Distractor #3"
);
$mydata[]=array(
    "name"=>"Distractor #4",
    "data"=>$data4,
    "stack"=>"Distractor #4"
);
?>

En la sección highcharts:

var mydata=<? echo json_encode($mydata)?>;

// Tooltip section
tooltip: {
    useHTML: true,
        formatter: function() {

            return 'Question ID: <b>'+ this.x +'</b><br/>'+
                   'Question: <b>'+ this.point.ques +'</b><br/>'+
                   this.series.name+'<br> Total attempts: '+ this.y +'<br/>'+
                   "<img src=\"images/"+ this.point.img +"\" width=\"100px\" height=\"50px\"/><br>"+
                   'Distractor: <b>'+ this.point.distractor +'</b><br/>'+
                   'Expected answer: <b>'+ this.point.answer +'</b><br/>';
               }
           },

// Series section of the highcharts 
series: mydata
// For the category section, just prepare an array of elements and assign to the category variable as the way I did it on series.

Espero que ayude a alguien.

DK250
fuente