📈

Flask + axios + Plotlyでajaxしてグラフを描画する

2021/09/26に公開

概要

Ajaxの勉強として、サーバサイドでデータ処理した結果をFlaskでAPIを実装し、ブラウザのPlotlyでグラフ化してみます。

サーバサイド(Flask)

今回はindexをホストするAPIと処理結果をJSONで送信するAPIの2つを作っておきます。前者はhtmlやブラウザサイドのコードなどの静的コンテンツを配信します。後者は(x,y)の乱数の組を100個JSONに詰めて配信するようにします。

app.py
# appの定義とかエントリーポイントは略
@app.route("/")
def app_route():
    return app.send_static_file("index.html")

@app.route("/api/data")
def app_sequence():
    return json.dumps(
        {
            "x": np.random.random(100).tolist(),
            "y": np.random.random(100).tolist(),
        }
    )

ここで注意しないといけないのは、JSONモジュールは中にNumPyのarrayをそのまま突っ込めないということです。ちゃんとlistにしてからjson.dumpsします。

ブラウザサイド(html、javascript)

html

Plotlyとaxiosをロードしておきます。

<html>
<head>
    <script src="public/javascripts/main.js"></script>

    <script src="https://cdn.plot.ly/plotly-2.4.2.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>

<body>
    <div id="mygraph"></div>
</body>
</html>

javascript

axiosでFlaskに作ったAPIをたたいてデータを取得し、mygraph領域に散布図を描画します。

window.onload = () => {
    scatter();
};

let scatter = () => {
    const mygraph = document.getElementById('mygraph');

    axios.get("/api/data")
        .then((res) => {
            Plotly.newPlot(mygraph, [{
                x: res.data.x,
                y: res.data.y,
                mode: 'markers',
                type: 'scatter',
            }], {
                margin: { t: 0 }
            });
        });
}

ここで注意しないといけないのは、描画する関数scatterwindow.onloadでウィンドウのロードが完了した後でないといけないということです。ブラウザサイドJavaScriptでは外部ライブラリもDOMの一つであるscriptタグで読み込むので、plotlyのscriptタグが読み込まれた後にこのJSコードが読み込まれないとnot foundになります。初歩的かもしれませんが自分はあまりフロントエンドを書かないので少し詰まりました。

実行結果

app.pyを実行してlocalhost:50000にアクセスすると下記のような散布図が出力されます。リロードするたびに点の位置が変わります。

Plotlyはぐりぐり動かしたりズームができるので、便利な描画ライブラリだと思います。

Discussion