修改Arcgis for js源码使WMSLayer.js支持cql_filter

背景

由于项目的地图服务要迁移到国产操作系统上,以前用Arcgis发布的地图服务都要改用geoserver重新发布。由此产生了一系列的问题,这里主要记录一下arcgis for js加载WMS服务时需要对多个子图层进行过滤的解决方法。
arcgis for js 的版本是 4.20

单一的WMS服务

如果你的WMS服务只有一个,没有子图层,那你可以直接使用WMSLayer中customLayerParameters的属性,在其中定义“cql_filter”来实现过滤效果,具体用法见arcgis官网

基本原理

事实上在项目中单一的地图服务很少见,不过我们还是要先从单一的WMS服务中看看带过滤的请求发出来时是什么样的。我们可以先通过geoserver中图层预览功能设置过滤条件,查看具体的请求参数
在这里插入图片描述

在这里插入图片描述
在这个请求里与过滤有关的两个参数分别是LAYERSCQL_FILTER,通过LAYERS指定加载图层,通过CQL_FILTER指定过滤条件,最终实现了对单一图层的过滤。
而当我们要加载多个子图层是请求就会变成下面这样
在这里插入图片描述
不设置过滤条件的话服务也是可以正常加载的
在这里插入图片描述

这个时候如果我们添加过滤条件
在这里插入图片描述
会看到geoserver报错 Layers and filters are mismatched, you need to provide one filter for each layer
在这里插入图片描述
通过查看geoserver的官方文档可以看到,在多layer时要给每个layer分别设置cql_fliter并以;隔开。
那如果某一部分图层不需要过滤呢?那也得设置,就设置成1=1吧,重点是过滤条件的顺序要和LAYERS中的顺序相同,不要搞乱。
我们对三个子图层分别设置了过滤条件,如下
在这里插入图片描述
在这里插入图片描述

ok,服务可以加载出来并对指定图层完成了过滤。
基本原理搞清了,下面就搞起来,让arcgis的WMSLayer支持cql_filter。

WMSSubLayer.js

在开始之前,让我们先看看arcgis是怎么如何加载WMS服务的,这是官网的代码

// Typical usage
let layer = new WMSLayer({
  url: // url to the service,
  sublayers: [{
    name: // name of the sublayer,
    legendUrl: // url to the legend
  }]
});

这里的sublayers就是我们要加载的子图层,它对应的类是WMSSublayer,遗憾的是在WMSSublayer的文档中并没有找到类似于customParameterscustomLayerParameters的属性,不然就可以直接拿来用了。
既然没有那就自己动手。多图层过滤,我们又要保证过滤条件的顺序与请求中LAYERS顺序相同,以我的直觉还是把过滤条件放在子图层中设置更好,让我们最终能这样用

// Typical usage
let layer = new WMSLayer({
  url: // url to the service,
  sublayers: [{
    name: // name of the sublayer,
    cqlFilter: //过滤条件1
    legendUrl: // url to the legend
  }{
    name: // name of the sublayer,
    cqlFilter: //过滤条件2
    legendUrl: // url to the legend
  }{
    name: // name of the sublayer,
    legendUrl: // url to the legend
  }]
});

我们首先要修改WMSSubLayer.js使它支持我们新增的属性cqlFilter
让我们找到WMSSubLayer.js的源码,格式化一下,并增加下面这些代码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ok,搞定。WMSSubLayer的对象已经拥有cqlFilter这个属性啦。

WMSLayer.js

接下来,我们就要修改WMSLayer的代码,请求毕竟还是从他这发出来的。
还是一样,找到WMSLayer.js的源码,格式化一下方便修改。
debug一下可以看到,请求是从fetchImage这个方法发出来的
在这里插入图片描述
而这个方法里,看名字都能看出来_mixCustomParameters就是我们要修改的最终目标。
废话不多说,直接上代码,首先要先增加一个mixSubLayersCqlFilter方法,用来整理所有子图层的cqlFilter参数。

function mixSubLayersCqlFilter(sublayers) {
    if (!sublayers || !sublayers.length) return null;
    const m = {};
    for (let i = 0; i < sublayers.length; i++) {
        let l = sublayers[i];
        if (l.cqlFilter)
            m[l.name] = l.cqlFilter;
    }
    return m;
}

接着就要在请求中增加cql_filter来达到我们多图层过滤的目的,将_mixCustomParameters方法改成这样

h._mixCustomParameters = function (b) {
	let mp = mixSubLayersCqlFilter(this.allSublayers.items);
	if (!this.customLayerParameters && !this.customParameters && !mp) return b;
	let ls = b.layers.split(",");
	let cqlFilters = [];
	for (let i = 0; i < ls.length; i++) {
	    if (mp[ls[i]]) {
	        cqlFilters.push(mp[ls[i]]);
	    } else {
	        cqlFilters.push("1=1");
	    }
	}
	const a = {
	    ...this.customParameters,
	    ...this.customLayerParameters
	};
	a['cql_filter'] = cqlFilters.join(";");
	for (const d in a) b[d.toLowerCase()] = a[d];
	return b
};

最终测试

将修改后的文件重新压缩一下,替换原文件。(记得备份,出问题了不负责)
按我们的过滤需求创建一个新图层

let layer = new WMSLayer({
  url:  basemap_url + "/sand/wms",
  sublayers: [{
    name: "mstRv",
    cqlFilter: "RV_CD='FFD4EA00000L'"
  }{
    name: "mstRvLabel"
  }{
    name: "countyGeo",
    maxScale: 288895.2771443219,
    cqlFilter: "code like '4113%'"
  }]
});

跑一下代码
在这里插入图片描述
没有问题,地图服务按要求加载出来了,再看看请求
在这里插入图片描述
也是没啥问题的

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ArcGIS API for JavaScript 4.x 中包含了一个名为 Wind.js 的模块,用于绘制风场效果。Wind.js 是一个由 Vladimir Agafonkin 开发的 JavaScript 库,用于在 Web 上渲染大规模天气数据。 使用 Wind.js 可以轻松地绘制出具有流动感的风场效果,可以在地图上显示风向和风速等信息。在 ArcGIS API for JavaScript 4.x 中,可以通过导入 Wind.js 模块并使用该模块提供的方法来实现风场效果的绘制。 以下是一个使用 ArcGIS API for JavaScript 4.x 和 Wind.js 绘制风场效果的示例代码: ```javascript require([ "esri/Map", "esri/views/SceneView", "esri/layers/GraphicsLayer", "esri/Graphic", "dojo/domReady!" ], function(Map, SceneView, GraphicsLayer, Graphic) { // 创建地图 var map = new Map({ basemap: "streets", ground: "world-elevation" }); // 创建场景视图 var view = new SceneView({ container: "viewDiv", map: map, camera: { position: [-118.244, 34.052, 25000], tilt: 70 } }); // 创建图形图层 var graphicsLayer = new GraphicsLayer(); map.add(graphicsLayer); // 导入 Wind.js 模块 require([ "widgets/Wind-js/wind-js" ], function(wind) { // 加载风场数据 var url = "data/wind-global.json"; fetch(url).then(function(response) { return response.json(); }).then(function(data) { // 创建 Wind.js 实例 var windLayer = new wind.WindGL({ map: map, data: data, colorScale: [ [65, 105, 225, 0.5], [255, 255, 255, 1.0], [255, 255, 0, 1.0], [255, 0, 0, 1.0], [128, 0, 128, 1.0], [0, 0, 255, 1.0], [0, 255, 255, 1.0], [0, 255, 0, 1.0], [255, 255, 255, 1.0] ] }); // 将风场效果添加到图形图层中 graphicsLayer.add(new Graphic({ geometry: windLayer.getGeometry(), symbol: windLayer.getSymbol() })); }); }); }); ``` 在这个示例代码中,我们首先创建了一个地图和一个场景视图,并将其显示在页面上。然后我们创建了一个图形图层,用于显示风场效果。接着,我们通过导入 Wind.js 模块和加载风场数据来创建了一个 Wind.js 实例,并将其添加到图形图层中。最后,我们将图形图层添加到地图中,完成了风场效果的绘制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值