SE_BOKUのまとめノート的ブログ

SE_BOKUが知ってること・勉強したこと・考えたことetc

Pythonからデータを渡し、JavaScriptでレーダーチャートを描く/django+Chart.js

f:id:arakan_no_boku:20200123212917p:plain

目次

Pythonからデータを渡し、JavaScriptでレーダーチャートを描く

PythonDjangoを使います。

JavaScriptでグラフを描くには、Chart.jsを使います。

描くのはこんな感じの「レーダーチャート」です。

f:id:arakan_no_boku:20200123213544p:plain

今回は、それなりに見える最小限の設定をやってみたいと思います。

 

Html部分

いきなりですが・・まずHtmlです。

<canvas id="myChart"></canvas>

<script type="text/javascript" src="{% static "js/chart01.js" %}"></script>

このようにcanvasを定義して、idをキーにして、グラフを表示する場所を定義し、グラフを描くJavaScriptはscriptタグに保存したファイル名を書いて、読み込みます。

JavaScriptは、chart01.jsという名前で保存している前提とします。

 

JavaScript
let ctx = document.getElementById('myChart').getContext('2d');
let myRadarChart = new Chart(ctx, {
    type: 'radar',
    data: {
        labels: ['選択肢1', '選択肢2', '選択肢3', '選択肢4','選択肢5'],
        datasets: [{
            data: [8, 5, 5, 5, 6],
            backgroundColor: "rgba(255,0,0,0.2)", // 線の下の塗りつぶしの色
            borderColor: "red",                   // 線の色
            borderWidth: 2,                       // 線の幅
            pointStyle: "circle",                 // 点の形状
            pointRadius: 6,                       // 点形状の半径
            pointBorderColor: "red",              // 点の境界線の色
            pointBorderWidth: 2,                  // 点の境界線の幅
            pointBackgroundColor: "yellow",       // 点の塗りつぶし色
            pointLabelFontSize: 20,
            label: 'Aさん'
            }
        ]
    },
    options: {
        responsive: true,
        title: {                // タイトル
            display: true,      // 表示する
            fontSize: 20,       // タイトルのフォント
            text: 'レーダーサンプル'         // 表示するタイトル
        },
        legend: {
            position: 'bottom', // 凡例の表示位置
            labels: {
                fontSize: 20,   // 判例のフォントサイズ
            },
        },
        scale: {
            // スケールを隠す。
            display: true,      // メモリを表示する
            ticks: {            // 目盛り
                min: 0,         // 目盛りの最小値
                max: 10,        // 目盛りの最大値
                stepSize: 1,    // 目盛の間隔
                fontSize: 12,   // 目盛り数字の大きさ
                fontColor: "purple"  // 目盛り数字の色
            },
            pointLabels: {
                fontSize: 20    // チャートラベルのフォントサイズ
            },
            angleLines: {        // 軸(放射軸)
                display: true,
                color: "maroon"
            },
            gridLines: {         // 補助線(目盛の線)
                display: true,
                color: "lime"
            }
        },
    }
});

 

ポイントを補足します。

ラベルを指定することで、選択肢の数が決まります。

labels: ['選択肢1', '選択肢2', '選択肢3', '選択肢4','選択肢5'],

 データは配列で渡します。

data: [8, 5, 5, 5, 6]

データの並び順は、ラベルの並び順に対応します。

 

体裁を整えるのに特に重要なのが、Scaleブロックの「ticks」と「pointLabels」です。

ticksは、チャートの目盛りを固定するための設定です。

ここで最小と最大を指定しない場合のデフォルトだと、与えたデータの最小値が中心の目盛りになるなど動的に調整されてしまうので、グラフの形が変わってしまいます。

 

pointlabelsはこの赤枠の部分のフォントです。

f:id:arakan_no_boku:20200123225532p:plain

 

色の指定は以下のようなカラーコード表を参照します。

W3C基本16色は「red」のように名前でも指定できるので、今回はそれを使いました。

www.netyasun.com

 

あとは、ソースのコメントを参照ください。。

 

djangoからデータを受け渡すサンプル

上記でグラフは表示できます。

でも、データをJavaScriptに直書きしてる限り、何の役にも立ちません(笑)

djangoからその辺を受け渡すようにします。

今回のターゲットは。

  • labels: ['選択肢1', '選択肢2', '選択肢3', '選択肢4','選択肢5'],
  • data: [8, 5, 5, 5, 6],
  • label: 'Aさん'
  • text: 'レーダーサンプル'

の4か所です。

これらをdjangopythonプログラムから、以下のようにして渡します。

from django.shortcuts import render


def chart_do(request):
    c = {
        'chart_labels': "'選択肢1', '選択肢2', '選択肢3', '選択肢4','選択肢5'",
        'chart_data': "8, 5, 5, 5, 6",
        'chart_title': "レーダーサンプル",
        'chart_target': "Aさん"
    }
    return render(request, 'chart01.html', c)

dataやlabelsは、javascript側では配列データでしたが、一旦受け渡しのためにカンマ区切りの文字列にしています。

上記のHTML部分は、chart01.htmlという名前で以下のように受け取る想定です。 

<div class="container">
    <div class="row my-4">
        <canvas id="myChart"></canvas>
    </div>
    <input type="hidden" id="chart_labels" name="chart_labels" value="{{ chart_labels}}">
    <input type="hidden" id="chart_title" name="chart_title" value="{{ chart_title}}">
    <input type="hidden" id="chart_target" name="chart_target" value="{{ chart_target}}">
    <input type="hidden" id="chart_data" name="chart_data" value="{{ chart_data}}">
</div>
<script type="text/javascript" src="{% static "js/chart01.js" %}"></script>

 

hiddenタグを配置して、valuepython側の変数を受け取っています。

あとは、このhiddenタグの情報をJavaScript側で受け取ればよいです。

受け取る部分だけ抜粋します。

let title = document.getElementById('chart_title').value;
let target = document.getElementById('chart_target').value;
let dstr = String(document.getElementById('chart_data').value);
let darr = dstr.split(',');
let dlabel = String(document.getElementById('chart_labels').value);
let larr = dlabel.split(',');

 

IDでvalueを取得して、dataとlabelsの部分はStringでうけとって、カンマをデリミタにしてsplitをかけて配列データに変換してます。

あとは。

  • labels: larr,
  • data: darr,
  • label: target
  • text: title

のようにリテラルの部分を変数に置き換えます。

これで実行して、リテラルで指定した時と同じグラフが表示できれば、OKですね。

f:id:arakan_no_boku:20200124014351p:plain

よしよし。

 

参考にしたサイトなど

日本語ドキュメントは充実してます。

misc.0o0o.org

サンプルもあります。

これでソースの表示をすると

www.chartjs.org

 あと、英語ですが本家の方です。

内容的には日本語版とほぼ同じみたいですけど。

www.chartjs.org

 

最後にソース全文です

pythondjango)のソース+JavaScriptです。

 

views.py 

from django.shortcuts import render


def chart_do(request):
    c = {
        'chart_labels': "'選択肢1', '選択肢2', '選択肢3', '選択肢4','選択肢5'",
        'chart_data': "8, 5, 5, 5, 6",
        'chart_title': "レーダーサンプル",
        'chart_target': "Aさん"
    }
    return render(request, 'chart01.html', c)

urls.py

from django.contrib import admin
from django.urls import path
from . import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('demo07/', views.chart_do, name='chart01'),
]
   

base.html

{% load static %}
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
{% load widget_tweaks %}

<!doctype html>
<html lang="jp">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  	{% block header %}
	{% endblock %}
    <title>{% block title %}デモ用テンプレート{% endblock %}</title>
  </head>
  <body>
    <nav class="navbar navbar-dark bg-primary text-white">
        <h3 >サンプル (django3.0 & bootstrap4)</h3>
    </nav>

    <div class="container">
	    {% block content %}
	    {% endblock %}
    </div>    
   </body>
</html>   

chart01.html

{% extends 'base.html' %}
{% load static %}
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
{% load widget_tweaks %}

{% block header %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
{% endblock %}

{% block title %}
  サンプルその1
{% endblock %}

{% block content %}
<div class="container">
    <div class="row my-4">
        <canvas id="myChart"></canvas>
    </div>
    <input type="hidden" id="chart_labels" name="chart_labels" value="{{ chart_labels}}">
    <input type="hidden" id="chart_title" name="chart_title" value="{{ chart_title}}">
    <input type="hidden" id="chart_target" name="chart_target" value="{{ chart_target}}">
    <input type="hidden" id="chart_data" name="chart_data" value="{{ chart_data}}">
</div>
<script type="text/javascript" src="{% static "js/chart01.js" %}"></script>
{% endblock %}
    

chart01.js

let ctx = document.getElementById('myChart').getContext('2d');
let title = document.getElementById('chart_title').value;
let target = document.getElementById('chart_target').value;
let dstr = String(document.getElementById('chart_data').value);
let darr = dstr.split(',');
let dlabel = String(document.getElementById('chart_labels').value);
let larr = dlabel.split(',');
let myRadarChart = new Chart(ctx, {
    type: 'radar',
    data: {
        labels: larr,
        datasets: [{
            data: darr,
            backgroundColor: "rgba(255,0,0,0.2)", // 線の下の塗りつぶしの色
            borderColor: "red",                   // 線の色
            borderWidth: 2,                       // 線の幅
            pointStyle: "circle",                 // 点の形状
            pointRadius: 6,                       // 点形状の半径
            pointBorderColor: "red",              // 点の境界線の色
            pointBorderWidth: 2,                  // 点の境界線の幅
            pointBackgroundColor: "yellow",       // 点の塗りつぶし色
            pointLabelFontSize: 20,
            label: target
            }
        ]
    },
    options: {
        responsive: true,
        title: {                // タイトル
            display: true,      // 表示する
            fontSize: 20,       // タイトルのフォント
            text: title         // 表示するタイトル
        },
        legend: {
            position: 'bottom', // 凡例の表示位置
            labels: {
                fontSize: 20,   // 判例のフォントサイズ
            },
        },
        scale: {
            // スケールを隠す。
            display: true,      // メモリを表示する
            ticks: {            // 目盛り
                min: 0,         // 目盛りの最小値
                max: 10,        // 目盛りの最大値
                stepSize: 1,    // 目盛の間隔
                fontSize: 12,   // 目盛り数字の大きさ
                fontColor: "purple"  // 目盛り数字の色
            },
            pointLabels: {
                fontSize: 20    // チャートラベルのフォントサイズ
            },
            angleLines: {        // 軸(放射軸)
                display: true,
                color: "maroon"
            },
            gridLines: {         // 補助線(目盛の線)
                display: true,
                color: "lime"
            }
        },
    }
});

こんな感じです。

ではでは。