我解释一下我的情况:
我正在使用HighCharts地图。代码强制执行DrillDown(强制更改地图),完成该操作后,我必须在此新地图的所有点内进行搜索(注意DrillDown -doDrilldown()`不是我声明的函数,而是一个函数)属性的属性)
问题在于,我必须等到DrillDown结束后才能搜索此新加载的地图的所有点。我已经使用SetTimeOut函数解决了它:
var names = name.split(', ');
// Find point in countries map
this.internalChart.series[0].data.forEach(data => {
if (data.name === names[1]) {
data.doDrilldown() // FORCE DRILLDOWN. HERE I MUST WAIT
// WAITING WITH A TIMEOUT IS WORKING
setTimeout(() => {
// CODE THAT MUST BE EXECUTED ONCE MAP IS LOADED
this.state.loadedMaps.length > 0 && this.internalChart.options.drilldown.series[0].data.forEach(dataInside => {
if (dataInside.name === names[0]) {
this.setState({
province: dataInside['hc-key'],
loading: false
});
}
});
}, 1000)
}
});
但这不是正确的方法。我不想总是等待一秒钟,我希望代码在加载完成后立即执行。我尝试使用异步/等待,但无法正常工作。我尝试过的代码是:
var names = name.split(', ');
// Find point in countries map
this.internalChart.series[0].data.forEach(data => {
if (data.name === names[1]) {
(async () => { await data.doDrilldown(); })() //HERE I MUST WAIT FOR DO THIS ACTION
.then(()=>{
// ONCE DONE BELOW ACTION, EXECUTE NEXT CODE:
this.internalChart.options.drilldown.series[0].data.forEach(dataInside => {
if (dataInside.name === names[0]) {
this.setState({
//country: country,
province: dataInside['hc-key'],
loading: false
});
}
});
});
}
});
任何人都知道我该如何解决我的问题?
谢谢。
编辑1:
我举了一个代表问题的例子。可以在这里找到:JSFiddle example
编辑2:
我需要知道.doDrilldown()
何时完成。此函数将加载新的地图及其数据,因此当加载新的地图和新数据时,代码应继续执行。我正在加载新的向下钻取系列,例如:
// Import all map data
import(`./maps/${point['hc-key']}-all.geo`).then(mapData => {
// Set data of the map
var data = [];
mapData.default.features.forEach((element, i) => {
data.push({ 'hc-key': element.properties['hc-key'], 'name': element.properties.name, 'value': 0 });
});
// Create the new drilldown serie
try {
var drilldownSerie = {
id: point['hc-key'],
mapData: mapData.default,
data: data,
joinBy: 'hc-key',
name: mapData.default.title,
allowPointSelect: true,
borderColor: '#ffffff',
borderWidth: 1.2,
states: {
hover: {
color: this.props.geoColor
},
select: {
color: this.props.geoColor
}
},
dataLabels: {
enabled: true,
format: '{point.name}'
},
point: {
events: {
click: (event) => {
this.props.handleZoneChange(event.point);
this.setState({
selectedPoint: event.point
});
console.log("Click")
console.log(this.state.selectedPoint)
console.log("---")
}
}
}
};
// Add the new drilldown serie
this.internalChart.addSeriesAsDrilldown(point, drilldownSerie);
} catch (err) {
console.log(err.message)
}
}).catch((err) => {
console.log(err.message)
})
编辑3:
如果需要的话,这里是完整的代码。
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import Highcharts from 'highcharts'
import HC_map from 'highcharts/modules/map'; //module
import HC_drilldown from 'highcharts/modules/drilldown'; //module
import HighchartsReact from 'highcharts-react-official';
import Button from '@material-ui/core/Button';
import worldMap, { dataWorldMap } from "./maps/worldMap.js";
HC_map(Highcharts); //init module
HC_drilldown(Highcharts) //init module
Highcharts.setOptions({
lang: {
drillUpText: '◁ Volver a: {series.name}'
}
});
class GeoZoneChart extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
selectedPoint: ''
};
}
geoZoneOptions = {
chart: {
map: worldMap,
events: {
drilldown: (event) => {
this.handleMapChange(event.point);
},
drillup: (event) => {
setTimeout(() => {
console.log("DU")
console.log(this.state.selectedPoint)
console.log("---")
}, 1000)
},
}
},
title: {
text: ""
},
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
colorAxis: {
min: 0,
max: 0,
minColor: "#f7f7f7",
maxColor: "#e2e2e2"
},
tooltip: {
enabled: false
},
legend: {
enabled: false
},
exporting: { enabled: false },
series: [{
mapData: worldMap,
data: dataWorldMap,
joinBy: 'hc-key',
name: 'Mundo',
allowPointSelect: true,
borderColor: '#ffffff',
borderWidth: 1.2,
states: {
hover: {
color: this.props.geoColor
},
select: {
color: this.props.geoColor
}
},
dataLabels: {
enabled: true,
format: '{point.name}'
},
}, {
name: 'Separators',
type: 'mapline',
color: 'silver',
showInLegend: false,
enableMouseTracking: false
}],
drilldown: {
activeDataLabelStyle: {
textDecoration: 'none',
color: 'black'
},
series: []
}
}
internalChart = undefined;
handleMapChange = (point) => {
// Import all map data
import(`./maps/${point['hc-key']}-all.geo`).then(mapData => {
// Set data of the map
var data = [];
mapData.default.features.forEach((element, i) => {
data.push({ 'hc-key': element.properties['hc-key'], 'name': element.properties.name, 'value': 0 });
});
// Create the new drilldown serie
try {
var drilldownSerie = {
id: point['hc-key'],
mapData: mapData.default,
data: data,
joinBy: 'hc-key',
name: mapData.default.title,
allowPointSelect: true,
borderColor: '#ffffff',
borderWidth: 1.2,
states: {
hover: {
color: this.props.geoColor
},
select: {
color: this.props.geoColor
}
},
dataLabels: {
enabled: true,
format: '{point.name}'
},
point: {
events: {
click: (event) => {
this.props.handleZoneChange(event.point);
this.setState({
selectedPoint: event.point
});
console.log("Click")
console.log(this.state.selectedPoint)
console.log("---")
}
}
}
};
// Add the new drilldown serie
this.internalChart.addSeriesAsDrilldown(point, drilldownSerie);
// Select all map
//this.selectAll();
} catch (err) {
console.log(err.message)
}
}).catch((err) => {
console.log(err.message)
})
}
componentDidMount = () => {
// Recover and set selected zone if exist
this.props.defaultZone && this.selectRegionByName(this.props.defaultZone)
}
selectRegionByName = (name) => {
if (!name.includes(', ')) {
// Find point in global map
this.internalChart.series[0].data.forEach(data => {
if (data.name === name) {
// Select the point
data.select(true, true)
}
});
} else {
var names = name.split(', ');
// Find point in countries map
this.internalChart.series[0].data.forEach(data => {
if (data.name === names[1]) {
// Drilldown on the map
data.doDrilldown();
setTimeout(() => {
this.internalChart.series[0].data.forEach(dataInside => {
if (dataInside.name === names[0]) {
// Select the point
dataInside.select(true, true)
}
});
}, 100)
}
});
}
}
afterChartCreated = (chart) => {
this.internalChart = chart;
}
selectAll = () => {
this.internalChart.series[0].data.forEach(data => {
data.select(true, true);
});
this.props.handleSelectAllZones(this.internalChart.series[0].name);
}
componentWillUnmount = () => {
this.internalChart.series[0].data.forEach(data => {
data.select(false, false);
});
}
render() {
return (
<Fragment>
<HighchartsReact
highcharts={Highcharts}
constructorType={'mapChart'}
options={this.geoZoneOptions}
callback={this.afterChartCreated}
/>
<Button
variant="contained"
color="primary"
onClick={this.selectAll}
style={{
marginTop: -28,
padding: 0,
paddingLeft: 10,
paddingRight: 10,
float: "right",
backgroundColor: this.props.geoColor,
'&:hover': {
backgroundColor: this.props.geoDarkColor
}
}}
>
Seleccionar todo
</Button>
</Fragment >
);
}
}
GeoZoneChart.propTypes = {
handleZoneChange: PropTypes.func
};
export default GeoZoneChart;
编辑4:
我想实现在doDrilldown()
之后执行了代码。我的问题是,当我在某个点(point.doDrilldown()
上进行向下钻取时,代码会异步加载地图,但代码会继续执行(地图尚未加载)并失败(如果我不使用{{1 }})。因此,我需要等待setTimeout
结束,加载异步映射结束,然后继续执行代码。
@WojciechChmiel的代码(已修改,我添加了异步负载,但它不起作用),我一直在尝试实现以下目的:
// @WojciechChmiel函数已修改 (函数(H){ H.Point.prototype.doDrilldown = function( _holdRedraw, 类别, originalEvent ){ var series = this.series, 图表= series.chart, 向下钻取= chart.options.drilldown, i =(drilldown.series || [])。length, seriesOptions;
doDrilldown()
编辑5:
这是主要问题:
if (!chart.ddDupes) {
chart.ddDupes = [];
}
while (i-- && !seriesOptions) {
if (
drilldown.series[i].id === this.drilldown &&
chart.ddDupes.indexOf(this.drilldown) === -1
) {
seriesOptions = drilldown.series[i];
chart.ddDupes.push(this.drilldown);
}
}
// Fire the event. If seriesOptions is undefined, the implementer can check
// for seriesOptions, and call addSeriesAsDrilldown async if necessary.
H.fireEvent(chart, 'drilldown', {
point: this,
seriesOptions: seriesOptions,
category: category,
originalEvent: originalEvent,
points: (
category !== undefined &&
this.series.xAxis.getDDPoints(category).slice(0)
)
}, function(e) {
var chart = e.point.series && e.point.series.chart,
seriesOptions = e.seriesOptions;
if (chart && seriesOptions) {
if (_holdRedraw) {
chart.addSingleSeriesAsDrilldown(e.point, seriesOptions);
} else {
chart.addSeriesAsDrilldown(e.point, seriesOptions);
}
}
// My code should go here?
else {
console.log(e.point)
// Import all map data
import(`./maps/${e.point['hc-key']}-all.geo`)
.then(mapData => {
// Set data of the map
var data = [];
mapData.default.features.forEach((element, i) => {
data.push({ 'hc-key': element.properties['hc-key'], 'name': element.properties.name, 'value': 0 });
});
// Create the new drilldown serie
try {
var drilldownSerie = {
id: e.point['hc-key'],
mapData: mapData.default,
data: data,
joinBy: 'hc-key',
name: mapData.default.title,
allowPointSelect: true,
borderColor: '#ffffff',
borderWidth: 1.2,
states: {
hover: {
color: this.props.geoColor
},
select: {
color: this.props.geoColor
}
},
dataLabels: {
enabled: true,
format: '{point.name}'
},
point: {
events: {
click: (event) => {
this.props.handleZoneChange(event.point);
this.setState({
selectedPoint: event.point['hc-key']
});
}
}
}
};
// Add the new drilldown serie
this.internalChart.addSeriesAsDrilldown(e.point, drilldownSerie);
// Select all map
//this.selectAll();
} catch (err) {
console.log(err.message)
}
}).catch((err) => {
console.log(err.message)
})
}
});
console.log('After drilldown');
}
})(Highcharts);
答案 0 :(得分:0)
这里是H.Point.prototype.doDrilldown
的包装:
(function(H) {
H.Point.prototype.doDrilldown = function(
_holdRedraw,
category,
originalEvent
) {
var series = this.series,
chart = series.chart,
drilldown = chart.options.drilldown,
i = (drilldown.series || []).length,
seriesOptions;
if (!chart.ddDupes) {
chart.ddDupes = [];
}
while (i-- && !seriesOptions) {
if (
drilldown.series[i].id === this.drilldown &&
chart.ddDupes.indexOf(this.drilldown) === -1
) {
seriesOptions = drilldown.series[i];
chart.ddDupes.push(this.drilldown);
}
}
// Fire the event. If seriesOptions is undefined, the implementer can check
// for seriesOptions, and call addSeriesAsDrilldown async if necessary.
H.fireEvent(chart, 'drilldown', {
point: this,
seriesOptions: seriesOptions,
category: category,
originalEvent: originalEvent,
points: (
category !== undefined &&
this.series.xAxis.getDDPoints(category).slice(0)
)
}, function(e) {
var chart = e.point.series && e.point.series.chart,
seriesOptions = e.seriesOptions;
if (chart && seriesOptions) {
if (_holdRedraw) {
chart.addSingleSeriesAsDrilldown(e.point, seriesOptions);
} else {
chart.addSeriesAsDrilldown(e.point, seriesOptions);
}
}
});
console.log('After drilldown');
}
})(Highcharts);
如您所见,此功能是同步的。如果您使用它异步添加数据,请添加一个复制它的示例。