🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Chart.js

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

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

1回答

2034閲覧

Chart.jsで二重にグラフが表示されてしまう

fork_

総合スコア43

Chart.js

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

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2020/12/03 14:02

編集2020/12/03 14:33

Laravel+Chart.jsで、複数のドロップダウンメニューでの選択に応じて動的にグラフが切り替わる仕組みを作りたいと考えています。

Laravelは6系、
Chart.js:2.9.4です。

【イメージ図】
イメージ説明

全体大まかな流れはこのような形になります。

  1. ドロップダウンメニューを複数設置
  2. ドロップダウンで条件を指定する
  3. 指定されたときに、ajaxで指定された複数の条件をpostする(int形式で送信する)
  4. コントローラー側でpostされた条件を元にselect文を投げ、一致するレコードのみ抽出する
  5. JS側でチャートを再描画する

そこで問題なのですが、5の手順まで完了してAjax通信してコントローラーから取得した値をグラフで表現するところまでできましたが、グラフをマウスオーバーすると前回の値が表示されてしまいます。

  1. ドロップダウンメニューで、「日本」「A型」 と選択すると、動的にグラフが切り替わる
  2. ドロップダウンメニューで、「アメリカ」「B型」と選択すると、動的にグラフが切り替わる
  3. グラフをマウスオーバーすると、マウスオーバーの位置によって1と2が両方表示(ちらつき)されてしまう

グラフ.destroy(); で既存のグラフは削除してから再描画しているはずなのですが、ちらつく原因が分からずつまづいています。
こちらの原因に関しまして、ご教示いただけますと幸いです。

【テーブル定義】

testuserテーブル

カラム概要
- idid
- bloodint
- country_id国籍テーブル切り出し
- 家賃int

countriesテーブル

カラム名概要 
idid
country国名
// blade.php <select name="country" id="country"> <option value="1">日本</option> <option value="2">アメリカ</option> </select> <select name="blood" id="blood"> <option value="1">A</option> <option value="2">B</option> </select> <canvas id="myBarChart"></canvas>
//script部分 <script> // カレンダー初期表示 var ctx = document.getElementById("myBarChart"); var myBarChart = new Chart(ctx, { type: "bar", data: { labels: ["条件に一致するレコードの家賃の合計"], datasets: [ { label: "売上", data: [], backgroundColor: "rgba(219,39,91,0.5)", }, ], }, options: { title: { display: true, text: "売上", }, scales: { yAxes: [ { ticks: { suggestedMax: 100, suggestedMin: 0, stepSize: 10, callback: function (value, index, values) { return "¥" + value; }, }, }, ], }, }, }); // 国籍のドロップダウンメニューを取得 var dropDown = document.getElementById("country"); // もし、ドロップダウンメニューが選択されたら dropDown.onchange = function () { var country = $(this).val(); // countryの選択値を取得 var blood = $("#blood").val(); // bloodの選択値を取得 $.ajaxSetup({ headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"), }, }); $.ajax({ //POST通信 type: "post", //ここでデータの送信先URLを指定します。 url: "/getcharts", dataType: "json", data: { country: country, //ドロップダウンの選択値を送信 blood: blood, }, }) //通信が成功したとき .then((res) => { if(myBarChart){ myBarChart.destroy(); } // レスポンスの結果(連想配列)から、「家賃」のところだけ合計する const total = res.reduce((sum, i) => sum + i.house_money, 0); // グラフ再描画 var myBarChart = new Chart(ctx, { type: "bar", data: { labels: ["条件に一致するレコードの家賃の合計"], datasets: [ { label: "売上", data: [total], // レスポンスの結果(家賃だけ合計した値) backgroundColor: "rgba(219,39,91,0.5)", }, ], }, options: { title: { display: true, text: "売上", }, scales: { yAxes: [ { ticks: { suggestedMax: 100, suggestedMin: 0, stepSize: 10, callback: function (value, index, values) { return "¥" + value; }, }, }, ], }, }, }); }) //通信が失敗したとき .fail((error) => { console.log(error); }) }; // 血液型のドロップダウンメニューを取得 var dropDown = document.getElementById("blood"); // もし、ドロップダウンメニューが選択されたら dropDown.onchange = function () { var country = $("#country").val(); // countryの選択値を取得 var blood = $(this).val(); // bloodの選択値を取得 $.ajaxSetup({ headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"), }, }); $.ajax({ //POST通信 type: "post", //ここでデータの送信先URLを指定します。 url: "/getcharts", dataType: "json", data: { country: country, blood: blood, }, }) //通信が成功したとき .then((res) => { if(myBarChart){ myBarChart.destroy(); } // レスポンスの結果(連想配列)から、「家賃」のところだけ合計する const total = res.reduce((sum, i) => sum + i.house_money, 0); // グラフ再描画 var myBarChart = new Chart(ctx, { type: "bar", data: { labels: ["条件に一致するレコードの家賃の合計"], datasets: [ { label: "売上", data: [total], // レスポンスの結果(家賃だけ合計した値) backgroundColor: "rgba(219,39,91,0.5)", }, ], }, options: { title: { display: true, text: "売上", }, scales: { yAxes: [ { ticks: { suggestedMax: 100, suggestedMin: 0, stepSize: 10, callback: function (value, index, values) { return "¥" + value; }, }, }, ], }, }, }); }) //通信が失敗したとき .fail((error) => { console.log(error); }) }; </script>
// Controller部分 public function getCharts(Request $request) { // ドロップダウンメニューの選択の結果から、当てはまるレコードのみを抽出 $country = $request->country; $blood = $request->blood; $house_money = Testuser::where("country_id", "=", $country) ->where("blood", "=", $blood)->get(); return $house_money; //JS側に値を返却 }

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

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

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

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

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

FKM

2020/12/04 00:44

Ajax通信は成功しているのでしょうか? そして、その後のif文判定はtrueを返しているのでしょうか?
fork_

2020/12/04 01:00

通信は成功しております。 また、if文判定もtrueを返しておりました。 if(myBarChart){ myBarChart.destroy(); } 部分と、グラフ再描画の部分を削除し、 myBarChart.data.datasets[0].data[0] = total; myBarChart.update(); とすることで解決できました。。
guest

回答1

0

自己解決

if(myBarChart){
myBarChart.destroy();
}
部分と、グラフ再描画の部分を削除し、
myBarChart.data.datasets[0].data[0] = total;
myBarChart.update();
とすることで解決に至りました。

コードの全貌は下記になります。

<script> // カレンダー初期表示 var ctx = document.getElementById("myBarChart"); var myBarChart = new Chart(ctx, { type: "bar", data: { labels: ["条件に一致するレコードの家賃の合計"], datasets: [ { label: "売上", data: [], backgroundColor: "rgba(219,39,91,0.5)", }, ], }, options: { title: { display: true, text: "売上", }, scales: { yAxes: [ { ticks: { suggestedMax: 100, suggestedMin: 0, stepSize: 10, callback: function (value, index, values) { return "¥" + value; }, }, }, ], }, }, }); // 国籍のドロップダウンメニューを取得 var dropDown = document.getElementById("country"); // もし、ドロップダウンメニューが選択されたら dropDown.onchange = function () { var country = $(this).val(); // countryの選択値を取得 var blood = $("#blood").val(); // bloodの選択値を取得 $.ajaxSetup({ headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"), }, }); $.ajax({ //POST通信 type: "post", //ここでデータの送信先URLを指定します。 url: "/getcharts", dataType: "json", data: { country: country, //ドロップダウンの選択値を送信 blood: blood, }, }) //通信が成功したとき .then((res) => { // レスポンスの結果(連想配列)から、「家賃」のところだけ合計する const total = res.reduce((sum, i) => sum + i.house_money, 0); myBarChart.data.datasets[0].data[0] = total; myBarChart.update(); }) //通信が失敗したとき .fail((error) => { console.log(error); }) }; // 血液型のドロップダウンメニューを取得 var dropDown = document.getElementById("blood"); // もし、ドロップダウンメニューが選択されたら dropDown.onchange = function () { var country = $("#country").val(); // countryの選択値を取得 var blood = $(this).val(); // bloodの選択値を取得 $.ajaxSetup({ headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"), }, }); $.ajax({ //POST通信 type: "post", //ここでデータの送信先URLを指定します。 url: "/getcharts", dataType: "json", data: { country: country, blood: blood, }, }) //通信が成功したとき .then((res) => { // レスポンスの結果(連想配列)から、「家賃」のところだけ合計する const total = res.reduce((sum, i) => sum + i.house_money, 0); myBarChart.data.datasets[0].data[0] = total; myBarChart.update(); }) //通信が失敗したとき .fail((error) => { console.log(error); }) }; </script>

投稿2020/12/04 01:04

fork_

総合スコア43

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問