这是我参与 8 月更文挑战的第 2 天,活动详情查看:8 月更文挑战
实现思路
继承Leaflet自带的 L.Canvas
每次视图更新都发送 GetMap 获取图片,然后把图片渲染到canvas上面。
监听canvas上的click事件 , 触发 GetFeatureInfo 请求,获取该点的属性。
扩展 L.Canvas 图层
L.GridLayer.CanvasWmsLayer = L.Canvas.extend({
initialize: function (url, options ) {
},
_onClick(e) { //每次 click 发送 GetFeatureInfo 请求获得所在点的属性
this.doGetFeatureInfo()
},
_update() { //视图更新时会触发
this.doGetMap() //发送 GetMap 请求获得新图像
},
doGetMap() {
},
doGetFeatureInfo(point) {
},
onAdd: function () {
L.DomEvent.on(canvas, 'click', this._onClick, this) //绑定 Click 事件
},
});
发送 GetMap 请求
L.GridLayer.CanvasWmsLayer = L.Canvas.extend({
options: {
padding: 0
},
initialize: function (url, options, projection) {
let defaultWmsParams = {
service: 'WMS',
layers: '',
styles: '',
format: 'image/png',
transparent: false,
version: '1.1.1'
}
this._url = url;
this.wmsParams = { ...defaultWmsParams, ...options };
this.projection = projection || L.CRS.EPSG4326
},
onAdd: function () {
L.Canvas.prototype.onAdd.call(this);
},
_update() {
if (this._map._animatingZoom && this._bounds) { return; }
L.Renderer.prototype._update.call(this);
var b = this._bounds,
container = this._container,
size = b.getSize(),
m = L.Browser.retina ? 2 : 1;
L.DomUtil.setPosition(container, b.min);
container.width = m * size.x;
container.height = m * size.y;
container.style.width = size.x + 'px';
container.style.height = size.y + 'px';
this.doGetMap()
},
genRequestParame() {
let map = this._map;
let bounds = map.getBounds();
let projection = this.projection;
let size = map.getSize();
let sw = bounds.getSouthWest();
let ne = bounds.getNorthEast();
let _sw = projection.project(sw);
let _ne = projection.project(ne);
let bbox = [_sw.x, _sw.y, _ne.x, _ne.y].join(",");
let { version } = this.wmsParams
return ({
...this.wmsParams,
bbox,
width: size.x,
height: size.y,
[version === '1.3.0' ? 'crs' : 'srs']: this.projection.code
})
},
doGetMap() {
let obj = {
request: 'GetMap',
...this.genRequestParame()
}
let url = this._buildImageURL(obj)
if(this.image){ //取消未成功发送的请求
this.image.src= ''
}
let ctx = this._ctx;
let image = new Image();
image.crossOrigin = "anonymous";
image.onload = function () {
ctx.drawImage(image, 0, 0, image.width, image.height);
this.image = null
};
image.src = url;
this.image = image
},
_buildImageURL(params) {
let version = params.version || '1.1.1'
const baseParams = this.wmsParams
const opt = {
...baseParams, ...params
}
let url = this._url + L.Util.getParamString(params);
return url;
}
});
发送 GetFeatureInfo 请求
L.GridLayer.CanvasWmsLayer = L.Canvas.extend({
_onClick(e) {
//console.log('_onClick')
clearTimeout(timer)
timer = setTimeout(()=>{
let point = this._map.mouseEventToLayerPoint(e);
this.doGetFeatureInfo(point)
},300)
},
_identify(e) {
this.doGetFeatureInfo(e)
},
genRequestParame() {
let map = this._map;
let bounds = map.getBounds();
let projection = this.projection;
let size = map.getSize();
let sw = bounds.getSouthWest();
let ne = bounds.getNorthEast();
let _sw = projection.project(sw);
let _ne = projection.project(ne);
let bbox = [_sw.x, _sw.y, _ne.x, _ne.y].join(",");
let { version } = this.wmsParams
return ({
...this.wmsParams,
bbox,
width: size.x,
height: size.y,
[version === '1.3.0' ? 'crs' : 'srs']: this.projection.code
})
},
doGetFeatureInfo(point) {
let { version } = this.wmsParams
let obj = {
request: 'GetFeatureInfo',
query_layers: this.wmsParams.layers,
info_format: 'application/json',
...this.genRequestParame(),
[version === '1.3.0' ? 'i' : 'x']: point.x,
[version === '1.3.0' ? 'j' : 'y']: point.y,
}
let url = this._buildImageURL(obj)
const p = this.sendGet(url);
p.then((text)=>{
const json = JSON.parse(text);
console.log(json)
})
},
sendGet(url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 ) {
if(xhr.status == 200){
//获取服务器响应
let innerHTML = xhr.responseText;
resolve(innerHTML)
return
}
reject()
}
};
//发送异步请求
xhr.open("GET", url, true);
//发送请求
xhr.send();
})
},
_buildImageURL(params) {
let version = params.version || '1.1.1'
const baseParams = this.wmsParams
const opt = {
...baseParams, ...params
}
let url = this._url + L.Util.getParamString(params);
return url;
},
onAdd: function () {
L.Canvas.prototype.onAdd.call(this);
const canvas = this._ctx.canvas;
L.DomEvent.on(canvas, 'click', this._onClick, this)
},
});