我正在努力学习教程这里*。但我在地图组件上发现了一些意想不到的东西。
应用程序/安装的背景信息:
我通过克隆这个存储库来安装GeoExt3:https://github.com/geoext/geoext3
这个应用程序最初是一个通用的应用程序:https://github.com/geoext/geoext3/blob/master/universal-app.md。
我的应用程序的mapComponent扩展了GeoExt.component.Map,后者扩展了Ext.Component。getWidth()是一个Ext.Component方法。我想知道我的问题是否与继承有关。下面两个api文档让我困惑了一下,但随后意识到,第一个是没有ext组件的GeoExt,第二个是ext组件。
https://geoext.github.io/geoext3/master/docs/#!/api/GeoExt.component.Map http://geoext.github.io/geoext3/master/docs-w-ext/#!/api/GeoExt.component.Map
应用程序代码https://github.com/qnmai/qnmai.github.io/tree/debugprint。
我的层、映射和映射组件以这种方式创建(成功):
var t_coupureaerien_source = new ol.source.VectorTile({
format: new ol.format.MVT(),
url: 'https://ahocevar.com/geoserver/gwc/service/tms/1.0.0/' + 'ne:ne_10m_admin_0_countries@EPSG%3A900913@pbf/{z}/{x}/{-y}.pbf'
})
var t_coupureaerien_style = new ol.style.Style({
fill: new ol.style.Fill({color: 'rgba(255, 255, 255, 0.6)'}),
stroke: new ol.style.Stroke({color: '#319FD3', width: 1})
});
var t_coupureaerien_layer = new ol.layer.VectorTile({
title: 'Coupure Aerien HTA',
style: t_coupureaerien_style,
source: t_coupureaerien_source,
legendUrl: 'https://ahocevar.com/geoserver/gwc/service/tms/1.0.0/' + 'ne:ne_10m_admin_0_countries@EPSG%3A900913@pbf/{z}/{x}/{-y}.pbf',
name: 'Appareil de coupure aerien'
});
var osm_source = new ol.source.OSM({url: "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"});
var osm_basemap = new ol.layer.Tile({
title: 'OSM basemap',
source: osm_source,
//legendUrl: 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
name: 'OSM basemap'})
var extentLayer = new ol.layer.Vector({
source: new ol.source.Vector()
});
var view = new ol.View({
center: ol.proj.fromLonLat([-149.3, -17.7]),
zoom: 7
});
var my_map = new ol.Map({
controls: ol.control.defaults().extend([new ol.control.ScaleLine]),
target: 'map',
view: view,
layers: [
new ol.layer.Group({title: 'Fond de plans', layers: [osm_basemap], name: 'Fond de plans'}),
new ol.layer.Group({title: 'Réseau Secosud', layers: [coupureaerien_layer], name: 'Réseau Secosud'}),
extentLayer
],
//overlays: [overlay],
});
var mapComponent = Ext.define('SIG.view.main.Map', {
// extend: "Ext.panel.Panel",
extend: 'GeoExt.component.Map',
xtype: 'mappanel',
//region: 'center',
requires: [
'SIG.view.main.MapController', 'SIG.view.main.MapModel'
],
controller: 'main-map',
viewModel: {
type: 'main-map'
},
// html: "Hello, World!!"
map: my_map
});
console.log(mapComponent);
console.log(mapComponent.getWidth());但是getWidth()给出了这个错误,尽管它是一个映射组件的方法:
Uncaught TypeError: mapComponent.getWidth is not a function我已经将mapComponent对象打印到控制台,超类显示了以下方法。似乎getWidth不在那里。这是问题的一部分吗?(对不起,json格式.我无法让火狐的toSource工作)。第一个想法是它可能是,但是我的对象再次扩展了GeoExt.map.Component,这反过来扩展了Ext.Component,所以这可能不是打印整个链(?)。
superclass: {…}
"$className": "GeoExt.component.Map"
"$inheritableStatics": Object { _checked: true, check: true, normalizeSymbol: true, … }
"$noClearOnDestroy": Object { events: true, hasListeners: true, managedListeners: true, … }
HasListeners: function HasListeners()
addLayer: function addLayer()
alias: Array [ "widget.gx_map", "widget.gx_component_map" ]
applyPointerRest: function applyPointerRest()
applyPointerRestInterval: function applyPointerRestInterval()
applyState: function applyState()
bindOverOutListeners: function bindOverOutListeners()
bindStateOlEvents: function bindStateOlEvents()
bufferedPointerMove: function emptyFn()
childEls: Object { frameTable: {}, frameTL: {}, frameTC: {}, … }
config: Object { pointerRest: false, pointerRestInterval: 1000, pointerRestPixelTolerance: 3, … }
constructor: function constructor()
defaultConfig: Object { pointerRest: false, pointerRestInterval: 1000, pointerRestPixelTolerance: 3, … }
defaultListenerScope: false
getCenter: function getCenter()
getExtent: function getExtent()
getLayers: function getLayers()
getMap: function makeGetter()
getPointerRest: function makeGetter()
getPointerRestInterval: function makeGetter()
getPointerRestPixelTolerance: function makeGetter()
getState: function getState()
getStore: function getStore()
getView: function getView()
isMouseOverMapEl: null
lastPointerPixel: null
layerStore: null
map: null
mapRendered: false
mixins: Object { isDefinedSymbol: {…} }
onMouseOut: function onMouseOut()
onMouseOver: function onMouseOver()
onResize: function onResize()
pointerRestPixelTolerance: 3
registerPointerRestEvents: function registerPointerRestEvents()
removeLayer: function removeLayer()
requires: Array [ Layers()
, Version()
]
self: function Map()
setCenter: function setCenter()
setExtent: function setExtent()
setMap: function setter()
setPointerRest: function setter()
setPointerRestInterval: function setter()
setPointerRestPixelTolerance: function setter()
setView: function setView()
stateEvents: Array [ "aftermapmove" ]
superclass: Object { self: Component()
, superclass: {…}, defaultConfig: {…}, … }
symbols: Array(15) [ "ol.layer.Base", "ol.Map", "ol.Map#addLayer", … ]
unbindOverOutListeners: function unbindOverOutListeners()
unbufferedPointerMove: function unbufferedPointerMove()
unregisterPointerRestEvents: function unregisterPointerRestEvents()
xtype: "gx_map"
xtypes: Array [ "gx_map", "gx_component_map" ]
xtypesChain: Array(4) [ "component", "box", "gx_map", … ]
xtypesMap: Object { component: true, box: true, gx_map: true, … }
<prototype>: Object { self: Component()
, superclass: {…}, defaultConfig: {…}, … }因此,使用以下代码调用MapFish模块会给出相同的错误:
Ext.require([
'GeoExt.component.Map',
'SIG.view.main.Map']);
/**
* Once the store is loaded, we can create the button with the
* following assumptions:
*
* * The button will print the first layout
* * The attributes used are the first of the above layout
* * We'll request the first dpi value of the suggested ones
* @param {GeoExt.data.MapfishPrintProvider} provider The print
* provider.
*/
var onPrintProviderReady = function(provider) {
// this is the assumption: take the first layout and render an
// appropriate extent on the map
var capabilities = provider.capabilityRec;
var layout = capabilities.layouts().getAt(0);
var attr = layout.attributes().getAt(0);
var clientInfo = attr.get('clientInfo');
var render = GeoExt.data.MapfishPrintProvider.renderPrintExtent;
console.log(mapComponent);
render(mapComponent, extentLayer, clientInfo);
mapComponent.getView().on('propertychange', function() {
extentLayer.getSource().clear();
render(mapComponent, extentLayer, clientInfo);
});
description.add({
xtype: 'button',
text: 'Print',
handler: function() {
var spec = {
layout: layout.get('name'),
attributes: {}
};
var firstFeature = extentLayer.getSource().getFeatures()[0];
var bbox = firstFeature.getGeometry().getExtent();
var util = GeoExt.data.MapfishPrintProvider;
var mapView = mapComponent.getView();
var serializedLayers = util.getSerializedLayers(
mapComponent,
function(layer) {
// do not print the extent layer
var isExtentLayer = (extentLayer === layer);
return !isExtentLayer;
}
);
serializedLayers = unHttpsLayers(serializedLayers);
serializedLayers.reverse();
spec.attributes[attr.get('name')] = {
bbox: bbox,
dpi: clientInfo.dpiSuggestions[0],
layers: serializedLayers,
projection: mapView.getProjection().getCode(),
rotation: mapView.getRotation()
};
Ext.create('Ext.form.Panel', {
standardSubmit: true,
url: 'https://apps.terrestris.de/print-servlet-3.1.2/' +
'print/geoext/buildreport.pdf',
method: 'POST',
items: [
{
xtype: 'textfield',
name: 'spec',
value: Ext.encode(spec)
}
]
}).submit();
}
});
};
Ext.create('GeoExt.data.MapfishPrintProvider', {
url: 'https://apps.terrestris.de/print-servlet-3.1.2/' +
'print/geoext/capabilities.json',
listeners: {
ready: onPrintProviderReady
}
});对于那些不熟悉MapFishPrintProvider的人来说。这个问题出现在renderPrintExtent中:
/* Copyright (c) 2015-2017 The Open Source Geospatial Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Provides an interface to a Mapfish or GeoServer print module.
*
* @class GeoExt.data.MapfishPrintProvider
*/
Ext.define('GeoExt.data.MapfishPrintProvider', {
extend: 'Ext.Base',
mixins: [
'Ext.mixin.Observable',
'GeoExt.mixin.SymbolCheck'
],
requires: [
'GeoExt.data.model.print.Capability',
'Ext.data.JsonStore'
],
// <debug>
symbols: [
'ol.Collection',
'ol.geom.Polygon.fromExtent',
'ol.Feature',
'ol.layer.Layer#getSource',
'ol.layer.Group',
'ol.source.Vector.prototype.addFeature',
'ol.View#calculateExtent'
],
// </debug>
/**
* @event ready
* Fires after the PrintCapability store is loaded.
*
* @param {GeoExt.data.MapfishPrintProvider} provider The
* GeoExt.data.MapfishPrintProvider itself
*/
config: {
capabilities: null,
url: ''
},
inheritableStatics: {
/**
* An array of objects specifying a serializer and a connected
* OpenLayers class. This should not be manipulated by hand, but rather
* with the method #registerSerializer.
*
* @private
*/
_serializers: [],
/**
* Registers the passed serializer class as an appropriate serializer
* for the passed OpenLayers source class.
*
* @param {ol.source.Source} olSourceCls The OpenLayers source class
* that the passed serializer can serialize.
* @param {GeoExt.data.serializer.Base} serializerCls The serializer
* that can serialize the passed source.
*/
registerSerializer: function(olSourceCls, serializerCls) {
var staticMe = GeoExt.data.MapfishPrintProvider;
staticMe._serializers.push({
olSourceCls: olSourceCls,
serializerCls: serializerCls
});
},
/**
* Unregisters the passed serializer class from the array of available
* serializers. This may be useful if you want to register a new
* serializer that is different from a serializer that we provide.
*
* @param {GeoExt.data.serializer.Base} serializerCls The serializer
* that can serialize the passed source.
* @return {Boolean} Whether we could unregister the serializer.
*/
unregisterSerializer: function(serializerCls) {
var available = GeoExt.data.MapfishPrintProvider._serializers;
var index;
Ext.each(available, function(candidate, idx) {
if (candidate.serializerCls === serializerCls) {
index = idx;
return false; // break early
}
});
if (Ext.isDefined(index)) {
Ext.Array.removeAt(available, index);
return true;
}
return false;
},
/**
* Returns a GeoExt.data.serializer.Base capable of serializing the
* passed source instance or undefined, if no such serializer was
* previously registered.
*
* @param {ol.source.Source} source The source instance to find a
* serializer for.
* @return {GeoExt.data.serializer.Base} A serializer for the passed
* source or `undefined`.
*/
findSerializerBySource: function(source) {
var available = GeoExt.data.MapfishPrintProvider._serializers;
var serializer;
Ext.each(available, function(candidate) {
if (source instanceof candidate.olSourceCls) {
serializer = candidate.serializerCls;
return false; // break early
}
});
if (!serializer) {
Ext.log.warn('Couldn\'t find a suitable serializer for source.'
+ ' Did you require() an appropriate serializer class?');
}
return serializer;
},
/**
* Will return an array of ol-layers by the given collection. Layers
* contained in `ol.layer.Group`s get extracted and groups get removed
* from returning array
*
* @param {GeoExt.data.store.Layers|ol.Collection|ol.layer.Base[]} coll
* The 'collection' of layers to get as array. If passed as
* ol.Collection, all items must be `ol.layer.Base`.
* @return {Array} The flat layers array.
*/
getLayerArray: function(coll) {
var me = this;
var inputLayers = [];
var outputLayers = [];
if (coll instanceof GeoExt.data.store.Layers) {
coll.each(function(layerRec) {
var layer = layerRec.getOlLayer();
inputLayers.push(layer);
});
} else if (coll instanceof ol.Collection) {
inputLayers = Ext.clone(coll.getArray());
} else {
inputLayers = Ext.clone(coll);
}
inputLayers.forEach(function(layer) {
if (layer instanceof ol.layer.Group) {
Ext.each(me.getLayerArray(layer.getLayers()),
function(subLayer) {
outputLayers.push(subLayer);
});
} else {
outputLayers.push(layer);
}
});
return outputLayers;
},
/**
* Will return an array of serialized layers for mapfish print servlet
* v3.0.
*
* @param {GeoExt.component.Map} mapComponent The GeoExt map component
* to get the the layers from.
* @param {Function} [filterFn] A function to filter the layers to be
* serialized.
* @param {ol.layer.Base} filterFn.item The layer to check for
* inclusion.
* @param {Number} filterFn.index The index of the layer in the
* flattened list.
* @param {Array} filterFn.array The complete flattened array of layers.
* @param {Boolean} filterFn.return Return a truthy value to keep the
* layer and serialize it.
* @param {Object} [filterScope] The scope in which the filtering
* function will be executed.
* @return {Array<Object>} An array of serialized layers.
* @static
*/
getSerializedLayers: function(mapComponent, filterFn, filterScope) {
var layers = mapComponent.getLayers();
var viewRes = mapComponent.getView().getResolution();
var serializedLayers = [];
var inputLayers = this.getLayerArray(layers);
if (Ext.isDefined(filterFn)) {
inputLayers = Ext.Array.filter(
inputLayers, filterFn, filterScope
);
}
Ext.each(inputLayers, function(layer) {
var source = layer.getSource();
var serialized = {};
var serializer = this.findSerializerBySource(source);
if (serializer) {
serialized = serializer.serialize(layer, source, viewRes);
serializedLayers.push(serialized);
}
}, this);
return serializedLayers;
},
/**
* Renders the extent of the printout. Will ensure that the extent is
* always visible and that the ratio matches the ratio that clientInfo
* contains.
*
* @param {GeoExt.component.Map} mapComponent The map component to
* render the print extent to.
* @param {ol.layer.Vector} extentLayer The vector layer to render the
* print extent to.
* @param {Object} clientInfo Information about the desired print
* dimensions.
* @param {Number} clientInfo.width The target width.
* @param {Number} clientInfo.height The target height.
* @return {ol.Feature} The feature representing the print extent.
*/
renderPrintExtent: function(mapComponent, extentLayer, clientInfo) {
var mapComponentWidth = mapComponent.getWidth();
var mapComponentHeight = mapComponent.getHeight();
var currentMapRatio = mapComponentWidth / mapComponentHeight;
var scaleFactor = 0.6;
var desiredPrintRatio = clientInfo.width / clientInfo.height;
var targetWidth;
var targetHeight;
var geomExtent;
var feat;
if (desiredPrintRatio >= currentMapRatio) {
targetWidth = mapComponentWidth * scaleFactor;
targetHeight = targetWidth / desiredPrintRatio;
} else {
targetHeight = mapComponentHeight * scaleFactor;
targetWidth = targetHeight * desiredPrintRatio;
}
geomExtent = mapComponent.getView().calculateExtent([
targetWidth,
targetHeight
]);
feat = new ol.Feature(ol.geom.Polygon.fromExtent(geomExtent));
extentLayer.getSource().addFeature(feat);
return feat;
}
},
/**
* The capabiltyRec is an instance of 'GeoExt.data.model.print.Capability'
* and contans the PrintCapabilities of the Printprovider.
*
* @property
* @readonly
*/
capabilityRec: null,
constructor: function(cfg) {
this.mixins.observable.constructor.call(this, cfg);
if (!cfg.capabilities && !cfg.url) {
Ext.Error.raise('Print capabilities or Url required');
}
this.initConfig(cfg);
this.fillCapabilityRec();
},
/**
* Creates the store from object or url.
*
* @private
*/
fillCapabilityRec: function() {
// enhance checks
var store;
var capabilities = this.getCapabilities();
var url = this.getUrl();
var fillRecordAndFireEvent = function() {
this.capabilityRec = store.getAt(0);
if (!this.capabilityRec) {
this.fireEvent('error', this);
} else {
this.fireEvent('ready', this);
}
};
if (capabilities) { // if capability object is passed
store = Ext.create('Ext.data.JsonStore', {
model: 'GeoExt.data.model.print.Capability',
listeners: {
datachanged: fillRecordAndFireEvent,
scope: this
}
});
store.loadRawData(capabilities);
} else if (url) { // if servlet url is passed
store = Ext.create('Ext.data.Store', {
autoLoad: true,
model: 'GeoExt.data.model.print.Capability',
proxy: {
type: 'jsonp',
url: url,
callbackKey: 'jsonp'
},
listeners: {
load: fillRecordAndFireEvent,
scope: this
}
});
}
}
});我的Main.js文件:
Ext.define('SIG.view.main.Main', {
extend: 'Ext.container.Viewport',
requires: [
'Ext.plugin.Viewport', 'Ext.window.MessageBox', 'SIG.view.main.MainController', 'SIG.view.main.MainModel', 'SIG.view.main.List', 'SIG.view.main.Map', 'SIG.view.main.Print'
],
controller: 'main',
viewModel: 'main',
layout: 'border',
items: [
mapComponent,
layerTreePanel
]
})*顺便提一句,这个应用程序对我不起作用,但有一个错误:“处理请求时出错: java.net.MalformedURLException: unknown : data",但我还是决定尝试使用它。
编辑
我已经更新了代码,以使用映射组件呈现上的侦听器创建MapFishPrintProvider,如下所示。不幸的是,这并没有解决我的问题,错误信息保持不变。
var mapComponent = Ext.define('SIG.view.main.Map', {
// extend: "Ext.panel.Panel",
extend: 'GeoExt.component.Map',
xtype: 'mappanel',
//region: 'center',
requires: [
'SIG.view.main.MapController', 'SIG.view.main.MapModel'
],
controller: 'main-map',
viewModel: {
type: 'main-map'
},
// html: "Hello, World!!"
map: my_map,
// Register the on render here
listeners: {
render: function(){
console.log("Map rendered"); //this prints
Ext.create('GeoExt.data.MapfishPrintProvider', {
url: 'https://apps.terrestris.de/print-servlet-3.1.2/' +
'print/geoext/capabilities.json',
listeners: {
ready: onPrintProviderReady
}
});
}
}
});发布于 2019-07-04 11:08:49
您是否确保在创建MapfishPrintProvider时创建和呈现映射?因为一旦提供程序获得了功能,它就会触发ready事件,不管映射是创建/呈现的还是未创建的。
在地图上注册on render事件,并在那里创建提供者:
var mapComponent = Ext.define('SIG.view.main.Map', {
// extend: "Ext.panel.Panel",
extend: 'GeoExt.component.Map',
xtype: 'mappanel',
//region: 'center',
requires: [
'SIG.view.main.MapController', 'SIG.view.main.MapModel'
],
controller: 'main-map',
viewModel: {
type: 'main-map'
},
// html: "Hello, World!!"
map: my_map,
// Register the on render here
listeners: {
render: function(){
Ext.create('GeoExt.data.MapfishPrintProvider', {
url: 'https://apps.terrestris.de/print-servlet-3.1.2/' +
'print/geoext/capabilities.json',
listeners: {
ready: onPrintProviderReady
}
});
}
}
});https://stackoverflow.com/questions/56605940
复制相似问题