Javascript Angular 5和OpenLayers 4:无法读取属性';getEventPixel';和';forEachFeatureAtPixel';
我正在尝试将OpenLayers与Angular 5结合使用。 我正在测试实现地图的不同方法,我已经在简单的HTML文件中测试了传单和OpenLayers,我选择使用OpenLayers,这在我的例子中更有效 有了这个地图,我想在不同的图层之间切换(使用ol layerswitcher),根据GeoJSON文件放置标记并显示弹出窗口。 所有这些功能在我的HTML文件中都运行良好,现在,我想用Angular 5做同样的事情(不是Angular openlayers指令) 我已经在app.component.ts文件中修改了Angular中的HTML代码,标记根据我的GeoJSON文件显示,我的图层切换器也是如此,但我在两个功能上有问题:forEachFeatureatPixel和getEventPixel 这是我的src/app/app.component.ts:Javascript Angular 5和OpenLayers 4:无法读取属性';getEventPixel';和';forEachFeatureAtPixel';,javascript,angular,typescript,openlayers,Javascript,Angular,Typescript,Openlayers,我正在尝试将OpenLayers与Angular 5结合使用。 我正在测试实现地图的不同方法,我已经在简单的HTML文件中测试了传单和OpenLayers,我选择使用OpenLayers,这在我的例子中更有效 有了这个地图,我想在不同的图层之间切换(使用ol layerswitcher),根据GeoJSON文件放置标记并显示弹出窗口。 所有这些功能在我的HTML文件中都运行良好,现在,我想用Angular 5做同样的事情(不是Angular openlayers指令) 我已经在app.compo
import { Component, OnInit } from '@angular/core';
import OlMap from 'ol/map';
import OlWMS from 'ol/source/tilewms';
import OlTileLayer from 'ol/layer/tile';
import OlView from 'ol/view';
import olProj from 'ol/proj';
import VectorLayer from 'ol/layer/vector';
import VectorSource from 'ol/source/vector';
import Point from 'ol/geom/point';
import Style from 'ol/style/style';
import IconStyle from 'ol/style/icon';
import WFS from 'ol/format/wfs';
import GeoJSON from 'ol/format/geojson';
import Overlay from 'ol/overlay';
import feature from 'ol/feature';
import OlSwitch from 'ol-layerswitcher/src/ol-layerswitcher';
import CanvasMap from 'ol/canvasmap';
//import evt from 'ol/mapbrowserevent';
//import mbe from 'ol/mapbrowsereventtype';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
map: OlMap;
gny_bright: OlWMS;
gny_bright_mobile: OlWMS;
layer: OlTileLayer;
view: OlView;
layerSwitcher: OlSwitch;
WFS: WFS;
vectorLayer: VectorLayer;
sourceLayer: VectorSource;
feature: feature;
evt: evt;
mbe: mbe;
//parkvert: IconStyle;
//parkorange: Style;
//parkrouge: Style;
//parknoir: Style;
constructor() {
}
ngOnInit() {
this.gny_bright = new OlWMS({
url: '...',
params: {...},
attributions: '...'
});
this.gny_bright_mobile = new OlWMS({
url: '...',
params: {...},
attributions: '...'
});
var parkvert = new Style({
image: new IconStyle(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'assets/image/parking-vert.png'
}))
});
var parkorange = new Style({
image: new IconStyle(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'assets/image/parking-orange.png'
}))
});
this.view = new OlView({
center: [689805.19, 6222389.4],
minZoom: 1,
maxZoom: 19,
zoom: 2
});
this.sourceLayer = new VectorSource({
url: 'url_to_my_geojson_file',
format: new GeoJSON()
});
this.vectorLayer = new VectorLayer({
source: this.sourceLayer
});
this.map = new OlMap({
target: 'map',
layers: [
new OlTileLayer({
title: 'gny_bright_mobile',
source: this.gny_bright_mobile,
type: 'base',
attributions: '...'
}),
new OlTileLayer({
title: 'gny_bright',
source: this.gny_bright,
type: 'base',
attributions: '...'
})
],
view: this.view
});
var markers = function style(feature, resolution) {
if (feature.get('PLACES') == null) {
return parknoir;
} else if(feature.get('PLACES') <= feature.get('CAPACITE') * 0.05) {
return parkrouge;
} else if(feature.get('PLACES') <= feature.get('CAPACITE') * 0.15){
return parkorange;
} else if(feature.get('PLACES') > feature.get('CAPACITE') * 0.15) {
return parkvert;
}
}
this.vectorLayer.setStyle(markers);
//popup
var element = document.getElementById('popup');
var popup = new Overlay({
element: element,
autoPan: true,
offset: [0, -30]
});
this.map.addOverlay(popup);
var content_element = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');
closer.onclick = function() {
popup.setPosition(undefined);
closer.blur();
return false;
};
this.map.on('click', function(evt){
this.feature = this.map.forEachFeatureAtPixel(evt.pixel,
function(feature) {
return this.feature;
});
if (this.feature) {
var geometry = this.feature.getGeometry();
var coord = geometry.getCoordinates();
if(this.feature.get('NOM')!=null) {
var content = '<center><h2>' + this.feature.get('NOM') + '</h2></center>' + '<br>';
}
if(this.feature.get('ADRESSE')!=null) {
content += '<h5>' + '<i>Adresse : </i>' + this.feature.get('ADRESSE') + '</h5>';
}
if(this.feature.get('CAPACITE')!=null) {
content += '<h5>' + '<i>Capacité : </i>' + this.feature.get('CAPACITE') + '</h5>';
}
if(this.feature.get('PLACES')!=null) {
content += '<h5>' + '<i>Places disponibles : </i>' + this.feature.get('PLACES') + '<h5>';
}
content_element.innerHTML = content;
popup.setPosition(coord);
}
});
this.map.on('pointermove', function(e) {
if (e.dragging) {
return;
};
var pixel = this.map.getEventPixel(e.originalEvent);
var hit = this.map.hasFeatureAtPixel(pixel);
this.map.getViewport().style.cursor = hit ? 'pointer' : '';
});
this.map.addControl(this.vectorLayer);
this.layerSwitcher = new OlSwitch();
this.map.addControl(this.layerSwitcher);
}
}
My styles.css:
html, body {
margin: 0px;
}
/* You can add global styles to this file, and also import other style files */
.ol-box {
box-sizing: border-box;
border-radius: 2px;
border: 2px solid blue;
}
.ol-mouse-position {
top: 8px;
right: 8px;
position: absolute;
}
.ol-scale-line {
background: rgba(0,60,136,0.3);
border-radius: 4px;
bottom: 8px;
left: 8px;
padding: 2px;
position: absolute;
}
.ol-scale-line-inner {
border: 1px solid #eee;
border-top: none;
color: #eee;
font-size: 10px;
text-align: center;
margin: 1px;
will-change: contents, width;
}
.ol-overlay-container {
will-change: left,right,top,bottom;
}
.ol-unsupported {
display: none;
}
.ol-viewport, .ol-unselectable {
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
.ol-selectable {
-webkit-touch-callout: default;
-webkit-user-select: auto;
-moz-user-select: auto;
-ms-user-select: auto;
user-select: auto;
}
.ol-grabbing {
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
cursor: grabbing;
}
.ol-grab {
cursor: move;
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: grab;
}
.ol-control {
position: absolute;
background-color: rgba(255,255,255,0.4);
border-radius: 4px;
padding: 2px;
}
.ol-control:hover {
background-color: rgba(255,255,255,0.6);
}
.ol-zoom {
top: .5em;
left: .5em;
}
.ol-rotate {
top: .5em;
right: .5em;
transition: opacity .25s linear, visibility 0s linear;
}
.ol-rotate.ol-hidden {
opacity: 0;
visibility: hidden;
transition: opacity .25s linear, visibility 0s linear .25s;
}
.ol-zoom-extent {
top: 4.643em;
left: .5em;
}
.ol-full-screen {
right: .5em;
top: .5em;
}
@media print {
.ol-control {
display: none;
}
}
.ol-control button {
display: block;
margin: 1px;
padding: 0;
color: white;
font-size: 1.14em;
font-weight: bold;
text-decoration: none;
text-align: center;
height: 1.375em;
width: 1.375em;
line-height: .4em;
background-color: rgba(0,60,136,0.5);
border: none;
border-radius: 2px;
}
.ol-control button::-moz-focus-inner {
border: none;
padding: 0;
}
.ol-zoom-extent button {
line-height: 1.4em;
}
.ol-compass {
display: block;
font-weight: normal;
font-size: 1.2em;
will-change: transform;
}
.ol-touch .ol-control button {
font-size: 1.5em;
}
.ol-touch .ol-zoom-extent {
top: 5.5em;
}
.ol-control button:hover,
.ol-control button:focus {
text-decoration: none;
background-color: rgba(0,60,136,0.7);
}
.ol-zoom .ol-zoom-in {
border-radius: 2px 2px 0 0;
}
.ol-zoom .ol-zoom-out {
border-radius: 0 0 2px 2px;
}
.ol-attribution {
text-align: right;
bottom: .5em;
right: .5em;
max-width: calc(100% - 1.3em);
}
.ol-attribution ul {
margin: 0;
padding: 0 .5em;
font-size: .7rem;
line-height: 1.375em;
color: #000;
text-shadow: 0 0 2px #fff;
}
.ol-attribution li {
display: inline;
list-style: none;
line-height: inherit;
}
.ol-attribution li:not(:last-child):after {
content: " ";
}
.ol-attribution img {
max-height: 2em;
max-width: inherit;
vertical-align: middle;
}
.ol-attribution ul, .ol-attribution button {
display: inline-block;
}
.ol-attribution.ol-collapsed ul {
display: none;
}
.ol-attribution.ol-logo-only ul {
display: block;
}
.ol-attribution:not(.ol-collapsed) {
background: rgba(255,255,255,0.8);
}
.ol-attribution.ol-uncollapsible {
bottom: 0;
right: 0;
border-radius: 4px 0 0;
height: 1.1em;
line-height: 1em;
}
.ol-attribution.ol-logo-only {
background: transparent;
bottom: .4em;
height: 1.1em;
line-height: 1em;
}
.ol-attribution.ol-uncollapsible img {
margin-top: -.2em;
max-height: 1.6em;
}
.ol-attribution.ol-logo-only button,
.ol-attribution.ol-uncollapsible button {
display: none;
}
.ol-zoomslider {
top: 4.5em;
left: .5em;
height: 200px;
}
.ol-zoomslider button {
position: relative;
height: 10px;
}
.ol-touch .ol-zoomslider {
top: 5.5em;
}
.ol-overviewmap {
left: 0.5em;
bottom: 0.5em;
}
.ol-overviewmap.ol-uncollapsible {
bottom: 0;
left: 0;
border-radius: 0 4px 0 0;
}
.ol-overviewmap .ol-overviewmap-map,
.ol-overviewmap button {
display: inline-block;
}
.ol-overviewmap .ol-overviewmap-map {
border: 1px solid #7b98bc;
height: 150px;
margin: 2px;
width: 150px;
}
.ol-overviewmap:not(.ol-collapsed) button{
bottom: 1px;
left: 2px;
position: absolute;
}
.ol-overviewmap.ol-collapsed .ol-overviewmap-map,
.ol-overviewmap.ol-uncollapsible button {
display: none;
}
.ol-overviewmap:not(.ol-collapsed) {
background: rgba(255,255,255,0.8);
}
.ol-overviewmap-box {
border: 2px dotted rgba(0,60,136,0.7);
}
.ol-overviewmap .ol-overviewmap-box:hover {
cursor: move;
}
.layer-switcher.shown.ol-control {
background-color: transparent;
}
.layer-switcher.shown.ol-control:hover {
background-color: transparent;
}
.layer-switcher {
position: absolute;
top: 3.5em;
right: 0.5em;
text-align: left;
}
.layer-switcher.shown {
bottom: 3em;
}
.layer-switcher .panel {
padding: 0 1em 0 0;
margin: 0;
border: 4px solid #eee;
border-radius: 4px;
background-color: white;
display: none;
max-height: 100%;
overflow-y: auto;
}
.layer-switcher.shown .panel {
display: block;
}
.layer-switcher button {
float: right;
width: 38px;
height: 38px;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACE1BMVEX///8A//8AgICA//8AVVVAQID///8rVVVJtttgv98nTmJ2xNgkW1ttyNsmWWZmzNZYxM4gWGgeU2JmzNNr0N1Rwc0eU2VXxdEhV2JqytQeVmMhVmNoydUfVGUgVGQfVGQfVmVqy9hqy9dWw9AfVWRpydVry9YhVmMgVGNUw9BrytchVWRexdGw294gVWQgVmUhVWPd4N6HoaZsy9cfVmQgVGRrytZsy9cgVWQgVWMgVWRsy9YfVWNsy9YgVWVty9YgVWVry9UgVWRsy9Zsy9UfVWRsy9YgVWVty9YgVWRty9Vsy9aM09sgVWRTws/AzM0gVWRtzNYgVWRuy9Zsy9cgVWRGcHxty9bb5ORbxdEgVWRty9bn6OZTws9mydRfxtLX3Nva5eRix9NFcXxOd4JPeINQeIMiVmVUws9Vws9Vw9BXw9BYxNBaxNBbxNBcxdJexdElWWgmWmhjyNRlx9IqXGtoipNpytVqytVryNNrytZsjZUuX210k5t1y9R2zNR3y9V4lp57zth9zdaAnKOGoaeK0NiNpquV09mesrag1tuitbmj1tuj19uktrqr2d2svcCu2d2xwMO63N+7x8nA3uDC3uDFz9DK4eHL4eLN4eIyYnDX5OM5Z3Tb397e4uDf4uHf5uXi5ePi5+Xj5+Xk5+Xm5+Xm6OY6aHXQ19fT4+NfhI1Ww89gx9Nhx9Nsy9ZWw9Dpj2abAAAAWnRSTlMAAQICAwQEBgcIDQ0ODhQZGiAiIyYpKywvNTs+QklPUlNUWWJjaGt0dnd+hIWFh4mNjZCSm6CpsbW2t7nDzNDT1dje5efr7PHy9PT29/j4+Pn5+vr8/f39/f6DPtKwAAABTklEQVR4Xr3QVWPbMBSAUTVFZmZmhhSXMjNvkhwqMzMzMzPDeD+xASvObKePPa+ffHVl8PlsnE0+qPpBuQjVJjno6pZpSKXYl7/bZyFaQxhf98hHDKEppwdWIW1frFnrxSOWHFfWesSEWC6R/P4zOFrix3TzDFLlXRTR8c0fEEJ1/itpo7SVO9Jdr1DVxZ0USyjZsEY5vZfiiAC0UoTGOrm9PZLuRl8X+Dq1HQtoFbJZbv61i+Poblh/97TC7n0neCcK0ETNUrz1/xPHf+DNAW9Ac6t8O8WH3Vp98f5lCaYKAOFZMLyHL4Y0fe319idMNgMMp+zWVSybUed/+/h7I4wRAG1W6XDy4XmjR9HnzvDRZXUAYDFOhC1S/Hh+fIXxen+eO+AKqbs+wAo30zDTDvDxKoJN88sjUzDFAvBzEUGFsnADoIvAJzoh2BZ8sner+Ke/vwECuQAAAABJRU5ErkJggg==') /*logo.png*/;
background-repeat: no-repeat;
background-position: 2px;
background-color: white;
border: none;
}
.layer-switcher.shown button {
display: none;
}
.layer-switcher button:focus, .layer-switcher button:hover {
background-color: white;
}
.layer-switcher ul {
padding-left: 1em;
list-style: none;
}
.layer-switcher li.group {
padding-top: 5px;
}
.layer-switcher li.group > label {
font-weight: bold;
}
.layer-switcher li.layer {
display: table;
}
.layer-switcher li.layer label, .layer-switcher li.layer input {
display: table-cell;
vertical-align: sub;
}
.layer-switcher label.disabled {
opacity:0.4;
}
.layer-switcher input {
margin: 6px;
}
.layer-switcher.touch ::-webkit-scrollbar {
width: 4px;
}
.layer-switcher.touch ::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
border-radius: 10px;
}
.layer-switcher.touch ::-webkit-scrollbar-thumb {
border-radius: 10px;
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
}
/** Popup */
.ol-popup {
position: absolute;
min-width: 260px;
background-color: white;
-webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
padding: 15px;
border-radius: 10px;
border: 1px solid #ccc;
bottom: 12px;
left: -50px;
}
.ol-popup:after, .ol-popup:before {
top: 100%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.ol-popup:after {
border-top-color: white;
border-width: 10px;
left: 48px;
margin-left: -10px;
}
.ol-popup:before {
border-top-color: #cccccc;
border-width: 11px;
left: 48px;
margin-left: -11px;
}
.ol-popup-closer {
text-decoration: none;
position: absolute;
top: 2px;
right: 8px;
}
.ol-popup-closer:after {
color: red;
content: "✖";
}
所有代码都以角度工作,直到scr/app/app.component.ts中的行“//popup”
在那一行之后,我有两个错误,当我用鼠标在地图上飞行时getEventPixel,当我点击一个标记时forEachFeatureAtPixel
提前谢谢 JavaScript不是Java。您没有将函数绑定到组件,因此
这不是您所认为的。阅读mozilla上的文章
在arrow函数之前,每个新函数都定义了自己的此值
但这是很容易解决的使用
箭头函数没有它自己的函数;使用封闭执行上下文的此值
考虑下面的代码:
this.map.on('click', function(evt){
this.map.getEventPixel
});
上面的代码试图访问事件函数函数(evt)
的属性映射,但它没有。要修复它,只需将其更改为箭头函数:
this.map.on('click', (evt) => {
this.map.getEventPixel
});
在上面的代码中,这个
实际上是组件的上下文,因此映射
是组件的属性。JavaScript不是Java。您没有将函数绑定到组件,因此这不是您所认为的。阅读mozilla上的文章
在arrow函数之前,每个新函数都定义了自己的此值
但这是很容易解决的使用
箭头函数没有它自己的函数;使用封闭执行上下文的此值
考虑下面的代码:
this.map.on('click', function(evt){
this.map.getEventPixel
});
上面的代码试图访问事件函数函数(evt)
的属性映射,但它没有。要修复它,只需将其更改为箭头函数:
this.map.on('click', (evt) => {
this.map.getEventPixel
});
在上面的代码中,此
实际上是组件的上下文,因此映射
是组件的属性。我找到了“无法读取属性”forEachFeatureAtPixel“未定义”错误的解决方案
我的初始代码(将引发错误):
工作代码:
this.map.on('click', function(evt){
var feature = evt.map.forEachFeatureAtPixel(evt.pixel, function(feature) {
return feature;
});
if (feature) {
console.log("Feature found");
}
});
说明:
使用click事件中的映射实例(evt.map.forEachFeatureAtPixel)而不是根实例(this.map.forEachFeatureAtPixel)。我找到了“无法读取属性”forEachFeatureAtPixel“未定义”错误的解决方案
我的初始代码(将引发错误):
工作代码:
this.map.on('click', function(evt){
var feature = evt.map.forEachFeatureAtPixel(evt.pixel, function(feature) {
return feature;
});
if (feature) {
console.log("Feature found");
}
});
说明:
使用click事件中的映射实例(evt.map.forEachFeatureAtPixel)而不是根实例(此.map.forEachFeatureAtPixel)。谢谢您的帮助,我已经尝试了您的解决方案,效果很好。我还尝试了另一件事,我删除了一行:map:OlMap;更改:this.map=new OlMap({…in:var-map=new OlMap({…我已经删除了两个函数“map”中导致麻烦的所有“this.map”,以便像在我的app.component.ts文件中一样使用这两个函数(map.on('click')和map.on('pointermove')(函数(evt)和非(evt=>))this和non-this方法之间有区别吗?请提前感谢var-map=…
是一个局部变量,在组件的上下文中定义。它可以工作,因为在访问变量“map”时在任何地方,它都会进入上下文堆栈,直到找到它。但是,缺点是您无法从其上下文之外访问它,这在使用this.map时是可能的,它基本上定义了组件的属性(或写入this的上下文的任何内容。[…]
。无可否认,在JS中这是一个令人困惑的话题,值得了解一下,它是许多问题(我想也是潜在问题)的根源。顺便说一句,像您这样成功地使用局部变量是在箭头函数存在之前人们倾向于使用的解决方案之一。感谢您的帮助,我尝试了您的解决方案,效果很好。我还尝试了另一件事,我删除了行:map:OlMap;更改:this.map=new OlMap({…in:var map=new OlMap({…我已经删除了两个函数“map”中导致麻烦的所有“this.map”,以便像在我的app.component.ts文件中一样使用这两个函数(map.on('click')和map.on('pointermove'))(函数(evt)和非(evt=>)this和non-this方法之间有区别吗?请提前感谢var-map=…
是一个局部变量,在组件的上下文中定义。它可以工作,因为在访问变量“map”时在任何地方,它都会进入上下文堆栈,直到找到它。但是,缺点是您无法从其上下文之外访问它,这在使用this.map时是可能的,它基本上定义了组件的属性(或写入this的上下文的任何内容。[…]
。无可否认,这在JS中是一个令人困惑的话题,值得了解一下,它是许多问题的根源(我想也是潜在问题)。顺便说一句,在arrow函数存在之前,人们通常使用的解决方案之一就是像您这样成功地使用局部变量。