2018年7月11日水曜日

外部 JavaScript のモジュール化

外部 JavaScript をモジュール化するとファイルパスではなくモジュールとしてインポートできます。
${HOME}/src/qt/examples/qml/javascript/module/
 +-- lib/
 |   +-- jsmodule/
 |   |   +-- qmldir
 |   |   +-- utils.js
 +-- use-jsmodule.qml
モジュール化する外部 JavaScript ファイルを上記のように配置して、qmldir ファイルに以下のように記述します。
qmldir:

Utils 1.0 utils.js
Utils は外部 JavaScript ファイル内の関数や変数、定数を参照するときに指定するプリフィック名で、1.0 はモジュールのバージョン番号 (メジャー.マイナー) です。
utils.js:

.pragma library

function colorName(color) {
    function formatElement(e) {
        return ("00" + Math.round(255*e).toString(16)).slice(-2);
    }

    const r = formatElement(color.r);
    const g = formatElement(color.g);
    const b = formatElement(color.b);
    const a = formatElement(color.a);

    return `#${a}${r}${g}${b}`
}

// Typical mono space font on each platform.
// const monoFont = function() { // Qt 5.11
var monoFont = function() {      // Qt 5.12 regression
    if (Qt.platform.os == "linux") {
        return Qt.font({ family: "DejaVuSansMono" });
    } else if (Qt.platform.os == "windows") {
        return Qt.font({ family: "Lucida Console" });
    } else if (Qt.platform.os == "osx") {
        return Qt.font({ family: "Osaka", styleName: "Regular-Mono" });
    } else {
        return Qt.font({ family: "Lucida Console" });
    }
}();

// Returns a gray for the specified color. Same as qGray() in Qt C++.
function grayFor(color) {
    return ((255*color.r*11 + 255*color.g*16 + 255*color.b*5)/32)/255;
}

// Retruns a contrast gray color for background to clearly display text.
function textColorFor(aBackgroundColor) {
    return grayFor(aBackgroundColor) > 0.5 ? "black" : "white";
}
上記のような外部 JavaScript ファイルを用意したときに、以下のようにしてモジュール化した JavaScript を使えます。
use-jsmodule.qml:

import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.12
import lib.jsmodule 1.0

ApplicationWindow {
    visible: true

    minimumWidth: 300
    minimumHeight: 300

    title: "JavaScript Module"

    Rectangle {
        width: 200
        height: 200
        anchors.centerIn: parent

        radius: 5
        color: Qt.rgba(Math.random(), Math.random(), Math.random())

        Text {
            anchors.centerIn: parent

            text: Utils.colorName(parent.color)
            font {
                family: Utils.monoFont
                pointSize: 32
            }
            color: Utils.textColorFor(parent.color)
        }
    }
}
JavaScript モジュールの import 文には、インポートパス以下の外部 JavaScript ファイルのパスをピリオドで区切って指定します。1.0 は qmldir に記述したバージョン番号です。実行するにはインポートパスを指定して以下のようにします。
$ qml -I ${HOME}/src/qt/examples/qml/javascript/module use-jsmodule.qml

参考情報

Module Definition qmldir Files