web-dev-qa-db-ja.com

Vue Chart.js-棒グラフの単純な点/線

barチャートに、動的なX値とY値に0を持つ単純なドット/垂直線を追加する必要があります。必要なもののプレビュー(赤い点):

enter image description here

緑の値は動的です。

私の現在の状態のプレビュー:

enter image description here

ここで3.30はドットのX座標-[3.30、0]です。

チャートに Vueチャート を使用していて、_ 混合 を作成しようとしましたが、barscatterを使用しますが、scattertype: 'linear'が必要です。これはxAxisであり、barチャートの必要性に合わないためです。

だから私は chartjs-plugin-annotation を試してみましたが、これは「座標」を受け入れるboxタイプですが、ここでの問題はXX軸の固定値である必要がありますlabelsオブジェクト)。 X軸[3,0]を指定すると機能しますが、[3.5、0]のように10進数がある場合は機能しません。


  // data
  options: {
    responsive: true,
    maintainAspectRatio: false,
    legend: {
      display: false
    },
    scales: {
      yAxes: [{
        ticks: {
          min: 0,
          max: 1,
          stepSize: 0.1
        }
      }]
    }
  }

  // computed 
  labels: [1, 2, 3, 4, 5, 6], // fixed value, there are always 6 bars
  datasets: [
    {
      label: 'Values',
      backgroundColor: '#f89098',
      data: this.tableInputValues // array of decimal values
    }
  ]

したがって、私の質問は、「単純な」ドットまたは垂直線をChart.js棒グラフに配置する方法です。ここで、ドットはX軸に対して動的な値を持ちます- > [動的な値、0]。

FYI-それは約です 期待値

13
Vucko

私が理解している限りVueチャートはキャンバスを使用して機能します( デモページ で見られるように)。
そこで、私の提案は、DOM内のグラフを表すキャンバスノードを取得し、目的のドットを動的に書き込むことです。例えば:

var c = document.getElementById("bar-chart");   //hereby assuming canvas named "bar-chart"
var ctx = c.getContext("2d");
ctx.fillStyle = "#ff0000";                     //red color for the dot
ctx.beginPath();
let yPosition = c.height - 5;                 //fixed y position
let xPosition = 35;                          //that's the dynamic expected value
ctx.arc(xPosition, yPosition, 2.5, 0, 2 * Math.PI);
ctx.fill();

ここ Vueを使用してそれを達成する方法を示すデモを見つけます。このシナリオでは、afterDrawフックでキャンバスにドットを描画するためにコードをラップする必要があります。このフックは、次のようにプラグインとしてチャートコンポーネントにアタッチする必要があります。

...
mounted () { 
   //adding the plugin to draw the red dot
   this.addPlugin({
    id: 'chart-plugin',
    afterDraw: function (chart) {
       var c = chart.canvas;   
       var ctx = c.getContext("2d");
       ctx.fillStyle = "#ff0000";                     
       ctx.beginPath();
       let xPosition = 742; //x positioning to be calculated according to your needs
       let yPosition = c.height - 28;                                       
       ctx.arc(xPosition, yPosition, 3, 0, 2 * Math.PI);
       ctx.fill();
    }
  });

  //actual chart rendering
  this.renderChart({ 
    ...
  });
}
...

完全を期すために、 here には、Chart.jsプラグインAPIの利用可能なすべてのフックのリストがあります。

7
P3trur0

これはあなたの問題に対する私の解決策です https://jsfiddle.net/huynhsamha/e54djwxp/

そして、これは結果のスクリーンショットです

enter image description here

私のソリューションでは、type="line"と、type="linear"でx軸とy軸の両方を使用しています。 optionsoptionsを使用するために、ChartJS<chart>に追加します

<div id="vue">
  <chart type="line" :data="data" :options="options"></chart>
</div>

optionsは、x軸とy軸を設定して、データポイントと期待値をレンダリングします。

      options: {
        scales: {
            xAxes: [{
            type: 'linear',
            ticks: {
                min: 1,
                max: 6,
                stepSize: 1
            }
          }],
           yAxes: [{
            type: 'linear',
            ticks: {
                min: 0,
                max: 1,
                stepSize: 0.1
            }
            }]
        }
      }

そして、dataは2 datasetsを持ちます。 1つ目はデータポイントです。タイプlineを使用し、2つ目はタイプbubbleを使用する期待値です。

      data: {
        datasets: [{
            label: 'Frequency Data',
            data: dataPoints.map(({ val, freq }) => ({
                x: val,
              y: freq
            })),
            backgroundColor: 'rgba(72, 202, 59, 0.4)',
            borderColor: 'rgba(72, 202, 59, 1)'
        }, {
            label: 'Expected Value',
            type: 'bubble',
            data: [{ 
                x: expectedValue, 
              y: 0, 
              r: 8 // radius
            }],
            backgroundColor: 'rgba(255, 68, 0, 0.4)',
            borderColor: 'rgba(255, 68, 0, 1)'
        }]
        },

datasetsには、dataPointsexpectedValueがあり、APIからフェッチされてデータポイントを取得します。データポイントの単純なAPIもシミュレートします。

// simulate the API to get data points
const retrieveData = () => [
    { val: 1, freq: 0.15 },
    { val: 2, freq: 0.25 },
    { val: 3, freq: 0.3 },
    { val: 4, freq: 0.2 },
    { val: 5, freq: 0.1 },
    { val: 6, freq: 0.45 }
]


// fetch your data here, return array of JSON { val, freg }
const dataPoints = retrieveData() || [];

// calculate expected value = sum( val * freq ) each i in dataPoints
const expectedValue = dataPoints.reduce((cur, { val, freq }) => cur + val * freq, 0).toFixed(4);

スニペットを実行するか、フィドルで実行できます https://jsfiddle.net/huynhsamha/e54djwxp/92/

<script async src="//jsfiddle.net/huynhsamha/e54djwxp/92/embed/js,html,css,result/dark/"></script>
2
huynhsamha