要素图层性能提升
本示例演示了如何启用 FeatureLayer 的 WebGL 渲染,以实现在 MapView 中显示 180,000 多个要素。默认情况下,FeatureLayer 是 SVG (使用可缩放矢量图形)渲染的,这种方式限制了视图中可以显示的要素的数量。使用 WebGL 渲染的 FeatureLayers 克服了这一限制,允许用户在浏览器中显示数十万甚至数百万个要素。
这个程序中启用 WebGL 的关键代码是:
var dojoConfig = {
has: {
"esri-featurelayer-webgl": 1
}
};
在 ArcGIS API for JavaScript 4.5 中,FeatureLayer 的 WebGL 渲染还处于测试阶段。要了解更多关于使用 FeatureLayer 渲染大型数据集的信息,请查看 https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#webgl-rendering 。
VectorGileLayer 已经利用 WebGL 在浏览器中显示大量的数据。虽然 VectorTileLayer 可用于显示类似于此示例中的可视化的专题数据,但是数据必须在发布时进行 cook,而 FeatureLayer 不必经过 cook 过程。FeatureLayer 也更加动态,它可以使用 definitionExpression 进行过滤、查询以及在 Legend 中引用。其渲染器也能更新到一个动态的改变,能被底层数据驱动。
要改变实例中的数据视图,请选择 LayerList 小部件中的选项,将会基于渲染器指定的字段或表达式来重新绘制图层。
程序完整源代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>FeatureLayer performance improvements [beta] - 4.5</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.5/esri/css/main.css">
<script>
var dojoConfig = {
has: {
"esri-featurelayer-webgl": 1
}
};
</script>
<script src="https://js.arcgis.com/4.5/"></script>
<script>
require([
"esri/WebMap",
"esri/views/MapView",
"esri/widgets/Legend",
"esri/widgets/LayerList",
"dojo/domReady!"
], function(WebMap, MapView, Legend, LayerList) {
// 这个网络地图包含一个要素图层。
// Dojo在前面的脚本中设置了标志,允许在WebGL中渲染该图层,从而提高了具有大量数据的图层的性能。 该图层包含18万个多边形。
var map = new WebMap({
portalItem: {
id: "294d8df2be3d40149874c6f5542da8e6"
}
});
var view = new MapView({
container: "viewDiv"
});
var rendererInfos;
var currentInfo;
map.load()
.then(function() {
// 加载地图之后,将每个图层的渲染器保存到 rendererInfos 对象。
// 当点击给定标题的动作时,这些渲染器将被应用到图层。
rendererInfos = map.layers.map(function(layer) {
return {
renderer: layer.renderer.clone(),
title: layer.title
};
});
currentInfo = rendererInfos.getItemAt(0);
var visibleLayer = map.layers.find(function(layer) {
layer.title = map.portalItem.title;
return layer.visible;
});
// 在将地图添加到视图之前,只保留一个图层(可见的)
map.layers.removeAll();
map.layers.add(visibleLayer);
view.map = map;
return view;
}).then(addWidgets);
// 添加 LayList 和 Legend 组件到视图
function addWidgets(view) {
view.ui.add(new Legend({
view: view
}), "bottom-left");
var layerList = new LayerList({
view: view,
// 每次更新相关图层视图时,都会为每次激发的 LayerList 小部件分配一个函数。
// 这个函数必须返回一个动作对象的二维集合
listItemCreatedFunction: createLayerListActions
});
view.ui.add(layerList, "top-right");
// 当单击 “图层列表” 中的任何选项时
// 将触发 trigger-action 事件并执行toggleRenderer() 回调
layerList.on("trigger-action", toggleRenderer);
}
function createLayerListActions(event) {
var listItem = event.item;
if (listItem.title === map.portalItem.title) {
listItem.actionsOpen = true;
listItem.actionsSections = [rendererInfos.map(function(
rendererInfo) {
return {
title: rendererInfo.title,
className: "esri-icon-maps",
id: "change-renderer"
};
}).toArray()];
}
}
function toggleRenderer(event) {
if (event.action.id === "change-renderer") {
var matchingInfo = rendererInfos.find(function(info) {
return info.title === event.action.title;
});
if (matchingInfo.title === currentInfo.title) {
return;
} else {
currentInfo = matchingInfo;
}
var renderer = matchingInfo.renderer;
var layer = view.map.layers.getItemAt(0);
layer.renderer = renderer;
}
}
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
程序运行效果:
(完)