teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

Chart.jsを使ったサンプルを追加

2021/01/29 16:31

投稿

退会済みユーザー
answer CHANGED
@@ -7,4 +7,147 @@
7
7
 
8
8
  (あとtimeがX軸、データがY軸のScatterというのがどういうものなのか想像しづらいです)
9
9
 
10
- なお手元で、Chart.jsを使っての散布図リアルタイム更新は普通に作れました。
10
+ なお手元で、Chart.jsを使っての散布図リアルタイム更新は普通に作れました。
11
+
12
+ # Chart.jsによるサンプル
13
+ コメント欄でChart.jsでの例が欲しいとのことだったので、最低限のコードを示します。
14
+ センシングデータがどのような形式であるのか、質問文では全く示されていないため、
15
+ 下記ではダミーデータを作成し表示しています。
16
+ 実際はセンシングデータの出力形式に合わせてflask側、html側を変える必要があります。
17
+
18
+ アニメーションのオン・オフやグラフ枠の固定などは調べれば出てきますので自力でやってください。
19
+ 補足:実際の手元verではChart.bundle.jsはCDNをリンクしています。
20
+
21
+ original.py
22
+ ```python
23
+ import json
24
+ import random
25
+ import time
26
+ from gevent import pywsgi
27
+ from geventwebsocket.handler import WebSocketHandler
28
+ from flask import Flask, request, render_template
29
+
30
+ app = Flask(__name__)
31
+
32
+ @app.route('/')
33
+ def index():
34
+ return render_template('index.html')
35
+
36
+ @app.route('/publish')
37
+ def publish():
38
+ if request.environ.get('wsgi.websocket'):
39
+ ws = request.environ['wsgi.websocket']
40
+ while True:
41
+ '''
42
+ ダミーのサンプルデータ。
43
+ Chart.jsに渡す場合は、
44
+ [
45
+ [{x: 10, y: 15}, {x: 8, y: 20}, {...},...],
46
+ [{x: **, y: **}, {x: , y: }, {...},...],
47
+ [{x: **, y: **}, {x: , y: }, {...},...],
48
+ ...
49
+ ]
50
+ という形をjson.dumpsして渡す。各行がグループとなる。
51
+ '''
52
+ ws.send(json.dumps(
53
+ [[{"x": random.random()*10, "y": random.random()*10} for _ in range(10)]for _ in range(3)]))
54
+
55
+ time.sleep(1)
56
+ return
57
+
58
+ if __name__ == '__main__':
59
+ app.debug = True
60
+ server = pywsgi.WSGIServer(('localhost', 8080), app, handler_class=WebSocketHandler)
61
+ server.serve_forever()
62
+ ```
63
+  
64
+ index.html
65
+ ```
66
+ <html>
67
+ <head>
68
+ <title>graph test</title>
69
+ </head>
70
+ <body>
71
+ <h1>Real time chart</h1>
72
+ <canvas id="graph" style="height: 200px;"></canvas>
73
+ <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
74
+ <script type="text/javascript" src="Chart.bundle.js"></script>
75
+
76
+ <script type="text/javascript">
77
+ var ws = new WebSocket("ws://localhost:8080/publish");
78
+ // 初期データ
79
+ var data = [[], [], []];
80
+
81
+ var ctx = document.getElementById('graph').getContext('2d');
82
+ var myChart = new Chart(ctx, {
83
+ type: 'line',
84
+ data: {
85
+ datasets: [
86
+ {
87
+ label: "Group 1",
88
+ data: data[0],
89
+ pointRadius: 5,
90
+ pointBorderRadius: 5,
91
+ borderColor: '#F00',
92
+ showLine: false
93
+ },
94
+ {
95
+ label: "Group 2",
96
+ data: data[1],
97
+ pointRadius: 5,
98
+ pointBorderRadius: 5,
99
+ borderColor: '#0F0',
100
+ showLine: false
101
+ },
102
+ {
103
+ label: "Group 3",
104
+ data: data[2],
105
+ pointRadius: 5,
106
+ pointBorderRadius: 5,
107
+ borderColor: '#00F',
108
+ showLine: false
109
+ }
110
+ ]
111
+ },
112
+ options: {
113
+ responsive: true,
114
+ scales: {
115
+ xAxes: [{
116
+ type: 'linear',
117
+ position: 'bottom'
118
+ }]
119
+ },
120
+ legend: {
121
+ position: 'bottom',
122
+ lineWidth: 0,
123
+ labels: {
124
+ fontSize: 12,
125
+ boxWidth: 12,
126
+ usePointStyle: true,
127
+ generateLabels: function (chart) {
128
+ return chart.data.datasets.map(function (dataset, i) {
129
+ return {
130
+ text: dataset.label,
131
+ fillStyle: dataset.backgroundColor,
132
+ hidden: !chart.isDatasetVisible(i),
133
+ lineCap: dataset.borderCapStyle,
134
+ strokeStyle: dataset.borderColor,
135
+ pointStyle: dataset.pointStyle,
136
+ datasetIndex: i
137
+ };
138
+ })
139
+ }
140
+ }
141
+ },
142
+ }
143
+ });
144
+ //websocket経由で受け取ったデータをparseしてChart.jsのデータに渡す
145
+ ws.onmessage = function (msg) {
146
+ myChart.data.datasets.forEach(function (dataset, index) { dataset.data = JSON.parse(msg.data)[index]; });
147
+ myChart.update();
148
+ };
149
+ </script>
150
+ </body>
151
+
152
+ </html>
153
+ ```