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

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

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

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

Angular

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

TypeScript

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

Q&A

解決済

1回答

2583閲覧

canvasで描画したグラフが削除できません

tnishi

総合スコア16

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

Angular

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

TypeScript

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

0グッド

0クリップ

投稿2017/08/18 11:25

Angular4を勉強している者です。

TypeScriptにてChart.jsを使ったグラフ描写を実装しています。

HTML

1<!doctype html> 2<html lang="en"> 3<head> 4 <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.min.js"></script> 5</head> 6<body> 7 <canvas id="graph2" width="1050" height="400"></canvas> 8</body> 9</html>

TypeScript

1 2// グラフ描画 3let data = { 4 labels: {"1月","2月","3月"}, 5 datasets: [ 6 { 7 label: "件数", 8 fillColor: "rgba(220,220,220,0.5)", 9 strokeColor: "rgba(220,220,220,0.8)", 10 highlightFill: "rgba(220,220,220,0.75)", 11 highlightStroke: "rgba(220,220,220,1)", 12 data: {3, 2, 10} // ★ここは可変データ。通るたびに変化★ 13 } 14 ] 15}; 16 17let element: HTMLCanvasElement =<HTMLCanvasElement>document.getElementById('graph1'); 18 19let myChart = new Chart(ctx, { 20 type: 'bar', 21 data: data 22 }); 23 24

一回上記の通り実装してグラフは表示されました。
しかし、画面リロードをせず再度上記処理を通した際に、一旦は最新のグラフが表示されるのですが、
1回目に描画した棒グラフの棒があった部分にホバーしたところ、1回目に描画したグラフに切り替わってしまいました。
おそらく裏で残ってしまっていると考えたので、以下の通り処理を追加しました。

TypeScript

1 2// グラフ描画 3let data = { 4 labels: {"1月","2月","3月"}, 5 datasets: [ 6 { 7 label: "件数", 8 fillColor: "rgba(220,220,220,0.5)", 9 strokeColor: "rgba(220,220,220,0.8)", 10 highlightFill: "rgba(220,220,220,0.75)", 11 highlightStroke: "rgba(220,220,220,1)", 12 data: {3, 2, 10} // ★ここは可変データ。通るたびに変化★ 13 } 14 ] 15}; 16 17let element: HTMLCanvasElement =<HTMLCanvasElement>document.getElementById('graph1'); 18 19// 追加箇所----------------------------------------------- 20let ctx = element.getContext("2d"); 21ctx.clearRect(0,0,element.width,element.height); 22ctx.beginPath(); 23// 追加箇所ここまで----------------------------------------------- 24 25let myChart = new Chart(ctx, { 26 type: 'bar', 27 data: data 28 }); 29 30 31

削除してから描画するという形でうまくいくかと思いきや、事態は変わりませんでした。
単純に描いたグラフを削除したいだけなのですが、なぜかうまくいきません。

非常にざっくりした説明で申し訳ございませんが、
canvasに詳しい方、同じような現象にあわれた方いらっしゃいましたらご教示いただけますと幸いです。

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

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

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

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

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

guest

回答1

0

ベストアンサー

毎回 new Chart(ctx,... としているであれば前のChartが残るのではないでしょうか。
Chart.jsは単純にCanvasにグラフを描くだけでなくアニメーション等も付いています。また、ホバー、クリック等のイベントが設定されるため、Chartへの参照が残ってGCに回収されないのだと思います。

別のグラフに切り替えるには new Chart(ctx,... をクラス変数に入れる等の後でアクセスできるようにして、グラフのデータを入れ替えて myChart.update() のメソッドで切替ができます。

素のJSですが切り替えサンプルです。

HTML

1<!DOCTYPE html> 2<html> 3<head> 4 <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script> 5</head> 6<body> 7<input type="button" value="graphA" onclick="graphA()"> 8<input type="button" value="graphB" onclick="graphB()"> 9<canvas id="graph1"></canvas> 10<script> 11function chartdata(data) { 12 return { 13 labels: ["1月","2月","3月"], 14 datasets: [ 15 { 16 label: "件数", 17 fillColor: "rgba(220,220,220,0.5)", 18 strokeColor: "rgba(220,220,220,0.8)", 19 highlightFill: "rgba(220,220,220,0.75)", 20 highlightStroke: "rgba(220,220,220,1)", 21 data: data 22 } 23 ] 24 }; 25} 26 27let ctx = document.getElementById('graph1').getContext("2d"); 28let myChart = new Chart(ctx, {type: 'bar', data: chartdata([])}); 29 30function graphA() { 31 myChart.data = chartdata([3, 2, 10]); 32 myChart.update(); 33} 34function graphB() { 35 myChart.data = chartdata([6,4,5]); 36 myChart.update(); 37} 38</script> 39</body> 40</html>

TypeScriptサンプルを追加します。
Angular-Cli 1.3.2 (Angular 4.3.6) + Chart.js 2.6.0で動作しています。

TypeScript

1import { Component, OnInit } from '@angular/core'; 2 3@Component({ 4 selector: 'app-chart', 5 template: '<div><button (click)="clicked($event)">Update</button><canvas id="graph1"></canvas></div>' 6}) 7export class ChartComponent implements OnInit { 8 cnt = 0; 9 myChart; 10 11 constructor() { } 12 13 ngOnInit() { 14 const element = <HTMLCanvasElement>document.getElementById('graph1'); 15 const ctx = element.getContext('2d'); 16 this.myChart = new Chart(ctx, {type: 'bar', data: this.chartdata([])}); 17 } 18 19 private chartdata(newData:Array<number>) { 20 return { 21 labels: ["1月","2月","3月"], 22 datasets: [ 23 { 24 label: "件数", 25 fillColor: "rgba(220,220,220,0.5)", 26 strokeColor: "rgba(220,220,220,0.8)", 27 highlightFill: "rgba(220,220,220,0.75)", 28 highlightStroke: "rgba(220,220,220,1)", 29 data: newData 30 } 31 ] 32 }; 33 } 34 35 clicked(event) { 36 this.cnt++; 37 const newData = ((this.cnt & 1) === 1) 38 ? [10, 20, 30] 39 : [30, 20, 10]; 40 this.myChart.data = this.chartdata(newData); 41 this.myChart.update(); 42 } 43}

投稿2017/08/21 02:32

編集2017/08/25 03:25
shimitei

総合スコア799

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

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

tnishi

2017/08/24 01:05

>shimitei 様 ご回答いただきありがとうございます。 いただいたサンプルを動かしたところ、正常に動作しました。 ただし、TypeScriptでは正常に動作しませんでした。 (グラフは切り替わりますが、前回表示されたグラフがあった場所にホバーすると前回のグラフに切り替わってしまします) 実装したTypeScript部分は以下の通りです。 ------------------------------------------------------------------------------------------------- // 一旦データを空にする let myChart = new Chart(ctx, {type: 'bar', data: this.chartdata(0)}); let data55: any; // データを取得 data55 = this.chartdata(1); myChart = new Chart(ctx, {type: 'bar', data: this.chartdata(1)}); myChart.update(); this.cnt ++; // これが呼ばれるたびに、返却するデータを切り替える chartdata(c) { let newData = []; // 引数が0の場合はデータを一切いれない if (c != 0) { if (this.cnt == 1 || this.cnt == 3 || this.cnt == 5 || this.cnt == 7) { newData[0] = 10; newData[1] = 20; newData[2] = 30; } else { newData[0] = 30; newData[1] = 20; newData[2] = 10; } } return { labels: ["1月","2月","3月"], datasets: [ { label: "件数", fillColor: "rgba(220,220,220,0.5)", strokeColor: "rgba(220,220,220,0.8)", highlightFill: "rgba(220,220,220,0.75)", highlightStroke: "rgba(220,220,220,1)", data: newData } ] }; } ------------------------------------------------------------------------------------------------- JavaScriptとTypeScriptで挙動が違うということはありますでしょうか。 勉強不足で申し訳ございません。 再度ご教示いただけますと幸いです。
shimitei

2017/08/25 03:36

問題なく切り替え可能なTypeScript(Angular4)のサンプルを追加しました。 質問者さんのコードでうまく切り替えできていない原因は、やはり更新時に毎回new Chartしているためでしょう。
tnishi

2017/08/28 02:04

早々のご回答、誠にありがとうございます。 ご教示いただきました通りオブジェクトは初期処理で生成し、データの更新は別で行いupdateをすることで前回のグラフが表示されなくなりました。解決です、ありがとうございます。 今回のポイントとしましては以下の点だと考えております。 ・オブジェクトを作り直ししていた為、以前のグラフが残っていた。 ・データを入れなおした後、updateをすれば切り替えられる。 ・Chart.jsのバージョンが若干古かった(2.3.0を使っていました) 特に一番上の「オブジェクトを作り直ししていた為、以前のグラフが残っていた。」 というところは盲点でした。 Angularの件でまたお伺いすることがあると思いますが、その際は助言いただけますと幸いです。 今回は丁寧親切かつ分かりやすく解説、またサンプルまでご提示いただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問