Définir des données supplémentaires sur les séries highcharts

116

existe-t-il un moyen de transmettre des données supplémentaires à l'objet série qui sera utilisé pour s'afficher dans l'info-bulle du graphique?

par exemple

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

ici, nous ne pouvons utiliser que series.name, this.x & this.y pour la série. disons que j'ai besoin de passer une autre valeur dynamique seule avec l'ensemble de données et que je peux accéder via un objet série. Est-ce possible?

Merci d'avance à tous.

Sam
la source
1
Javascript n'est pas pointilleux sur les objets que vous transmettez et les ignore généralement s'ils ne sont pas utilisés. Ils peuvent être supprimés par le code interne de la bibliothèque, mais ils ne le sont pas nécessairement, et cela vaut généralement le coup. Avez-vous essayé d'ajouter des données supplémentaires à votre seriesobjet et de les afficher dans ce gestionnaire?
Merlyn Morgan-Graham
@ MerlynMorgan-Graham - Je suis nouveau sur «HighCharts». pouvez-vous s'il vous plaît poster un lien que je peux trouver une sorte d'exemple? Merci beaucoup pour votre aide.
Sam
@Sam, ma réponse a un exemple fonctionnel complet que vous pouvez consulter. Faites-moi savoir si cela ne répond pas tout à fait à vos exigences.
Nick
Comment puis-je ajouter des données supplémentaires comme myData en cas de graphique à bulles car le tableau de données est comme des données: [[12, 43, 13], [74, 23, 44]] Par exemple, quelles sont les clés pour les valeurs de données comme ci-dessus a 'y', y a-t-il 'x', 'y' et 'z'? ou 'size'
vishal

Réponses:

220

Oui, si vous configurez l'objet série comme suit, où chaque point de données est un hachage, vous pouvez transmettre des valeurs supplémentaires:

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

Dans votre tooltip vous pouvez y accéder via l'attribut "point" de l'objet passé:

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

Exemple complet ici: https://jsfiddle.net/burwelldesigns/jeoL5y7s/

pseudo
la source
1
Je sais que c'est une vieille réponse, mais le violon lié ne montre plus l'exemple pertinent.
undefinedvariable
@undefinedvariable - hmm, on dirait que d'autres l'ont modifié et défini une nouvelle version comme version "de base" dans jsfiddle. C'est malheureux. Mise à jour du violon et lien maintenant vers une version spécifique dans la réponse.
Nick
@Nick, génial, merci. Excellente réponse, au fait. Je manquais de valeurs par défaut inutilisées pour y insérer des informations.
undefinedvariable
Comment accéder à myData si c'est un tableau?
vishal
2
Merci, Comment puis-je ajouter des données supplémentaires comme myData dans le cas d'un graphique à bulles car le tableau de données est comme des données: [[12, 43, 13], [74, 23, 44]] par exemple, quelles sont les clés des valeurs de données comme ce qui précède a «y», y a-t-il «x», «y» et «z»? ou «taille»?
vishal
17

De plus, avec cette solution, vous pouvez même mettre plusieurs données autant que vous le souhaitez :

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'
    }]
}]

Merci Nick.

Antoine Subit
la source
4
Les 'données supplémentaires' ne sont pas possibles lorsque le format non-objet [x, y] est utilisé? Nous avons une datetimevaleur x mais souhaitons ajouter des données supplémentaires à l'info-bulle.
Rvanlaak le
Exemple de données chronologiques: var serie = {x: Date.parse (d.Value), y: d.Item, method: d.method};
Arjun Upadhyay
15

Pour les données de séries chronologiques, en particulier avec suffisamment de points de données pour activer le seuil turbo , les solutions proposées ci-dessus ne fonctionneront pas. Dans le cas du seuil turbo, c'est parce que Highcarts s'attend à ce que les points de données soient un tableau comme:

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

Afin de ne pas perdre les avantages du seuil turbo (ce qui est important lorsqu'il s'agit de nombreux points de données), je stocke les données en dehors du graphique et je recherche le point de données dans la formatterfonction d' info-bulle . Voici un exemple:

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])
    }]
})

Cette approche fonctionnera pour tous les types de graphiques.

Christof
la source
Merci pour la réponse, c'est vraiment utile pour afficher des données supplémentaires dans les graphiques High Stock.
S Kumar
1
Ne devrait pas l' data: _.map(data, row => [row['timestamp'], row['value']])être data: chartData.map(row => [row.timestamp, row.value])? De plus, vous n'avez pas besoin de lodash; vous pouvez utiliser Array.find . Il n'est pas pris en charge par IE, mais vous utilisez déjà ES6 ( const) et MS a cessé de prendre en charge IE en 2016 .
Dan Dascalescu
Bonne prise avec chartData. J'ai l'habitude d'utiliser lodash mais tu as raison. J'ai mis à jour mon exemple pour qu'il soit indépendant de la bibliothèque. THX.
Christof
3

J'utilise AJAX pour obtenir mes données depuis SQL Server, puis je prépare un tableau js qui est utilisé comme données dans mon graphique. Code JavaScript une fois que l'AJAX est réussi:

...,
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);
         },

Maintenant, pour afficher des méta-données supplémentaires dans l'info-bulle:

...
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,
},

J'utilise un DataRow pour parcourir mon jeu de résultats, puis j'utilise une classe pour attribuer les valeurs avant de les renvoyer au format Json. Voici le code C # dans l'action du contrôleur appelée par 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;
}

Je me rends compte qu'il existe un moyen plus efficace et acceptable de coder en C #, mais j'ai hérité du projet.

CodageSerge
la source
1

Juste pour ajouter une sorte de dynamisme:

Fait cela pour générer des données pour un histogramme empilé avec 10 catégories.
Je voulais avoir pour chaque série de données de catégorie 4 et je voulais afficher des informations supplémentaires (image, question, distracteur et réponse attendue) pour chacune des séries de données:

<?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"
);
?>

Dans la section 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.

J'espère que ça aide quelqu'un.

DK250
la source