0

1 つの kendoChart を使用して、最大 10 行のデータを表示しています。

各行は、コンテキストと最小/最大範囲が大きく異なる可能性があるプロセス データを表しますが、すべての行は時間的に関連付けられており、categoryAxis です。表示されると、各 valueAxis は対応する線のスケールを正しく示します。

ただし、10 行の場合、10 個の valueAxes が画面を占有しすぎて、要件を満たすことができません。

非表示の軸が占めるスペースを埋めるためにチャートが拡張されることを期待して、1 つを除くすべての軸を非表示にしようとしましたが、そうはなりません。空白に囲まれた軸が 1 つだけ表示され、グラフのプロット エリアは同じサイズのままです。

すべてのシリーズで同じ valueAxis を使用するように設定してから、凡例項目をクリックして選択したアクティブなチャネルごとに valueAxis の最小値/最大値を変更してみました。これにより、必要に応じてプロット エリアが拡大されますが、縮尺が 1 つのラインに固有であるため、すべてのラインを表示する機能が削除されます。

kendoChart が単一の valueAxis から独立して複数のプロットを表示することは可能ですか?どちらの縮尺でも構いません。)

4

1 に答える 1

0

この問題に対して私が使用した解決策は、予想以上に多くのコードを使用することでした。おそらく、Telerik の他の製品には、このための API があります。

基本的に、各シリーズの実際のデータを格納する kendoChart の外側に構造体を維持します。この実際のデータは、現在表示されている valueAxis の予想されるスケールにマップされます。マッピング関数は、あるスケールから別のスケールへの標準的な変換です。

valueAxis は、クリックされた凡例項目に応じて「スワップ」され、そのイベントは、すべての系列データが「アクティブな」軸にマップされるチャートの再描画をトリガーします。

いくつかのコード スニペット。シリーズはチャネルとも呼ばれます。

// 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();
}
于 2016-06-03T13:36:46.760 に答える