我想基于下拉菜单上的选择使用“ zoomToMapObject”方法。 由于某种原因,开始缩放位置位于地图的中间,而不是设置的geoPoint。
(缩放有效,但是起始位置使它看起来有点奇怪。)
我当前的方法如下:
const duration = this.chart.zoomToMapObject(selectedPoloygon, this.countryZoom, true).duration;
setTimeout(() => {
this.chart.homeGeoPoint = geoPoint;
this.chart.homeZoomLevel = this.countryZoom;
}, duration);
this.handleCountrySelection(selectedPoloygon);
即使以某种方式设置homeGeoPoint / homeZoomLevel也不会影响接下来的缩放操作。
**更新:解决方法成本高昂(从1300个节点到超过9000个节点)**
我进一步研究了这个问题。当我将新的mapImageSeries推入地图时,似乎设置了中间点。
我目前的工作环境是在地图上绘制所有点并将其隐藏。 然后,在选择一个国家/地区后,将州更改为可见。
但是,这种方法非常昂贵。 DOM节点从1300上升到9100。
选择国家/地区并完成缩放动画后创建动画的另一种方法是 有效。但是由于地图每次都从某个中心位置开始,因此不可行吗?还是我做某事错误吗?
这是我当前未执行的代码:
// map.ts
export class MapComponent implements AfterViewInit, OnDestroy {
imageSeriesMap = {};
// ... standard map initialization ( not in zone of course )
// creating the "MapImages" which is very costly
this.dataService.getCountries().forEach(country => {
const imageSeriesKey = country.id;
const imageSeriesVal = chart.series.push(new am4maps.MapImageSeries()); // takes arround 1-2 ms -> 300 x 2 ~ 500 ms.
const addressForCountry = this.dataService.filterAddressToCountry(country.id); // returns "DE" or "FR" for example.
const imageSeriesTemplate = imageSeriesVal.mapImages.template;
const circle = imageSeriesTemplate.createChild(am4core.Circle);
circle.radius = 4;
circle.fill = am4core.color(this.colorRed);
circle.stroke = am4core.color('#FFFFFF');
circle.strokeWidth = 2;
circle.nonScaling = true;
circle.tooltipText = '{title}';
imageSeriesTemplate.propertyFields.latitude = 'latitude';
imageSeriesTemplate.propertyFields.longitude = 'longitude';
imageSeriesVal.data = addressForCountry.map(address => {
return {
latitude: Number.parseFloat(address.lat),
longitude: Number.parseFloat(address.long),
title: address.company
};
});
imageSeriesVal.visible = false;
this.imageSeriesMap[imageSeriesKey] = imageSeriesVal;
});
// clicking on the map
onSelect(country) {
this.imageSeriesMap[country].visible = true;
setTimeout( () => {
const chartPolygons = <any>this.chart.series.values[0];
const polygon = chartPolygons.getPolygonById(country);
const anim = this.chart.zoomToMapObject(polygon, 1, true, 1000);
anim.events.on('animationended', () => {});
this.handleCountrySelection(polygon);
}, 100);
});
}
handleCountrySelection(polygon: am4maps.MapPolygon) {
if (this.selectedPolygon && this.selectedPolygon !== polygon) {
this.selectedPolygon.isActive = false;
}
polygon.isActive = true;
const geoPoint: IGeoPoint = {
latitude: polygon.latitude,
longitude: polygon.longitude
};
this.chart.homeGeoPoint = geoPoint;
this.chart.homeZoomLevel = this.countryZoom;
this.selectedPolygon = polygon;
}
}
答案 0 :(得分:3)
感谢您的彻底跟进,我得以重现此问题。您遇到的问题是由以下任一步骤触发的:
MapImageSeries
推向图表MapImage
动态创建data
(也请注意,在您提供的pastebind中,data
需要一个数组,我必须在测试时更改它)在任一步骤中,图表将完全缩小,就像在重置自身一样。我将调查为什么会发生这种情况,以及是否可以更改它,因此在此期间,让我们看看下面的解决方法是否对您有用。
如果我们仅使用一个预先设置的MapImageSeries
(我看不出有多个MapImageSeries
的原因,那不是吗?),这可以消除问题1的发生。在data
的旁边,我们可以通过mapImageSeries.mapImages.create();
来create()
MapImages
manually,然后手动分配它们的latitude
和longitude
属性。这样一来,问题2也不会发生,我们看起来还不错。
这是一个演示版,其中包含pastebin的修改版本:
https://codepen.io/team/amcharts/pen/c460241b0efe9c8f6ab1746f44d666af
所做的更改是MapImageSeries
代码是从createMarkers
函数中取出的,因此它只发生一次:
const mapImageSeries = chart.series.push(new am4maps.MapImageSeries());
const imageSeriesTemplate = mapImageSeries.mapImages.template;
const circle = imageSeriesTemplate.createChild(am4core.Circle);
circle.radius = 10;
circle.fill = am4core.color('#ff0000');
circle.stroke = am4core.color('#FFFFFF');
circle.strokeWidth = 2;
circle.nonScaling = true;
circle.tooltipText = 'hi';
在这种情况下,无需将chart
传递给createMarkers
并返回它,所以我已经传递了polygon
来演示动态纬度/经度,我还分配了多边形数据(MapImage
的新dataItem.dataContext
,因此我们以后可以参考它。这是createMarkers
的新内容:
function createMarkers(polygon) {
console.log('calling createMarkers');
if ( !polygon.dataItem.dataContext.redDot) {
const dataItem = polygon.dataItem;
// Object notation for making a MapImage
const redDot = mapImageSeries.mapImages.create();
// Note the lat/long are direct properties
redDot.id = `reddot-${dataItem.dataContext.id}`;
// attempt to make a marker in the middle of the country (note how this is inaccurate for US since we're getting the center for a rectangle, but it's not a rectangle)
redDot.latitude = dataItem.north - (dataItem.north - dataItem.south)/2;
redDot.longitude = dataItem.west - (dataItem.west - dataItem.east)/2;;
dataItem.dataContext.redDot = redDot;
}
}
不需要animationended
事件或其他任何东西,它就可以了,因为不再有任何干扰您的代码的事件。您还应该恢复演奏。
这对您有用吗?
以下问题编辑之前的原始答案:
我无法复制您提到的行为。另外,我不知道this.countryZoom
是什么。
只需在按钮处理程序中使用以下内容...
chart.zoomToMapObject(polygon);
...无论当前的地图位置/ zoomLevel
,似乎都可以放大到该国家/地区。
如果在缩放动画结束后需要计时,zoomToMapObject
返回一个Animation
,则可以使用其'animationended'
事件,例如
const animation = this.chart.zoomToMapObject(selectedPoloygon, this.countryZoom, true);
animation.events.on("animationended", () => {
// ...
});
下面是一个示例,其中包含2个外部<button>
,其中一个用于缩放至美国,另一个用于缩放巴西:
https://codepen.io/team/amcharts/pen/c1d1151803799c3d8f51afed0c6eb61d
这有帮助吗?如果没有,您可以提供一个minimal example,以便我们复制您遇到的问题吗?