mars3d关于Widget方式开发有如下说明:
我们通过vscode打开该项目,项目中最重要的是2个点是,json配置文件 和 widget模块化开发,一般开发项目只用修改配置文件和开发新的widget即可。
config/config.json是地图初始化构造参数配置文件
config/widget.json为项目widget的模块配置信息文件
widgets目录为模块功能目录,也可以按业务分在多个目录中,比如widgetsTS目录
CenterXY是mars3d开放的2个widget的一个,
而完整版的mars3d的widget有很多,不止“坐标定位“和”视角书签”2个,还包括漫游等其它widget,如下图所示:
一、mars3d关于Widget如何开发进行简要的说明:
3. widget初始化及管理
目前平台示例和项目中使用到的widget.json (opens new window) 是静态json文件方式 文件中配置参数与mars3d.widget.init方法API (opens new window)的方法参数是完成相同一致的,代码中加载json后传入到init方法中。
widget初始化方法:
//初始化widget管理器
mars3d.widget.init(map, widgetCfg, './') //tip: 第3个参数支持定义widget目录的相对路径。
# 3.1 widget的管理
在外部调用widget功能,都是通过mars3d.widget静态类 (opens new window)来统一管理的,更多方法可以参阅该类的API文档。
比如激活widet:在需要外部使用的地方通过 mars3d.widget.activate(参数 (opens new window)) 来激活widget模块, 参数支持多种模式可多样化兼容使用, 比如:
//常用,直接使用uri
mars3d.widget.activate("widgets/bookmark/widget.js");
//支持所有可配参数和自定义参数,在widget.js内部通过this.config可获取传入的参数
mars3d.widget.activate({name:"书签", uri: "widgets/bookmark/widget.js "});
# 4. 单个widget模块组成
每个widget模块必须存在 widget.js 文件,该文件内部定义了一个继承了 BaseWidget类 (opens new window)的子类。
类内最重要的几个属性和方法如下:
分类 名称 功能
get属性 resources 需要预先加载到主页面的js、css资源文件
get属性 view 存在弹窗或界面时配置,具体详见后节说明
内部变量 config 对应widget定义的或传入的配置信息
内部变量 path 当前widget所在目录的相对于网页的路径
内部变量 map 当前Map地图对象
方法 create 插件初始化触发,仅执行1次
方法 winCreateOK view属性定义的界面每次初始化后调用
方法 activate 打开激活插件 触发
方法 disable 关闭释放插件 触发
# 4.1 view属性
默认每个插件是无界面或弹窗的, 如果需要有对应的弹窗或界面(如弹窗、输入栏、菜单等)请定义view属性。
请参考贝widgets\_example*命名的示例widget来新建widget模块,建议直接复制后改下目录名称即可。
view配置中必须存在2个属性:type标识类型,url为html地址。 目前view有下面3种模式供使用:
type属性 功能 对应的示例 说明
window iframe模式弹窗 _example 独立的html子页面,比较自由,简单粗暴、无任何限制;可以每个页面用不同的UI和第三方插件不用考虑冲突问题;任何水平的开发人员均容易快速开发。
divwindow div元素模式弹窗 _example_divwin 可直接互相访问,这种模式弊端是易引起模块间id命名冲突,在css和html中命名时需注意。
append 任意html元素 _example_append 任意div节点,比较自由.
# window时:
view.html页面(或引入的view.js中)必须定义一个initWidgetView方法,框架会自动调用进行传入当前widget对象,用于页面中调用widget中的方法属性。 可以配置windowOptions参数来定义弹窗的大小、位置等。
get view() {
return {
type: 'window',
url: 'view.html',
windowOptions: { width: 250 },
}
}
# divwindow时:
此模式不用单独的js, view界面相关js逻辑全部写在widget.js中 同样支持windowOptions参数配置。
get view() {
return {
type: 'divwindow',
url: 'view.html',
windowOptions: { width: 210, height: 210 },
}
}
# append时:
将view的html直接添加至主页面中指定id的DOM节点下,通过parent属性配置指定,默认是body。
get view() {
return { type: 'append', url: 'view.html', parent: '#centerDiv' }
}
# 4.2 widget被激活后执行流程
widget激活后页面执行流程:
引入加载widget.js到index.html页面上
(如果有resources配置)引入加载resources资源到index.html页面上
(如果有view配置)打开view弹窗或构造view界面
widget激活后执行方法顺序: create => winCreateOK => activate => view中的 initWidgetView
# 4.3 测试开发好的widget
当还没有菜单时,需要测试widget功能,可以2种方式:
一是在url中传入widget参数方式激活对应widget来测试.比如:
http://mars3d.cn/project/jcxm/index.html?widget=widgets/plot/widget.js (opens new window)
二是在widget.json中可以加配置"debugger": true, 打开 widget测试栏 功能,方便测试及触发激活widget,发布的正式版本记得改回 false 或删除。
4.4 不同widget之间的通信交互示例(暂时用不到)
二、下面以CenterXY来说明Widget的运行机制
先看view.css文件,样式文件
.centerXY {
padding: 5px;
}
//class=centerXY的元素是padding(元素内容与元素边框的距离)
.centerXY .input-group {
width: 100%;
padding-top: 5px;
}
//class=centerXY的元素内的class=input-group的所有元素,width为元素内容的宽度,元素内容距元素上边框的距离为5px
这个干说,不好理解,看下面的view.html文件就明白了
再看view.html文件,
HTML的文档document页面是一切的基础,没有它dom(DOM就是文档对象模型)就无从谈起。当创建好一个页面并加载到浏览器时,DOM就悄然而生,它会把网页文档转换为一个文档对象,主要功能是处理网页内容。在这个文档对象里,所有的元素呈现出一种层次结构,就是说除了顶级元素html外,其他所有元素都被包含在另外的元素中。那么可以说,html文件是DOM的容器,我们所有的操作都是基于DOM节点进行操作,比如body、div等元素。
<div class="centerXY">
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">经度</span>
<input type="number" id="point_jd" class="form-control" value="0" placeholder="请输入经度数值0-180" aria-describedby="basic-addon1" />
</div>
<div class="input-group">
<span class="input-group-addon" id="basic-addon2">纬度</span>
<input type="number" id="point_wd" class="form-control" value="0" placeholder="请输入纬度数值0-90" aria-describedby="basic-addon2" />
</div>
<div class="input-group">
<span class="input-group-addon" id="basic-addon2">高度</span>
<input type="number" id="point_height" class="form-control" value="0" placeholder="请输入高度值" aria-describedby="basic-addon2" />
</div>
<div class="input-group text-right">
<input id="btnCenterXY" type="button" class="btn btn-primary" value="确定" />
</div>
</div>
;(function (window, mars3d) {
//创建widget类,需要继承BaseWidget
class MyWidget extends mars3d.widget.BaseWidget {
//外部资源配置
get resources() {
return ['view.css']
}
//弹窗配置
get view() {
return {
type: 'divwindow',
url: 'view.html',
windowOptions: {
width: 210,
height: 210,
},
}
}
//每个窗口创建完成后调用
winCreateOK(opt, result) {
var point = this.map.getCenter()
this.showInputView(point)
$('#btnCenterXY').click(() => {
var jd = $('#point_jd').val()
var wd = $('#point_wd').val()
var height = $('#point_height').val()
let point = new mars3d.LatLngPoint(Number(jd), Number(wd), Number(height))
this.updateMarker(point, true)
})
}
//激活插件
activate() {
//单击地图事件
this.map.on(mars3d.EventType.click, this.onMapClick, this)
}
//释放插件
disable() {
//释放单击地图事件
this.map.off(mars3d.EventType.click, this.onMapClick, this)
if (this.graphic) {
this.map.graphicLayer.removeGraphic(this.graphic, true)
this.graphic = null
}
}
onMapClick(event) {
var cartesian = event.cartesian
if (cartesian) {
var point = mars3d.LatLngPoint.fromCartesian(cartesian)
this.updateMarker(point)
this.showInputView(point)
}
}
updateMarker(position, iscenter) {
if (this.graphic) {
this.graphic.position = position
} else {
this.graphic = new mars3d.graphic.BillboardEntity({
position: position,
style: {
image: this.path + 'img/marker.png',
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // default: CENTER
scale: 0.6,
},
})
this.map.graphicLayer.addGraphic(this.graphic)
}
if (iscenter) {
this.map.flyToGraphic(this.graphic, { radius: 2000 })
}
}
showInputView(xy) {
$('#point_jd').val(xy.lng.toFixed(6))
$('#point_wd').val(xy.lat.toFixed(6))
$('#point_height').val(xy.alt.toFixed(1))
}
}
//注册到widget管理器中。
mars3d.widget.bindClass(MyWidget)
//每个widet之间都是直接引入到index.html中,会存在彼此命名冲突,所以闭包处理下。
})(window, mars3d)
widget.js是一个带参数的自调用函数,前面的分号,是防止代码压缩在一行的时候出现错误;这个函数按照如下顺序执行:
1、get resources获取样式文件css
getview获取centerxy的窗口文件
就会创建如下一个定位小窗口
2、winCreateOK窗口创建以后,调用的函数,函数的主要内容是:
获取当前三维视图的中心坐标;
将坐标显示在对应的文本框内
函数还定义一个“确定”按钮的方法:
将文本框的坐标传给point,并point处更新定位标注
3、在地图中点击
先激活,意思就是如果要在地图上单击一下,想要获得自己想要的结果,必须先激活即将定位插件挂到map中,
并实现OnMapClick方法,OnMapClick的功能:
先获取鼠标单击处的坐标,(1)在此处更新标注,updatemarker;(2)将坐标写入到定位小窗口中对应的文本框内,showinputview
函数的末尾是updatemarker和showinputview的方法实现。
可以先找一个简单的功能比如空间量算,来尝试一下widget的开发。