2016-05-03 12 views
-1

Ich verwende ein einzelnes KendoChart, um bis zu 10 Datenzeilen anzuzeigen.kendoChart: Gibt es eine Möglichkeit, mehrere Reihen unterschiedlicher Wertskalen mit einem einzigen WertAchse anzuzeigen?

Jede Zeile steht für Prozessdaten, die sehr unterschiedliche Kontext- und Min/Max-Bereiche haben können, aber alle Zeilen sind zeitlich miteinander verknüpft, die KategorieAchse. Bei der Anzeige zeigt jeder WertAchse korrekt die Skalierung für die entsprechende Zeile an.

Mit 10 Zeilen nehmen die 10 valueAxes jedoch viel zu viel Platz in Anspruch, um für meine Anforderungen nutzbar zu sein.

Ich habe versucht, alle Achsen außer einer mit der Erwartung versteckt, dass das Diagramm erweitert werden würde, um den Platz zu füllen, der von den versteckten Achsen eingenommen wird, aber das tut nicht passieren. Ich bekomme eine freie Achse, die von Leerzeichen umgeben ist, und die Diagrammfläche bleibt gleich groß.

Ich habe versucht, alle Serien so einzustellen, dass sie denselben WertAchse verwenden und dann den Wert Max/Min. Für den aktiven Kanal ändern, der durch Klicken auf ein Legendenelement ausgewählt wurde. Dadurch wird der Plotbereich nach Bedarf erweitert, aber die Möglichkeit, alle Zeilen zu sehen, wird entfernt, da die Skalierung für eine Zeile spezifisch ist.

Ist es für KendoChart möglich, mehrere Diagramme unabhängig von einem einzigen WertAxis anzuzeigen (z. B. würde eine Linie mit Werten zwischen 0,5 und 0,7 auf die gesamte Diagrammfläche skaliert, ebenso eine Linie mit Werten zwischen 25 und 100) Der ValueAxis zeigt möglicherweise eine Skalierung an.)

Antwort

0

Die Lösung, die ich für dieses Problem verwendet habe, ist mehr Code, als ich erwartet habe. Vielleicht haben Teleriks andere Produkte eine API dafür.

Im Wesentlichen pflege ich eine Struktur außerhalb des KendoChart, die die realen Daten für jede Serie speichert, und diese realen Daten werden auf den erwarteten Maßstab der aktuell sichtbaren WertAchse abgebildet. Die Zuordnungsfunktion ist die Standardtransformation von einer Skala in eine andere.

Die valueAxis wird je nachdem, auf welches Legendenelement geklickt wird, "ausgelagert", und dieses Ereignis löst eine Neuzeichnung im Diagramm aus, bei der alle Seriendaten der "aktiven" Achse zugeordnet sind.

Einige Codeausschnitte. Eine Reihe wird auch als ein Kanal beschrieben.

// The data structure. 
this._channelDescriptors.push({ 
    fullName: ch.fullName || "", 
    axisTitle: (ch.fullName + axisEUString) || "", 
    axisFont: ch.axisFont || "", 
    axisColor: ch.color || "#000000", 
    realData: [], 
    minData: Number.MAX_VALUE, 
    maxData: Number.MIN_VALUE 
}); 

// This event causes the switching of valueAxis for all members of the series. 
$("#" + chartID).kendoChart({ 
    // Other kendoChart configurations 
    // 
    legendItemClick: function (e) { 
     var idx = e.seriesIndex; 
     sncTrender.updateAxis(idx); 
     e.preventDefault(); 
    }, 
    tooltip: { 
     visible: true, 
     template: "#=series.name# : #=kendo.format('{0:N4}', dataItem.realValue)#<br />#=kendo.format('{0:MM-dd HH:mm:ss.fff}', dataItem.Time)#", 
    }, 
    // 
    // Other kendoChart configurations 
}); 

// All code snippets are members of a wrapper object. 
updateAxis: function (ch) { 
    if (this.series[ch].visible) { 
     this.setAxis(ch); 
    } 
}, 

// Every series is set to the same valueAxis via the selected series' valueAxis.name property. 
setAxis: function (ch) { 
    var i, 
     channel = this._channelDescriptors[ch]; 
    this._currentChannel = ch; 
    for (i = 0; i < this.series.length; i++) { 
     this.series[i].axis = this._channelDescriptors[ch].fullName; 
    } 
    // Set the active valueAxis properties. This is the only axis visible maintained for the chart. 
    this.valueAxis.name = channel.fullName; 
    this.valueAxis.title.text = channel.axisTitle; 
    this.valueAxis.title.font = channel.axisFont; 
    this.valueAxis.line.color = channel.axisColor; 
}, 

// The mapping occurs here, and the transform calculation is this line 
// Y: (yRange * (chDesc.realData[k].realValue - newMin)/newRange) + this.valueAxis.min, 
// 
updateChart: function (allTrends) { 
    // ... 
    timeStamps = trendDataResponse.curve.Timestamp; 
    t1 = trendArgs.t1; 
    t2 = trendArgs.t2; 
    xValues = trendDataResponse.curve.X; 
    yValues = trendDataResponse.curve.Y; 
    pointCount = xValues.length; 
    min = Number.MAX_VALUE; 
    max = Number.MIN_VALUE; 
    categoryTimes = [pointCount]; 
    newData = []; 
    for (l = 0; l < pointCount; l++) { 
     min = Math.min(min, yValues[l]); 
     max = Math.max(max, yValues[l]); 
     ts = new Date(timeStamps[l]); 
     categoryTimes[l] = ts; 
     // The Y data will be plotted on the chart, but the cursor tooltip will 
     // use the realValue data. In this way, the series can be visible regardless of 
     // the valueAxis scaling, but the actual data is also available. Refer to the 
     // tooltip template. 
     newData.push({ X: xValues[l], Y: yValues[l], realValue: yValues[l], Time: ts }); 
    } 

    // Real data for each channel is stored in channelDescriptors. 
    chDesc = this._channelDescriptors[channelID]; 
    chDesc.realData = newData; 
    chDesc.minData = min; 
    chDesc.maxData = max; 

    // The valueAxis min/max is set only for the 'active' series. 
    if (this._currentChannel === channelID) { 
     this.categoryAxis.categories = categoryTimes; 
     yRange = max - min; 
     scaleAdjustment = yRange * SNC.CONST_yAxisScaleAdjustmentFactor; 
     this.valueAxis.min = min - scaleAdjustment; 
     this.valueAxis.max = max + scaleAdjustment; 
    } 
    } 
    // Scale curves to current axis. 
    // Use real data for the current series. 
    for (j = 0; j < this.series.length; ++j) { 
    chDesc = this._channelDescriptors[j]; 
    if (j === this._currentChannel) { 
     this.series[j].data = chDesc.realData; 
     continue; 
    } 

    // Use mapped data for all other series. 
    recalcData = []; 
    newMin = chDesc.minData; 
    newMax = chDesc.maxData; 
    newRange = newMax - newMin; 
    rangeAdjustment = newRange * SNC.CONST_yAxisScaleAdjustmentFactor; 
    newMin = newMin - rangeAdjustment; 
    newMax = newMax + rangeAdjustment; 
    for (k = 0; k < chDesc.realData.length; ++k) { 
     recalcData.push({ 
      X: chDesc.realData[k].X, 
      Y: (yRange * (chDesc.realData[k].realValue - newMin)/newRange) + this.valueAxis.min, 
      realValue: chDesc.realData[k].realValue, 
      Time: chDesc.realData[k].Time, 
     }); 
    } 
    this.series[j].data = recalcData; 
    } 
    chart.redraw(); 
}