矢量层
矢量层 VectorLayer
是用于在地图上显示实体的基础层。该图层是一个数据感知组件,将数据(几何对象)和地图连接起来。矢量图层支持在地图上进行简单显示、交互式编辑和绘制几何对象。
几何对象
几何对象是指具有几何属性的实体。此属性应具有包含在 io.jmix.maps.datatype
包中的特定几何数据类型之一:
数据类型 |
Java 类型 |
geoPoint |
org.locationtech.jts.geom.Point |
geoPolyline |
org.locationtech.jts.geom.LineString |
geoPolygon |
org.locationtech.jts.geom.Polygon |
通过实体设计器创建,添加一个新的属性并在下拉列表选择特定的几何类型。
打开实体源码,并添加下列注解:
-
@Geometry
- 标记该属性用于在地图中展示几何对象。几何对象必须包含一个几何属性,否则在绘制图层时会抛出异常。 -
@Convert
- 指定一个自定义的 JPA 转换器,定义这种数据类型如何进行持久化。默认情况下,扩展组件会使用 JPA 转换器将坐标转换为 WKT 格式,然后使用文本类型保存。从数据加载时,文本也会反向解析为对象。这些转换器位于 io.jmix.maps.converter.wkt
包中。
几何对象 Order
示例:
@JmixEntity
public class Order {
//...
@Geometry
@PropertyDatatype("geoPoint")
@Column(name = "LOCATION")
@JmixProperty
private Point location;
//...
}
可以看到,Order
是一个很简单的实体,其中一个属性 location
为 org.locationtech.jts.geom.Polygon
类型。
绑定几何对象至图层
通过 datacontainer
将几何对象绑定至图层。可以在 XML 中声明:
<maps:layers selectedLayer="orderLayer">
<maps:tile id="tileLayer" tileProvider="map_OpenStreetMap"/>
<maps:vector id="orderLayer" dataContainer="orderDc" editable="true"/>
</maps:layers>
id
和 dataContainer
是必需参数。矢量层可以支持 InstanceContainer
和 CollectionContainer
数据容器。
editable
参数定义图层是否可修改。
如需在矢量层编辑/绘制几何图形,需在 layers 的 selectedLayer 参数指定相应的图层。
|
另外,还支持在界面控制器创建 VectorLayer
:
@Autowired
private GeoMap map;
@Autowired
private InstanceContainer<Order> orderDc;
@Subscribe
public void onBeforeShow(BeforeShowEvent event) {
VectorLayer<Order> orderLayer = new VectorLayer<>("orderLayer", orderDc);
orderLayer.setEditable(true);
map.addLayer(orderLayer);
map.selectLayer(orderLayer);
}
设置几何图形样式
使用 setStyleProvider()
方法确定几何对象的图形样式。也可以使用 @Install
注解在界面控制器中声明式的定义该方法,示例:
@Autowired
private GeometryStyles geometryStyles;
@Install(to = "map.territoryLayer", subject = "styleProvider")
private GeometryStyle mapTerritoryLayerStyleProvider(Territory territory) {
return geometryStyles.polygon()
.setFillColor("#08a343")
.setStrokeColor("#004912")
.setFillOpacity(0.3)
.setStrokeWeight(1);
}
使用 io.jmix.mapsui.component.layer.style.GeometryStyles
bean 为不同的几何图形类型创建样式。
处理选中的几何对象
几何对象可以通过用户点击或者通过关联的数据容器自动选中。如果 VectorLayer
设置为活动图层,则用户可以通过点击选取几何对象。
setSelectedGeoObject()
方法设置图层中选中的几何对象。例如,如果实体在编辑界面打开,则会自动在对应的矢量层中选中。
VectorLayer
订阅了数据容器变更事件,当数据容器中新增或删除数据时,会自动刷新。
选中几何对象时,会产生 GeoObjectSelectedEvent
事件。可以在界面控制器中订阅该事件,例如,在表格中选中几何对象:
@Autowired
private GroupTable<Order> ordersTable;
@Subscribe("map.orderLayer")
public void onMapOrderLayerGeoObjectSelected(VectorLayer.GeoObjectSelectedEvent<Order> event) {
ordersTable.setSelected(event.getItem());
}
聚合
对于由几何点构成的矢量图层,可以将一些靠近的点划分为一个聚合点,在某些缩放级别将多个点显示为一个点:
如需使用聚合,需要在 XML 的 vector
元素内添加 cluster
元素:
<maps:layers>
<maps:tile id="tiles" tileProvider="sample_CartoTileProvider"/>
<maps:vector id="orders" dataContainer="ordersDc">
<maps:cluster/>
</maps:vector>
</maps:layers>
你还可以配置一些聚合的属性:
-
radius
- 聚合能覆盖的最大半径,以像素为单位,默认80
。 -
weightProperty
- 如果指定,则图层中每个点都会有一个权重值(int),由几何对象的权重属性定义。该值用于计算聚合中点值的总和(默认情况下,总和为点的数量)。 -
showCoverage
- 当鼠标悬停于聚合点时,显示其覆盖的范围。 -
disableAtZoom
- 指定一个缩放级别,从该级别开始不显示聚合点。 -
showSinglePointAsCluster
- 将单一点也显示为大小为 1 的聚合点。
几何对象底层的 Vaadin 组件
对地图中展示的每个几何对象,扩展组件都会创建一个 io.jmix.mapsui.component.leaflet.translators.GeoObjectWrapper
类的实例,其中包含底层的 Vaadin 组件。这个类提供与其包装的组件直接交互的方法:
-
openPopup()
- 如果指定弹窗内容,则打开几何对象的弹窗。 -
closePopup()
- 关闭几何对象的弹窗。 -
openTooltip()
- 如果指定提示窗内容,则打开几何对象的提示窗。 -
closeTooltip()
- 关闭几何对象的提示窗。 -
getLeafletComponent()
- 返回客户端层展示的小树叶组件底层的 Vaadin 组件。
如需获取矢量层的几何对象包装器,可以调用 GeoMapImpl
类(实现了 GeoMap
)的 getGeoObjectWrappersMap()
方法,并将矢量层传递给该方法:
VectorLayer<Order> ordersLayer = map.getLayer("orderLayer");
Map<?, GeoObjectWrapper<Order>> geoObjectWrappersMap =
((GeoMapImpl) map).getGeoObjectWrappersMap(ordersLayer);
返回的键值对中的 key 为几何对象的 ID(或几何对象本身,如果 ID = null),value 为对应的 GeoObjectWrapper
实例。因此,可以用下面的方式获取特定几何对象的 GeoObjectWrapper
。
@Autowired
private GroupTable<Order> ordersTable;
@Subscribe("map.orderLayer")
public void onMapOrderLayerGeoObjectSelected(VectorLayer.GeoObjectSelectedEvent<Order> event) {
ordersTable.setSelected(event.getItem());
GeoObjectWrapper<Order> geoObjectWrapper = geoObjectWrappersMap.get(event.getItem().getId());
if (geoObjectWrapper != null) {
geoObjectWrapper.openPopup();
}
}
如果几何对象的几何值是 null,则该几何对象没有 GeoObjectWrapper 。
|
另外,当刷新图层时,GeoObjectWrapper
实例可能会发生改变或被替换。因此每次都需要用这个键值对获取相关的包装类实例。