Stellen Sie zusätzliche Daten auf Highcharts ein

116

Gibt es eine Möglichkeit, zusätzliche Daten an das Serienobjekt zu übergeben, die im Diagramm-Tooltip angezeigt werden?

beispielsweise

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

hier können wir nur series.name, this.x & this.y für die Serie verwenden. Nehmen wir an, ich muss einen anderen dynamischen Wert allein mit dem Datensatz übergeben und kann über ein Serienobjekt darauf zugreifen. Ist das möglich?

Vielen Dank im Voraus.

Sam
quelle
1
Javascript ist nicht wählerisch, welche Objekte Sie weitergeben, und ignoriert sie normalerweise, wenn sie nicht verwendet werden. Sie werden möglicherweise durch den internen Code der Bibliothek entfernt, sind es aber nicht unbedingt, und es ist normalerweise einen Versuch wert. Haben Sie versucht, zusätzliche Daten an Ihr seriesObjekt anzuhängen und in diesem Handler anzuzeigen?
Merlyn Morgan-Graham
@ MerlynMorgan-Graham - Ich bin neu bei 'HighCharts'. Kannst du bitte einen Link posten, den ich als Beispiel finden kann? Vielen Dank, dass Sie mir geholfen haben.
Sam
@ Sam, meine Antwort enthält ein voll funktionsfähiges Beispiel, das Sie sich ansehen können. Lassen Sie mich wissen, wenn es Ihren Anforderungen nicht ganz entspricht.
Nick
Wie kann ich zusätzliche Daten wie myData im Fall eines Blasendiagramms hinzufügen, da das Datenarray wie Daten ist: [[12, 43, 13], [74, 23, 44]] z. B. was sind die Schlüssel für die Datenwerte wie oben hat 'y', gibt es 'x', 'y' und 'z'? oder 'Größe'
Vishal

Antworten:

220

Ja, wenn Sie das Serienobjekt wie folgt einrichten, wobei jeder Datenpunkt ein Hash ist, können Sie zusätzliche Werte übergeben:

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

In Ihrem Tooltip können Sie über das Attribut "point" des übergebenen Objekts darauf zugreifen:

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

Vollständiges Beispiel hier: https://jsfiddle.net/burwelldesigns/jeoL5y7s/

Nick
quelle
1
Ich weiß, dass dies eine alte Antwort ist, aber Fiddle Linked zeigt das relevante Beispiel nicht mehr.
undefinierte
@undefinedvariable - hmm, es sieht so aus, als hätten andere dies bearbeitet und eine neue Version als "Basis" -Version in jsfiddle festgelegt. Das ist bedauerlich. Die Geige wurde aktualisiert und jetzt in der Antwort auf eine bestimmte Version verlinkt.
Nick
@ Nick, super, danke. Tolle Antwort übrigens. Mir gingen die nicht verwendeten Standardwerte aus, um Informationen einzuspeisen.
undefinierte
Wie greife ich auf myData zu, wenn es sich um ein Array handelt?
Vishal
2
Danke, wie kann ich im Falle eines Blasendiagramms zusätzliche Daten wie myData hinzufügen, da das Datenarray wie Daten ist: [[12, 43, 13], [74, 23, 44]] zB wie lauten die Schlüssel für die Datenwerte? das obige hat 'y', gibt es 'x', 'y' und 'z'? oder 'Größe'?
Vishal
17

Darüber hinaus können Sie mit dieser Lösung sogar so viele Daten speichern, wie Sie möchten :

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

Danke Nick.

Antoine Subit
quelle
4
Die 'zusätzlichen Daten' sind nicht möglich, wenn das Nicht-Objekt-Format [x, y] verwendet wird. Wir haben datetimeals x-Wert, möchten aber dem Tooltip zusätzliche Daten hinzufügen.
Rvanlaak
Beispiel für Zeitreihendaten: var serie = {x: Date.parse (d.Value), y: d.Item, method: d.method};
Arjun Upadhyay
15

Für Zeitreihendaten, insbesondere mit genügend Datenpunkten, um die Turboschwelle zu aktivieren , funktionieren die oben vorgeschlagenen Lösungen nicht. Im Fall der Turboschwelle liegt dies daran, dass Highcarts erwartet, dass die Datenpunkte ein Array wie folgt sind:

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

Um die Vorteile der Turboschwelle (die beim Umgang mit vielen Datenpunkten wichtig ist) nicht zu verlieren, speichere ich die Daten außerhalb des Diagramms und suche den Datenpunkt in der Tooltip- formatterFunktion nach. Hier ist ein Beispiel:

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

Dieser Ansatz funktioniert für alle Diagrammtypen.

Christof
quelle
Vielen Dank, für die Antwort ist es sehr hilfreich, zusätzliche Daten in High Stock-Diagrammen anzuzeigen.
S Kumar
1
Sollte nicht data: _.map(data, row => [row['timestamp'], row['value']])sein data: chartData.map(row => [row.timestamp, row.value])? Außerdem brauchst du kein Lodash. Sie können Array.find verwenden . Es wird vom IE nicht unterstützt, aber Sie verwenden ES6 bereits ( const) und MS hat die Unterstützung des IE im Jahr 2016 eingestellt .
Dan Dascalescu
Guter Fang mit chartData. Ich bin es gewohnt, lodash zu benutzen, aber du hast recht. Ich habe mein Beispiel aktualisiert, damit es bibliotheksunabhängig ist. Vielen Dank.
Christof
3

Ich verwende AJAX, um meine Daten von SQL Server abzurufen, und bereite dann ein js-Array vor, das als Daten in meinem Diagramm verwendet wird. JavaScript-Code nach erfolgreichem AJAX:

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

Um nun zusätzliche Metadaten im Tooltip anzuzeigen:

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

Ich verwende eine DataRow, um meine Ergebnismenge zu durchlaufen, und verwende dann eine Klasse, um die Werte zuzuweisen, bevor sie im Json-Format zurückgegeben werden. Hier ist der C # -Code in der von Ajax aufgerufenen Controller-Aktion.

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;
}

Mir ist klar, dass es eine effizientere und akzeptablere Möglichkeit gibt, in C # zu codieren, aber ich habe das Projekt geerbt.

CodingSerge
quelle
1

Nur um eine Art Dynamik hinzuzufügen:

Dies geschah zum Generieren von Daten für ein gestapeltes Säulendiagramm mit 10 Kategorien.
Ich wollte für jede Datenreihe der Kategorie 4 zusätzliche Informationen (Bild, Frage, Ablenker und erwartete Antwort) für jede der Datenreihen anzeigen:

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

In der Highcharts-Sektion:

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.

Hoffe es hilft jemandem.

DK250
quelle