首页 > 其他分享 >Potree 003 基于Potree Desktop创建自定义工程

Potree 003 基于Potree Desktop创建自定义工程

时间:2023-01-15 20:11:45浏览次数:44  
标签:function dojo 自定义 js electron ._ var Potree Desktop

1、第三方js库

第三方库js库选择dojo,其官网地址为https://dojotoolkit.org/,git地址为https://github.com/dojo/dojo,demo地址为https://demos.dojotoolkit.org/demos/,如果打不开,可以多刷新几次。

截图.png

因为使用ArcGIS API for js开发,接触到了dojo,dojo是一个非常优秀的js框架库,包含的内容非常全,做单页面Web应用程序是一个非常不错的选择。

2、修改Mian.js文件

Main.js文件主要还是设置electron的一些参数,代码如下。

var electron = require("electron");
var app = electron.app;
var BrowserWindow = electron.BrowserWindow;
var path = require("path");
var Menu = electron.Menu;
var myMainWindow;
function CreateWindow() {
    // 新建主窗体,设置图标、加载主页面
    myMainWindow = new BrowserWindow({
        webPreferences: {
            nodeIntegration: true,
            backgroundThrottling: false
        },
        show: false
    });
    myMainWindow.maximize();
    myMainWindow.setIcon(path.join(__dirname, "Res/Images/Ico64.png"));
    myMainWindow.loadFile(path.join(__dirname, "Index.html"));
    myMainWindow.show();
    //把electron带的菜单隐藏
    Menu.setApplicationMenu(null);
    //屏蔽警告
    process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
    myMainWindow.on("closed", function () {
        myMainWindow = null;
    });
}
app.on("ready", CreateWindow);
// Quit when all windows are closed.
app.on("window-all-closed", function () {
    if (process.platform !== "darwin") {
        app.quit()
    }
});
app.on("activate", function () {
    if (myMainWindow === null) {
        CreateWindow()
    }
});

我们在Potree Desktop代码中的Main.js文件的基础上上做了修改。通过引用electron,得到electron、app、BrowserWindow、path、Menu等引用,并定义了CreateWindow函数。

该函数是Main.js最主要的函数,在代码中,我们创建了一个BrowserWindow窗体,并最大化该窗体。设置了窗体图标、加载的页面等。最后调用窗体的Show函数,打开窗体。BrowserWindow窗体自带了一个菜单,通过Menu.setApplicationMenu(null);隐藏electron自带的菜单。当窗体关闭的时候,设置myMainWindow变量的值为null。

后面的代码主要针对全局App,当系统环境准备好的时候,调用CreateWindow函数。当所有的窗体都关闭后,退出App。当App被激活的时候,如果myMainWindow变量为null,则调用CreateWindow函数。这些逻辑基本上都是从Potree Desktop中拷贝过来的,修改了下变量名称,逻辑未变。

代码运行Mian.js,实例化BrowserWindow窗体,加载Index.html,此时系统就进入了Index.html页面。

3、修改index.html文件

我们的目的是做一个Web单页面应用程序,样式以及操作方式要尽量能贴近普通的桌面应用程序。整体布局包括菜单栏、工具栏、左侧工程树以及中间的主显示区。

首先引用外部的js和css文件,包括dojo、Potree定义的文件以及我们系统中自己定义的一些文件,代码如下。

<link rel="stylesheet" type="text/css" href="./libs/potree/potree.css">
<link rel="stylesheet" type="text/css" href="./libs/jquery-ui/jquery-ui.min.css">
<link rel="stylesheet" type="text/css" href="./libs/openlayers3/ol.css">
<link rel="stylesheet" type="text/css" href="./libs/spectrum/spectrum.css">
<link rel="stylesheet" type="text/css" href="./libs/jstree/themes/mixed/style.css">

<link rel="stylesheet" href="Res/dojo/dijit/themes/claro/claro.css" />
<link rel="stylesheet" href="Res/dojo/dojox/grid/resources/claroGrid.css" />
<link rel="stylesheet" href="Res/dojo/dojox/form/resources/CheckedMultiSelect.css" />
<link rel="stylesheet" href="Res/dojo/dojox/form/resources/RangeSlider.css" />
<link rel="stylesheet" href="Res/dojo/dojox/widget/ColorPicker/ColorPicker.css" />

<link rel="stylesheet" href="Index.css" />
<link rel="stylesheet" href="AppUI/AppMenuUI.css" />
<link rel="stylesheet" href="AppUI/AppToolBarUI.css" />

<script>
    if (typeof module === 'object') {
        window.module = module;
        module = undefined;
    }
</script>
<script src="./libs/jquery/jquery-3.1.1.min.js"></script>
<script src="./libs/spectrum/spectrum.js"></script>
<script src="./libs/jquery-ui/jquery-ui.min.js"></script>
<script src="./libs/other/BinaryHeap.js"></script>
<script src="./libs/tween/tween.min.js"></script>
<script src="./libs/d3/d3.js"></script>
<script src="./libs/proj4/proj4.js"></script>
<script src="./libs/openlayers3/ol.js"></script>
<script src="./libs/i18next/i18next.js"></script>
<script src="./libs/jstree/jstree.js"></script>
<script src="./libs/potree/potree.js"></script>
<script src="./libs/plasio/js/laslaz.js"></script>
<script src="./libs/three.js/build/three.js"></script>
<script src="./libs/three.js/build/three.js"></script>

接下来定义对electron和Nodejs中一些功能的引用。

<script>
    var Electron = require('electron');
    var ElectronDialog = require('electron').remote.dialog;
    var NodeFS = require('fs');
    var NodePath = require('path');
    var NodeChildProcess = require('child_process');
</script>

ElectronDialog可弹出本地对话框,包括消息对话框,是否对话框等,类似于.Net中的MessageBox。NodeFS模块可对文件进行操作,类似于.Net中的File类。NodePath模块可文件路径进行操作,类似于.Net中的Path类。NodeChildProcess模块可调用本地的exe文件,并可以传入参数,捕捉输出信息等。

接下来是使用dojo库的一些配置以及Index.html页面直接引用的一些js文件。

<script>
    var dojoConfig = {
        async: true,
        parseOnLoad: false,
        //用于页面加载时立即加载的JS依赖
        deps: ["dojo/parser"],
        callback: function (parser) { },
        //加载一个模块的请求超时时间,如果超时说明加载模块失败
        waitSeconds: 10,
        //如果为true可以避免模块缓存(原理就是在请求模块的URL加上当前时间戳)
        //cacheBust: true,
    }
</script>
<script src="Res/dojo/dojo/dojo.js"></script>
<script src="Framework/URLHelper.js"></script>
<script src="Framework/DateFormat.js"></script>
<script src="Index.js"></script>

Index.html文件最后,是该页面的布局代码,如下所示。

<body class="claro">
    <table id="UI_Main_Table">
        <tr style="height:30px">
            <td padding:0">
                <div id="UI_AppMenuUI_Div"></div>
            </td>
        </tr>
        <tr style="height:30px">
            <td padding:0">
                <div id="UI_AppToolBarUI_Div"></div>
            </td>
        </tr>
        <tr>
            <td style="padding:0;">
                <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="gutters:true, liveSplitters:false" style="width: 100%; height: 100%; margin: 0; padding: 0; ">
                    <div id="UI_AppTreeUI_Div" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="minSize:20, region:'leading', splitter:true" style="width: 260px;"></div>
                    <div id="UI_Center_BorderContainer" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="region:'center'" style="width: 100%; height: 100%; margin: 0; padding: 0; ">
                        <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center',splitter:true">
                            <div class="potree_container" style="height:100%">
                                <div id="potree_render_area"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </td>
        </tr>
    </table>
</body>

我们在body中直接定义了一个Table作为根元素,该表格分三行,第一行菜单栏,第二行工具条,第三行就是主显示区。如果想在底部增加状态栏,可再增加一行。

主显示区使用了dojo中定义的dijit/layout/BorderContainer,在BorderContainer中添加了两个dijit/layout/ContentPane,其中一个ContentPane的region属性设置为leading,另外一个ContentPane的region属性设置为center,并都设置splitter=true。这样主显示区域左侧会添加一个区域,宽度为260px,剩下的为中间区域,并且两区域可左右调整大小。

我们在Index.js中添加菜单。

4、添加菜单

菜单我们使用dojo中定义的dijit/MenuBar,如果我们添加文件子菜单,html代码如下。

<div style="font-size:14px">
    <div data-dojo-type="dijit/MenuBar">
        <div data-dojo-type="dijit/PopupMenuBarItem">
            <span>文件</span>
            <div data-dojo-type="dijit/DropDownMenu" data-dojo-attach-point="UI_File_DropDownMenu"></div>
        </div>
    </div>
</div>

在js文件中,我们可以实例化一个dijit/MenuItem,添加到UI_File_DropDownMenu中。

CreateMenuItem: function () {
    var myMenuItem = new MenuItem({
        label: "打开文件",
        iconClass: "AppMenuUIMenuItemIcon FileOpenIcon"
    });
    var myThis = this;
    var myEventHander = on(myMenuItem, "click", function () {
        myThis._OnClick();
    });
    this._EventHanderArray.push(myEventHander);
    return myMenuItem;
},
//点击命令按钮执行的函数
_OnClick: function () {
    var myFilePathArray = ElectronDialog.showOpenDialogSync(null, {
        title: "选择工程文件",
        properties: ["openFile"],
        filters: [
            { name: '工程文件', extensions: ['project'] }
        ]
    });
    if (myFilePathArray == null) {
        return;
    }
    var myProject = new Project();
    myProject.Open(myFilePathArray[0]);
    this._Application.SetProject(myProject);
},

把创建的MenuItem添加到菜单栏上的代码如下。

this.UI_File_DropDownMenu.addChild(new FileNewCommand({}, this._Application).CreateMenuItem());

5、添加工具条

工具条使用dojo中定义的dijit/Toolbar,html代码定义如下。

<div>
    <div data-dojo-type="dijit/Toolbar" data-dojo-attach-point="UI_Toolbar">
        <button data-dojo-type="dijit/form/Button" data-dojo-attach-point="UI_TopView_Button"
                data-dojo-props="iconClass:'AppToolBarUIButtonIcon TopViewIcon',showLabel:false">
            上视图
        </button>
        <button data-dojo-type="dijit/form/Button" data-dojo-attach-point="UI_BottomView_Button"
                data-dojo-props="iconClass:'AppToolBarUIButtonIcon BottomViewIcon',showLabel:false">
            下视图
        </button>
        <span data-dojo-type="dijit/ToolbarSeparator"></span>
        <button data-dojo-type="dijit/form/Button" data-dojo-attach-point="UI_FullExtent_Button"
                data-dojo-props="iconClass:'AppToolBarUIButtonIcon FullExtentIcon',showLabel:false">
            全图
        </button>
    </div>
</div>

在js文件中,可以具体定义Button按钮点击后执行的函数,代码如下。

//点击全图按钮执行的函数
on(this.UI_FullExtent_Button, "click", function () {
    myThis._Application.Viewer.fitToScreen();
});

一些逻辑较为复杂的工具,我们就要单独定义了,类似于定义菜单,我们会定义一个工具按钮。我们以新建工程为例,js代码如下。

define([
    "dojo/_base/declare",
    "dojo/on",
    "dijit/MenuItem",
    "dijit/form/Button"
], function (
    declare,
    on,
    MenuItem,
    Button
) {
    return declare("ProjectNewCommand", null, {
        _Application: null,
        _EventHanderArray: null,
        //构造函数
        constructor: function (args, pApplication) {
            declare.safeMixin(this, args);
            this._Application = pApplication;
            this._EventHanderArray = [];
        },
        //创建MenuItem
        CreateMenuItem: function () {
            var myMenuItem = new MenuItem({
                label: "新建工程",
                iconClass: "AppMenuUIMenuItemIcon ProjectNewIcon"
            });
            var myThis = this;
            var myEventHander = on(myMenuItem, "click", function () {
                myThis._OnClick();
            });
            this._EventHanderArray.push(myEventHander);
            return myMenuItem;
        },
        //创建Button
        CreateButton: function () {
            var myButton = new Button({
                label: "新建工程",
                iconClass: "AppToolBarUIButtonIcon ProjectNewIcon",
                showLabel: false,
            });
            var myThis = this;
            var myEventHander = on(myButton, "click", function () {
                myThis._OnClick();
            });
            this._EventHanderArray.push(myEventHander);
            return myButton;
        },
        //点击命令按钮执行的函数
        _OnClick: function () {
            var myThis = this;
            require(["WebRoot/CoreUI/Projects/ProjectNewDialog"],
                function (Dialog) {
                    var myDialog = new Dialog({});
                    myDialog.ShowDialog();
                    myDialog.on("ProjectCreated", function (e) {
                        myThis._Application.SetProject(e.Project);
                    });
                });
        },
        //默认销毁函数
        destroy: function () {
            for (var i = 0; i < this._EventHanderArray.length; i++) {
                this._EventHanderArray[i].remove();
            }
            this._EventHanderArray = [];
        },
    });
});

代码中包含了CreateMenuItem和CreateButton函数,分别返回MenuItem和Button,点击这两个UI都是执行_OnClick函数,也就是说,我们当前定义的ProjectNewCommand.js,实例化得到ProjectNewCommand对象后,调用CreateMenuItem函数获取的按钮可以添加到菜单上,调用CreateButton函数获取的按钮可以添加到工具条上,且点击后,两个按钮的行为一致。

把按钮添加到工具栏上的代码如下。

var myProjectNewCommand = new ProjectNewCommand({}, myApplication);
myAppToolBarUI.UI_Toolbar.addChild(myProjectNewCommand.CreateButton(), 0);

6、Potree Viewer初始化

系统整体布局、菜单栏,工具条、左侧工程区域以及中间显示区域都定义好了之后,我们就要定义Viewer了。定义的时候,我们依然要参考Potree Desktop中实例化Viewer的代码,并根据实际需求修改。

var myPotreeRenderArea = document.getElementById("potree_render_area");
var myViewerArgs = {
    noDragAndDrop: true,
};
var myViewer = new Potree.Viewer(myPotreeRenderArea, myViewerArgs);
myViewer.setEDLEnabled(true);
myViewer.setFOV(60);
myViewer.setPointBudget(3 * 1000 * 1000);
myViewer.setMinNodeSize(0);
myViewer.loadSettingsFromURL();
myViewer.setDescription("");
myViewer.setControls(myViewer.earthControls);

7、系统运行效果

执行.bat文件,运行,得到的系统主界面如下图所示。

标签:function,dojo,自定义,js,electron,._,var,Potree,Desktop
From: https://www.cnblogs.com/mytudousi/p/17054022.html

相关文章

  • win10 docker desktop wsl2
    现在(2023年1月15日),在win10系统上使用docker,最好的搭配就是wsl2子系统+dockerdesktop的wsl2basedenginedockerdesktop可以在win10系统上安装,较新版本的dockerdesk......
  • 自定义异常处理
    1.MyAccessDeniedHandler类@ComponentpublicclassMyAccessDeniedHandlerimplementsAccessDeniedHandler{@Overridepublicvoidhandle(HttpServletRequ......
  • FlinkCDC的自定义反序列化
    FlinkCDC的自定义反序列化FlinkCDC的简单使用方法packagecom.pzb;importcom.ververica.cdc.connectors.mysql.MySqlSource;importcom.ververica.cdc.connectors.my......
  • flex 4.6 自定义Datagrid添加checkbox\图片等功能
    flex4.6中的 spark 的Datagrid相比于之前的mx有很大不同实现自定义<s:itemRenderer>详见代码~<s:DataGridid="dg"left="14"right="10"top="35"bottom="9"d......
  • 微信小程序自定义字体
    微信小程序自定义字体  解决方法 //加载字体wx.loadFontFace({global:true,family:'cl',......
  • python教程6--自定义函数,数据类型转换,解方程
    本文主要讲解点如下:简单函数数据类型转换空函数自定义绝对值函数自定义函数检查参数类型函数返回多个值求解ax2+bx+c=0的根具体代码如下:'函数相关'__author__='mo......
  • 自定义用户登录验证
    1.自定义用户登录验证把自带的登录逻辑改写以及界面的改写1.1UserDetailServiceImpl@ServicepublicclassUserDetailServiceImplimplementsUserDetailsService{......
  • arcgis api for 自定义zoom
    1.需求自定义UI,实现对地图的zoom操作,在view缩放的时候,带动画效果2.分析问题UI视图一般情况,可能大部分初学者会使用以下代码对zoom进行操作,这个方法是可以放大缩小,但是......
  • iisexpress 绑定自定义域名
    1、项目根目录找到    2、添加绑定域名  3、host映射  4、以管理员身份运行vs,以管理员身份运行vs,以管理员身份运行vs,重要的事情说三遍。。。不然域名无......
  • JS_6_自定义对象
    JS中万事万物皆对象,灵活! 对象:可以调用不存在的属性方法(自动扩充),值为undefined。可以直接新增属性方法。创建自定义对象://创建一个自定义对象var对象名......