如何在QML中使用JavaScript库

3

我在5.12.2版本的QML中使用一些JavaScript库,其中一些类似于Proj4JS。但是当我在QML中使用geographiclib.js库时,会出现错误。如何将JavaScript库导入到QML中?

main.qml:

import QtQuick 2.12
import QtQuick.Window 2.12
import "geographiclib.js" as MyGeo
Window {
    visible: true
    width: 640
    height: 480
    Component.onCompleted: {
        var Geodesic = MyGeo.GeographicLib.Geodesic,
            DMS = MyGeo.GeographicLib.DMS,
            geod = Geodesic.WGS84;
        var r = geod.Inverse(23, 22, 44, 29);
        console.log("distance is: ", r.s12.toFixed(3) + " m")
    }
}

错误:
qrc:/geographiclib.js:3081: ReferenceError: window is not defined
qrc:/main.qml:9: TypeError: Cannot read property 'Geodesic' of undefined

你把.js文件放在哪里了(运行时)?我认为它应该作为.qrc资源附加。 - Amfasis
js文件在qrc中:<file>main.qml</file><file>geographiclib.js</file> - Edip Ahmet
2个回答

3

最简单的方法是在全局范围内提供GeographicLib:

geographiclib.js文件结尾处更改:

window.GeographicLib = geo;

to

this.GeographicLib = geo;

然后你就可以直接使用:

main.qml:

import QtQuick 2.12
import QtQuick.Window 2.12
import "geographiclib.js" as ThenItWillBeAvailableGlobally
Window {
    visible: true
    width: 640
    height: 480
    Component.onCompleted: {
        var Geodesic = GeographicLib.Geodesic,
            DMS = GeographicLib.DMS,
            geod = Geodesic.WGS84;
        var r = geod.Inverse(23, 22, 44, 29);
        console.log("distance is: ", JSON.stringify(r))
    }
}

导致:
qml: distance is:  {"lat1":23,"lat2":44,"lon1":22,"lon2":29,"a12":21.754466225665134,"s12":2416081.7576307985,"azi1":13.736139413215236,"azi2":17.669059640534535}

如果您不想更改geographiclib.js文件,您可以添加一个全局的window对象,例如:

window.js:

this.window = this;

然后使用:

import QtQuick 2.12
import QtQuick.Window 2.12
import "window.js" as ThenWindowWillBeAvailableGlobally
import "geographiclib.js" as ThenGeographicLibWillBeAvailableGlobally
Window {
    visible: true
    width: 640
    height: 480
    Component.onCompleted: {
        var Geodesic = GeographicLib.Geodesic,
            DMS = GeographicLib.DMS,
            geod = Geodesic.WGS84;
        var r = geod.Inverse(23, 22, 44, 29);
        console.log("distance is: ", JSON.stringify(r))
    }
}

如果您不想添加任何全局变量,但是愿意编辑geographiclib.js文件,那么您可以将第68行移到文件顶部:
var GeographicLib = {};
/*
 * Geodesic routines from GeographicLib translated to JavaScript.  See
 * https://geographiclib.sourceforge.io/html/js/

并在文件末尾进行更改

  } else {
    /******** otherwise just pollute our global namespace ********/
    window.GeographicLib = geo;
  }
});

to

  } else if (typeof window === 'object') {
    /******** otherwise just pollute our global namespace ********/
    window.GeographicLib = geo;
  }
});

然后你的main.qml就能正常工作了。


谢谢你的精彩回答!如果我继续使用带有QML的npm包,我就不需要开始React Native :) 我希望Qt公司能够添加关于这个的详细文档。顺便说一下,我在输入距离时犯了错误,应该是“距离为:r.s12”。 - Edip Ahmet

1
你已经正确地导入了javascript文件。
来自doc

QML提供了一个JavaScript主机环境,专门用于编写QML应用程序。该环境与浏览器或服务器端JavaScript环境(例如Node.js)提供的主机环境不同。例如,QML不提供窗口对象或DOM API,这在浏览器环境中很常见。


我认为在5.12.2版本中支持Ecmascript 7后,QML可能会接受window对象。JavaScript库包含window对象。不幸的是,我不知道如何将JavaScript库适配到QML中。我尝试了像Qmljsfy这样的库(一个将npm包转换为QML JavaScript文件的qml模块),但它没有起作用。 - Edip Ahmet
谢谢。我没有收到窗口错误,但是我收到了“TypeError:无法读取未定义的属性'Geodesic'” - Edip Ahmet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接