Pyodide Python APIからのJavaScript関数実行

Web PyxelでJavaScriptの自作関数を呼び出す

 前回記事「Web PyxelからのJavaScript呼び出し - 勉強ボックス管理者ブログ」の続きです。今回は自分で定義したJavaScriptの関数を,PyxelのPythonコードから実行する例です。

 参考サイト Python API — Version 0.22.1

  You can import these modules using the Python import statement in the normal way.
  js   The global JavaScript scope.

 jsをインポートすればdocumentに限らずJavaScriptグローバル変数にアクセスできるようですので,やってみましょう。

 

JavaScript関数の呼び出し

 HTMLファイルに自作の関数を定義します。またvar定義でグローバル変数も用意して値を参照できるか確かめます。

HTMLファイル例

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Calling JavaScript functions from pyxel</title>
    <style>
        #msg{
            position: absolute;
            top: 5px;
            left: 5px;
            border: solid 1px #eeeeee;
            width: 10rem;
            color: #aaa;
            background: black
        }
    </style>

    <script>
    var jsval = "Good!"
    let cnt = 0
    function myfunc(aStr){
        document.getElementById("msg").innerText = "I am JavaScript " + aStr;
        return cnt++;
    }
    </script>
</head>
<body>

    <script src="https://cdn.jsdelivr.net/gh/kitao/pyxel/wasm/pyxel.js"></script>
    <pyxel-run  root="." name="functest.py"></pyxel-run>


    <div id="msg">This is a html.</div>
</body>
</html>

・scriptタグでグローバル変数 jsval と,関数 myfunc() を定義しました。myfunc()は引数の文字列も加えてdiv要素のテキストを書き換えます。

functest.py

from js import myfunc,jsval
import pyxel

pyxel.init(240,160)
pyxel.mouse(True)
val = "no data"
ret = "nothing"
def update():
    global val,ret
    if pyxel.btnp(pyxel.MOUSE_BUTTON_LEFT):
        ret = myfunc("from Pyxel!")
        val = jsval

    return

def draw():
    pyxel.cls(1)
    pyxel.text(40,40, "Click to test.",7)
    pyxel.text(40,50, "ret = "+str(ret),7)
    pyxel.text(40,60, "val = "+str(val),7)
    return

pyxel.run(update,draw)

Pythonのfrom節でmyfunc,jsvalをインポートします。関数の戻り値もPython側で表示してみます。

Webサーバーに配置して実行

 ↓画面クリックでdiv要素のテキストが変更されました。myfunc()の戻り値とjsvalの値も取得できています。

 ↓もう一度クリックして,戻り値がインクリメントされていることを確認。

 
 ブラウザでのデモ
 http://benkyoubox.starfree.jp/100_game/10_pyxel/JStest/functest.html

  

音楽ファイルの再生

 JavaScriptの処理で音楽ファイルを再生させてみます。

HTMLファイルの例

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Calling JavaScript functions from pyxel</title>

    <style>
        #msg{
            position: absolute;
            top: 5px;
            left: 5px;
            border: solid 1px #eeeeee;
            color: #aaa;
            background: black
        }
    </style>

    <script>
    function playbgm(aFlg){
        obj = document.getElementById("bgm");
        if(1 == aFlg){
            obj.play()
        }else{
            obj.pause();
            obj.currentTime = 0;
        }
        return;
    }
    </script>
</head>
<body>
    <audio id="bgm"><source src="MusMus-BGM-097.mp3" type="audio/mpeg"></audio>
    
    <script src="https://cdn.jsdelivr.net/gh/kitao/pyxel/wasm/pyxel.js"></script>
    <pyxel-run  root="." name="bgmtest.py"></pyxel-run>


    <div id="msg">BGM: フリーBGM・音楽素材MusMus https://musmus.main.jp</div>
</body>
</html>

・audioタグで読み込んだmp3ファイルを,関数playbgm()内で再生と停止を行うように準備しました。

from js import playbgm
import pyxel

pyxel.init(240,160)
pyxel.mouse(True)
flg = 1
def update():
    global flg
    if pyxel.btnp(pyxel.MOUSE_BUTTON_LEFT):
        playbgm(flg)
        flg = 1 - flg

    return

def draw():
    pyxel.cls(1)
    if 1 == flg:
        pyxel.text(40,40, "Click to start.",7)
    else:
        pyxel.text(40,40, "Click to stop.",7)

    return

pyxel.run(update,draw)

・インポートするものをplaybgmに変えて,クリックのたびに切り替わるようにしました。

 ブラウザでのデモ
 http://benkyoubox.starfree.jp/100_game/10_pyxel/JStest/bgmtest.html

 

効果音と音楽ファイル同時再生

 音楽ファイル再生中に,Pyxelの効果音再生を動かしてみます。

HTMLファイルの例

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Calling JavaScript functions from pyxel</title>

    <style>
        #msg{
            position: absolute;
            top: 5px;
            left: 5px;
            border: solid 1px #eeeeee;
            color: #aaa;
            background: black
        }
    </style>

    <script>
    function playbgm(aFlg){
        obj = document.getElementById("bgm");
        if(1 == aFlg){
            obj.play()
        }else{
            obj.pause();
            obj.currentTime = 0;
        }
        return;
    }
    </script>
</head>
<body>
    <audio id="bgm"><source src="MusMus-BGM-097.mp3" type="audio/mpeg"></audio>
    <script src="https://cdn.jsdelivr.net/gh/kitao/pyxel/wasm/pyxel.js"></script>

<pyxel-run  script='
from js import playbgm
import pyxel

pyxel.init(240,160)
pyxel.mouse(True)
pyxel.sound(0).set("a3a2c1a1", "p", "7", "s", 5)
flg = 1
def update():
    global flg
    if pyxel.btnp(pyxel.MOUSE_BUTTON_LEFT):
        playbgm(flg)
        flg = 1 - flg
    if pyxel.btnp(pyxel.KEY_SPACE):
        pyxel.play(0, 0)
    return

def draw():
    pyxel.cls(1)
    if 1 == flg:
        pyxel.text(40,40, "Click to start.",7)
    else:
        pyxel.text(40,40, "Click to stop.",7)

    pyxel.text(40,80, "[SPACE] SE",7)
    return

pyxel.run(update,draw)
'></pyxel-run>

    <div id="msg">BGM: フリーBGM・音楽素材MusMus https://musmus.main.jp</div>
</body>
</html>

・Pyxelカスタムタグ(pyxel-run)の中にPythonコードを直接記述する形式でやってみました。この場合はWebサーバーに配置せずにローカルで直接HTMLファイルを開いて実行できます。
Pythonコードでダブルクォーテーションを使っているので全体はシングルクォーテーションで囲んでいます。

 
 Webブラウザでのデモ(クリックでBGM再生開始,スペースキーを押すと効果音再生)
 http://benkyoubox.starfree.jp/100_game/10_pyxel/JStest/bgmtest2.html

 

関連記事

kinutani.hateblo.jp