【PythonのFlask、JavaScript】端末の傾きに応じてボールを動かすアプリを作る
PythonのFlaskとJavaScriptを使って、Android端末の傾きに応じてブラウザ上でボールを動かすプログラムを試します。メモ。
動作中のキャプチャ画像
傾けるとボールが動きます。
- JavaScriptってどう書くの?
- JavaScriptはどうやって動かすの?
- PythonのWebアプリでJavaScriptが動くんじゃない?
- JavaScriptで端末の傾きセンサー値が取得できるの?
というサッパリな状況で作っております。htmlとJavaScriptは写経。リンクは最後に貼っています。
目次
1. 実行環境
- Android(スマホ)
- Termux(Androidアプリ)
- Python3.9(Termuxでインストール)
- Pythonの外部ライブラリ
- Flask(Webアプリ作成用)
- ブラウザ(Google Chrome)
※端末の傾きをJavaScriptで取得させます。端末やブラウザによっては動かないかも知れません。
1.1 AndroidにTermuxとPythonが入ってない場合
スマホやタブレットでPythonとFlask、傾きセンサーが動く・取得できる環境があればできる(はず)。AndroidアプリならPydroid3
はFlaskをインストールできるようです。QPython3
やその他Pythonアプリは情報不足・不明。Flaskが駄目ならbottle
で。
2. 動作の仕組み、流れ
- PythonのFlaskでAndroid端末内にサーバーを起動させます。
- 用意しておいたテンプレート
index.html
を読み込みます。 - index.htmlは傾きセンサーの動作をJavaScriptで制御する
main.js
を読み込みます。 - ブラウザで
http://localhost:8888/
を開けば、画面上にAndroidの傾きに応じて動くボールが表示されます。
2.1 ブラウザの設定
2.1.1 JavaScriptとモーションセンサー
ブラウザ上でAndroid端末の傾きセンサー値をJavaScriptで取得していますので、この2つはオンにしておきます。
Chromeでの設定
- ブラウザを開く
- ブラウザの「設定⚙️」を開く
- 「サイトの設定」を開く
- 「モーションセンサー」と「JavaScript」をオンにする。
Firefoxでの設定(不明)
傾きセンサーを設定する所が見つかりません。試したがFirefoxでは動かなかった。なぜかWebページすら表示されない。😱
3. 用意するファイル(3つ)
- app.py(Flaskを起動するpyファイル)
- index.html(ブラウザ表示用)
- main.js(センサー取得用)
3.1 ディレクトリ構成
$ tree . ├── app.py ├── static/ │ └── js/ │ └── main.js ├── templates/ └── index.html 3 directories, 3 files
Flaskは、
- indexテンプレートファイルを
templates/
フォルダ内。
- js、css、imageファイル等を
- static/フォルダ内の各フォルダ内。
に入れてあげないと、どうやらファイルが読み込まれない(たぶん)。ディレクトリ構成が決まっているようなので注意します。
4. 実装
ファイルを3つ作ります。
それぞれは上記のディレクトリ構成でフォルダに保存してあげる。
4.1 app.py(Flask用)
from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') if __name__ == "__main__": app.run(debug=True, port=8888, threaded=True)
※ブラウザでlocalhostのポート8888番にアクセスすると、index.htmlが表示される。
4.2 index.html(テンプレートファイル)
app.pyと同じ階層にtemplates/
フォルダを作り、その中のこのファイルを保存する。
※このファイルはほぼ写経です。リンクは最後に貼っています。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>端末の傾きに応じてボールを動かす</title> <script src="static/js/main.js" type="text/javascript"></script> <style>*{margin:0; padding:0;}</style> </head> <body> <canvas id="canvas" width="" height=""></canvas> </body> </html>
※javascript
ファイルのパスをapp.pyからの相対でscriptタグに書いておくだけで読み込んでくれる。
4.3 main.js(傾き取得用)
app.pyと同じ階層にstatic/
フォルダを作り、更にその中にjs/
フォルダを作った中にこのファイルを保存する。
このファイルも写経です。リンクは最後に。
/* * 端末の傾きに応じてボールを動かす */ /* * 定数 */ const SCREEN_WIDTH = 480; // キャンバス幅(ピクセル) const SCREEN_HEIGHT = 480; // キャンバス高さ(ピクセル) /* * グローバル変数 */ var canvas = null; // キャンバス var g = null; // コンテキスト var vec = {x: 0, y: 0 }; // 加速度センサー値格納用 var ball = null; // 表示するボール /* * ボールクラス */ class Ball{ constructor(x, y, r){ this.x = x; // x座標 this.y = y; // y座標 this.r = r; // 半径 } draw(){ // 位置を計算 this.x += vec.x; this.y += vec.y; // 円を描画(塗りつぶし円) g.beginPath(); g.fillStyle = "orange"; g.arc(this.x, this.y, this.r, 0, Math.PI*2, false); g.fill(); }; }; /* * ゲームループ */ function mainLoop(){ // 画面クリア g.fillStyle = "#ddd"; g.fillRect(0, 0, canvas.width, canvas.height); // ボールを描く ball.draw(); // 再帰呼び出し requestAnimationFrame(mainLoop); } /* * 加速度センサーの値を取得 */ window.addEventListener("deviceorientation", function(e){ vec.x = e.gamma / 5; // x方向の移動量: そのままでは大きい為、小さくする vec.y = e.beta / 5; // y方向の移動量: 〃 }, false); /* * 起動処理 */ window.addEventListener("load", function(){ // キャンバス情報取得 canvas = document.getElementById("canvas"); g = canvas.getContext("2d"); // キャンバスサイズ設定 canvas.width = SCREEN_WIDTH; canvas.height = SCREEN_HEIGHT; // ボールを一つ生成 ball = new Ball(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, 20); // メインループ実行 mainLoop(); });
Pythonでセンサー値の取得が簡単に出来れば良いんだけどなぁ。
よし、3つのファイルがそろった。実行する\\\٩( 'ω' )و ////
5. 実行
◆実行の手順は、
- ターミナルでapp.pyを実行(
$ python app.py
) - ブラウザで
http://localhost:8888
にアクセス - 画面上でオレンジ色のボールが傾きに合わせて動けば成功
◆止める時は、
- ターミナルで
Ctrl+c
を入力するとFlaskサーバーが止まる。 - ブラウザのタブを閉じる。
- ブラウザの設定を元に戻す
- (JavaScriptとモーションセンサー)
おわりに
JavaScriptを動かすにはサーバーが要るのか要らないのか、ローカル保存のhtmlファイルでもJavaScriptを書いとけば動くと思っていたが動かない、ブラウザによっても挙動が違うようだ、何か分派みたいなのがメチャクチャいっぱいある、などなど。勉強大変なんじゃないか。
ジャイロセンサーの値をPCなどに送ればなんかのコントローラーとして使えそう。PC側でサーバー立ててやれば良いのかな。IoT的な方向で夢が拡がりそう。😆
【追記】
JavaScriptファイルに記されたボールの色を変えようとorange
とある部分を書き換えたのですが、変更が表示に反映されませんでした。再読込でも変わらない。
反映させるには、ブラウザ(Chromeのばあい)履歴の「キャッシュされた画像とファイル」を削除すれば出来ました。理由等は分かりません。
参考リンク
JavaScriptで端末の傾きを取得し表示する写経元です。勉強になります。ありがとうございます。 - JS:端末の傾きに応じてボールを動かす | 電脳産物
以上。