2017-03-06 62 views
0

動的に更新されたデータが表示されているページに棒グラフがあります。私が持っている問題は、表示されているデータに基づいてy軸のタイプを変更する必要があるということです。データの範囲が100未満(たとえば0〜99)で対数が大きい場合(たとえば0〜1000)は線形尺度にする必要があります。chartjsグラフのスケールタイプを動的に更新します

私は対数尺度が必要かどうかを計算できますが、尺度タイプを変更する場合は紛失します。タイプを変更することを考えて、

Object.keys(mychart.scales).forEach((function (axisName) { 
      var axis = myChart.scales[axisName]; 
      if (axis && axis.id.startsWith('y')) { 
       axis.options.type = 'logarithmic' 
      } 
     })); 
myChart.update(); 

を、私はbeforeBuildTicksコールバックを使用してみました:私は、チャートのoptionsオブジェクトを変更してupdate()を呼び出す試してみました:

myChart.options/scales.yAxes.map(function (axis) { axis.type = 'logarithmic' }); 
myChart.update(); 

とも直接規模自体を変えてみましたデータを更新して、グラフを再描画するのが遅すぎるか、間違ったタイミングになった可能性があります。

beforeBuildTicks: function (scale) { 
           if (scale.chart) { 
            console.log('logarithmic'); 
            scale.options.type = 'logarithmic'; 
           } 
          } 

これらのすべてhesはグラフオブジェクトを変更しますが、表示は影響を受けません。

グラフ全体を破棄して再作成することなく、chartjs棒グラフの尺度タイプを動的に変更する方法はありますか?

答えて

0

最終的にこれに対する解決策が見つかりましたが、それは簡単ではありません。

`scaleMerge 'ヘルパー関数の使用に関しては、@jordanwillisの正しい方向のポインタがあります。

私はすべての仕事行いplugin作成:

var changeScaleTypePlugin = { 
beforeUpdate: function (chartInstance) { 
    var self = this; 
    chartInstance.beforeInit = null; 
    if (chartInstance.options.changeScale) { 
     self.changeScales(chartInstance); 
     if (chartInstance.options.scaleTypeChanged) { 
      chartInstance.options.scaleTypeChanged = false; 
      Object.keys(chartInstance.scales).forEach(function (axisName) { 
       var scale = chartInstance.scales[axisName]; 
       Chart.layoutService.removeBox(chartInstance, scale); 
      }); 
      chartInstance.initialize(); 
     } 
    } 
}, 
changeScales: function (chartInstance) { 
    var maxValue = Math.max.apply(null, chartInstance.data.datasets.map(function (dataset) { return Math.max.apply(null, dataset.data); })); 
    var minValue = Math.min.apply(null, chartInstance.data.datasets.map(function (dataset) { return Math.min.apply(null, dataset.data); })); 
    var logMax = Math.floor(Math.log(maxValue)/Math.LN10); 
    var logMin = Math.floor(Math.log(minValue)/Math.LN10); 
    if (logMax - logMin > chartInstance.options.maxRankDifference) { 
     if (!chartInstance.options.scaleTypeChanged && chartInstance.options.scales.yAxes.filter(function (axis) { return axis.type !== 'logarithmic'; }).length) { 
      console.log('logarithmic'); 
      chartInstance.options.scaleTypeChanged = true; 
      chartInstance.options.scales.yAxes = Chart.helpers.scaleMerge(Chart.defaults.scale, { yAxes: chartInstance.options.logarithmicScaleOptions }).yAxes;     
     } 
    } else { 
     if (!chartInstance.options.scaleTypeChanged && chartInstance.options.scales.yAxes.filter(function (axis) { return axis.type !== 'linear'; }).length) { 
      console.log('linear'); 
      chartInstance.options.scaleTypeChanged = true; 
      chartInstance.options.scales.yAxes = Chart.helpers.scaleMerge(Chart.defaults.scale, { yAxes: chartInstance.options.linearScaleOptions }).yAxes; 
     } 
    } 
} 

を};

Chart.pluginService.register(changeScaleTypePlugin);

と、これは単純にチャートのオプションにいくつかのプロパティを追加適用する:ダニの

options: { 
        linearScaleOptions: [{ 
         id: 'y-axis-0', 
         type: 'linear', 
         tick: { 
          // callback: Chart.Ticks.formatters.linear, 
          min: 0 
         } 
        }], 
        logarithmicScaleOptions: [{ 
         id: 'y-axis-0', 
         type: 'logarithmic', 
         ticks: { 
          // callback: function (tickValue, index, ticks) { 
          //  var remain = tickValue/(Math.pow(10, Math.floor(Math.log(tickValue)/Math.LN10))); 

          //  if (tickValue === 0) { 
          //   return '0'; 
          //  } else if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === ticks.length - 1) { 
          //   return tickValue; 
          //  } 
          //  return ''; 
          //}, 
          min: 0 
         } 
        }], 
        changeScale: true, 
        maxRankDifference: 1, 

コメントアウトコールバックを使用すると、目盛り値をしたくない(私のような)状況にあります対数スケール上の科学的表記法で示されている。

この

に見える出力を与えるように:それは3

に設定して1

または

linear

に設定し、最大ランクプロパティで

logarithmic

またはコールバックのセットで:「変更」は対数であるように、スケールを設定するためになされたとき

logarithmic with natural ticks

0

あなたは適切な軌道に乗っていましたが、問題はスケールタイプごとにあり、スケールをレンダリングするために基礎となるスケールサービスによって使用される対応するプロパティセットがあります。

スケールを「線形」に設定すると、レンダリングされた線形スケールを生成する非表示の軸プロパティのセットがトリガされます。ただし、スケールを「対数」に設定すると、非表示の軸プロパティをレンダリングされた対数スケールを生成するために別々に設定する必要があります。

短いストーリーのため、このすべてを処理するにはChart.helpers.scaleMerge()関数を使用する必要があります(グラフオプションで単純にスケールタイプを変更して再レンダリングすることはできません)。

私はworking exampleを作成し、あなたが何を達成するかを実証しました。この仕組みの本質は以下の通りです。

document.getElementById('changeScaleAndData').addEventListener('click', function() { 
    if (isLinear) { 
    myBar.options.scales.yAxes = Chart.helpers.scaleMerge(Chart.defaults.scale, {yAxes: logarithmicScaleOptions}).yAxes; 
    isLinear = false; 
    } else { 
    myBar.options.scales.yAxes = Chart.helpers.scaleMerge(Chart.defaults.scale, {yAxes: linearScaleOptions}).yAxes; 
    isLinear = true; 
    } 

    myBar.data.datasets[0].data = [ 
    randomScalingFactor(), 
    randomScalingFactor(), 
    randomScalingFactor(), 
    ]; 

    myBar.update(); 
}); 
+0

これは実際にYSCALEに、対数1に目盛りの間の差をスケールを変更するには表示されません。すべてのティックの間で同じように、空間的な分離であり、それは定義上、リニアスケールである。私は最終的に解決策を見つけました(私は 'scaleMerge'へのポインタのためにあなたに感謝しなければなりません)私の答えを見てください – MikeW

関連する問題