質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

Chart.js

Chart.jsは、多様なグラフを組み込めるJavaScriptのライブラリ。折れ線グラフや棒グラフ、円グラフ、レーダーチャートなどのグラフの種類が用意されています。HTML5のCanvasを用いて描画され、マークアップも分かりやすく、簡単に編集することが可能です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

1回答

1215閲覧

【JavaScript】少々特殊なグラフ描写について質問

waito

総合スコア23

Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

Chart.js

Chart.jsは、多様なグラフを組み込めるJavaScriptのライブラリ。折れ線グラフや棒グラフ、円グラフ、レーダーチャートなどのグラフの種類が用意されています。HTML5のCanvasを用いて描画され、マークアップも分かりやすく、簡単に編集することが可能です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2020/09/03 22:48

編集2020/09/21 22:24

実現したいこと

以下のようなグラフを作成したいです。
![イメージ説明]

<要件>
・各モデルのスコアとカテゴリを日付毎に表示する
※カテゴリ:全てのモデルのスコアを元に算出し、高、中、低で表現したもの。

<希望>
・chart.jsを使用する
※現在chart.jsを使用して色々と試行錯誤しているので、chart.jsを使いたいです。
chart.jsで実現できなければ他のライブラリでも全く問題ないです。

環境

Angular 10
Internet Explorer 11(または、Microsoft Edge)
chart.js 2.9.24

困っていること

実現方法は何でも良いのですが、
以下の通り、X軸ラベルに日付とカテゴリをセットしてグラフ上部の表を作成しようと思っています。
labels: [[6/1, 低], [6/5, 低], ~, [7/13, 中]]

次にラベルの項目毎(低、中、高)のfontColorを変更しようと考えたのですが、
方法が分かりませんでした。

試したこと

以下を参考に、fontColorを配列にしてみましたが、デフォルトの色になり、
設定通りにセット出来ませんでした。

https://github.com/chartjs/Chart.js/issues/2442

お手数ですが、アドバイスをお願い致します。

ソースコードの抜粋

HTMLとJavaScriptのコードです。(CSSはないです)
JavaScriptのコードは多少切り貼りしています。
また、Scoreオブジェクトは日付、カテゴリ、スコアを持っています。

html

1<div> 2 <canvas #categoryChart width="744px" height="212px"></canvas> 3</div>

javascript

1 2(省略) 3 4// 宣言 5@ViewChild('categoryChart') 6elementRef: ElementRef; 7chartData = { labels: [], series1: [], series2: [] }; 8chartOptions: ChartOptions; 9context: CanvasRenderingContext2D; 10chart: Chart; 11 12(省略) 13 14// chart作成関数 15chartCreate(history: Score[]): void { 16 17 // チャートデータのセット 18 this.chartData.labels = []; 19 this.chartData.series1 = []; 20 this.chartData.series2 = []; 21 history.forEach((score, i) => { 22 const scoringDate = new Date(score.SCORINGDATE); 23 // ラベルを日付とカテゴリの配列にする(日付\nカテゴリと表示される) 24 this.chartData.labels[i] = 25 [this.datepipe.transform(scoringDate, 'M/d'), score.CATEGORY]; 26 this.chartData.series1[i] = score.model[0].SCORE; 27 this.chartData.series2[i] = score.model[1].SCORE; 28 }); 29 30 // チャートオプションのセット 31 this.chartOptions = { 32 scales: { 33 yAxes: [ 34 { 35 ticks: { 36 min: 0, 37 max: 100 38 }, 39 }], 40 xAxes: [ 41 { 42 ticks: { 43 fontSize: 16, 44 // 色をつけようと試した箇所 45 // fontColor: ['#f0554e', '#f3ca3e'], 46 // callback: (tickValue, index, ticks) => { 47 // return tickValue; 48 // } 49 }, 50 }], 51 }, 52 events: ['click'], 53 onClick: (event, elements) => { 54 this.changeDate(elements, history); 55 } 56 }; 57 58 // canvasの取得 59 this.context = this.elementRef.nativeElement.getContext('2d'); 60 61 // チャートの作成 62 this.chart = new Chart(this.context, { 63 type: environment.chart_type, 64 data: { 65 labels: this.chartData.labels, 66 datasets: [{ 67 label: 'Aモデル', 68 data: this.chartData.series1, 69 backgroundColor: ['rgba(0, 0, 255, 0)'], 70 borderColor: ['rgba(20, 0, 255, 100)'], 71 steppedLine: true, 72 borderWidth: 4, 73 }, { 74 label: 'Bモデル', 75 data: this.chartData.series2, 76 backgroundColor: ['rgba(135, 206, 250, 0)'], 77 borderColor: ['rgba(135, 206, 250, 100)'], 78 steppedLine: true, 79 borderWidth: 2, 80 }], 81 }, 82 options: this.chartOptions, 83 }); 84};

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kuma_kuma_

2020/09/21 18:10

chart.jsのバージョンを教えてください(1と2で処理が全く違う) あとchart.jsで再現できている範囲で構いません HTTPとCSS,JSの内容を追加記載下さい。
waito

2020/09/21 21:45

コメントありがとうございます! 追記致しました。 chart.jsはバージョン2.9.24です。
guest

回答1

0

ベストアンサー

画像サンプルとChart.jsの設定全然別で大変でした。
その辺りの調整でコードの呼び方など変えていますので調整はお願いします。
画像サンプルにできるだけ合わせて表示するように調整しました。

左のラベルと上の列名2列はChartの描写が終了した時点で
計算しながら追記しています。

あとはChart.js標準の機能ですので調整はわかるかと思います。

HTML

1<!DOCTYPE html> 2<html> 3<head> 4<meta charset="utf-8" /> 5<title></title> 6 <link rel="stylesheet" href="./Chart/dist/Chart.min.css"> 7 <script src="./Chart/dist/Chart.min.js"></script> 8 9</head> 10<body> 11<div> 12 <canvas id="claimCategoryChart" width="744px" height="212px"></canvas> 13</div> 14</body> 15</html>

Javascript

1var chartLines; 2var context; 3var chartData = { labels: [], labels2: [], series1: [], series2: [] }; 4window.onload = function () { 5 // データ登録 6 this.chartData.labels = ['6/1', '6/5', '6/8', '6/14', '6/19', '6/25', '7/3']; 7 this.chartData.labels2 = ['低', '高', '低', '中', '高', '中', '中']; 8 this.chartData.series1 = [100, 50, 110, 80, 90, 50, 10]; 9 this.chartData.series2 = [50, 80, 100, 80, 120, 100, 70]; 10 11 // 描写後処理追加 12 Chart.plugins.register({ 13 afterDatasetsDraw: function(chart, easing) { 14 if(chart.canvas.id == 'claimCategoryChart'){ 15 // 縦軸ラベル描写 16 context.font = '10pt Arial'; 17 context.fillStyle = 'rgba(137, 137, 137)'; 18 context.fillText('スコア', 2, Math.floor(chart.height / 2) + 20); 19 var nLeft = 62; // 表の左端の距離 20 var nRight = 110; // 表の右端の距離 21 var nMove = (chart.width - nLeft - nRight) / chartLines.data.labels.length; 22 nLeft += nMove / 2; // 中央へ移動 23 // ラベルの分だけループ 24 for(var i = 0; i < chartLines.data.labels.length; i++){ 25 // 日付ラベル表示 26 context.fillStyle = 'rgba(137, 137, 137)'; 27 var nTextWidth = context.measureText(chartLines.data.labels[i]).width; // 文字幅取得 28 context.fillText(chartLines.data.labels[i], nLeft - (nTextWidth / 2), 10); // 中央表示 29 // ランク度表示 30 if(chartLines.data.labels2[i] == '高'){ 31 context.fillStyle = 'rgba(255, 95, 88)'; 32 }else if(chartLines.data.labels2[i] == '中'){ 33 context.fillStyle = 'rgba(245, 212, 98)'; 34 }else if(chartLines.data.labels2[i] == '低'){ 35 context.fillStyle = 'rgba(42, 201, 64)'; 36 } 37 nTextWidth = context.measureText(chartLines.data.labels2[i]).width; // 文字幅取得 38 context.fillText(chartLines.data.labels2[i], nLeft - (nTextWidth / 2), 30); // 中央表示 39 nLeft += nMove; 40 } 41 } 42 } 43 }); 44 // チャート登録 45 context = document.getElementById('claimCategoryChart').getContext('2d'); 46 chartLines = new Chart(context, { 47 type: 'bar', 48 data: { 49 labels: this.chartData.labels, 50 labels2: this.chartData.labels2, 51 datasets: [{ 52 label: 'Aモデル', 53 type: "line", 54 fill: false, 55 data: this.chartData.series1, 56 backgroundColor: ['rgba(0, 0, 255, 0)'], 57 borderColor: ['rgba(20, 0, 255, 100)'], 58 yAxisID: "y-axis-1", 59 steppedLine: true, 60 }, { 61 label: 'Bモデル', 62 type: "line", 63 fill: false, 64 data: this.chartData.series2, 65 backgroundColor: ['rgba(135, 206, 250, 0)'], 66 borderColor: ['rgba(135, 206, 250, 100)'], 67 yAxisID: "y-axis-1", 68 steppedLine: true, 69 }] 70 }, 71 options: { 72 tooltips: { 73 mode: 'nearest', 74 intersect: false, 75 }, 76 responsive: true, 77 layout: { 78 padding: { 79 left: 25, 80 right: 0, 81 top: 16, 82 bottom: 0 83 } 84 }, 85 legend: { 86 display: true, 87 position: 'right', 88 fullWidth: true, 89 }, 90 scales: { 91 xAxes: [{ 92 position: "top", 93 ticks: { 94 callback: function(value, index, values) { 95 return ''; 96 } 97 }, 98 gridLines: { 99 display: false, 100 }, 101 }], 102 yAxes: [{ 103 id: "y-axis-1", 104 type: "linear", 105 position: "left", 106 ticks: { 107 max: 120, 108 min: 0, 109 stepSize: 20, 110 callback: function(value, index, values) { 111 return (value == 100 || value == 0) ? value : ''; 112 } 113 }, 114 scaleLabel: { 115 display: false 116 }, 117 }, { 118 id: "y-axis-2", 119 type: "linear", 120 display: false, 121 ticks: { 122 max: 120, 123 min: 0, 124 stepSize: 20 125 }, 126 gridLines: { 127 drawOnChartArea: false, 128 }, 129 }], 130 }, 131 } 132 }); 133}

投稿2020/09/22 02:21

kuma_kuma_

総合スコア2506

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

waito

2020/09/22 03:27

大変ありがとうございます!! chart.jsで実装することを諦めかけていたので本当に助かります! ありがとうございました!
waito

2020/09/22 07:15

すみません。一つ質問させて下さい。 2つ目のY軸(y-axis-2)は何のために設定しているのでしょうか? 消して試してみても、変化が良く分からず。
kuma_kuma_

2020/09/22 12:46

2つ目のY軸(y-axis-2) Bモデル用の設定です。 max: 120, min: 0, stepSize: 20 2本目のグラフ範囲等で使用していまうので消さないで下さい でないと1本目とY軸単位が合わなくなります
waito

2020/09/22 21:46

ありがとうございます。 例えば、aモデルのmaxが50でbモデルのmaxが200の場合、y-axis-2のmaxだけ大きくするのでしょうか? それともaモデルとbモデルのmin,max,stepsizeは合わせるべきなのでしょうか?
kuma_kuma_

2020/09/22 22:48

試されると判るはずですが、 この画像のグラフですと左のY軸(Aモデル)だけに目盛を出していますよね? AモデルとBモデルの最少最大が違う場合右にもY軸(Bモデル)の目盛を出さないとおかしくなります。 (例としてAモデルの100とBモデルの100の位置が変わる) 今回は単位が同じなのでAモデル、Bモデルを左のY軸表記だけでまかなっています。 よって「min,max,stepsize」は同じにしないといけません。 それとも根本的にAモデルとBモデルの値の内容(単位)が違うのですか? PS.今気づいたのですが”カテゴリ”と記載する処理が抜けていましたね "スコア"と同じタイミングで描写を行ってください。
waito

2020/09/23 02:15

丁寧にありがとうございます。 よく理解出来ました! AモデルとBモデルの単位は同じなので大丈夫です。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問