我解释我的情况:
我在用海图地图。代码强制向下搜索(强制更改映射),完成后,我必须搜索此新映射的所有点(注意drilldown-dodrilldown()`-不是我声明的函数,而是highcharts的函数属性)
问题是,在搜索这个新加载的地图的所有点之前,我必须等到钻取结束。我已经用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)
}
});
但这不是正确的方法。我不希望总是等待一秒钟,我希望代码在加载完成后执行。我试过使用async/await,但它不起作用。我试过的代码是:
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()
)代码异步加载映射,但代码继续执行(映射尚未加载)并失败(如果我不使用
setTimeout
)中。所以我需要等一下
多德里尔敦()
结束,加载异步映射结束,然后继续执行代码。
@wojciechchmiel的代码(已修改,我添加了异步加载,但它不工作)我一直在尝试实现这一点:
//@修正的wojciechchmil函数
(函数(h){
h.point.prototype.dodrilldown=函数(
_保持原样,
类别,
原始喷口
){
var系列=本系列,
chart=系列图表,
钻取=chart.options.drilldown,
i=(drilldown.series[])。长度,
系列选择;
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);
编辑5:
这是主要问题:
this.internalChart.series[0].data.forEach(data => { // FIND A POINT IN ALL MAP
if (data.name === SelectedName1) { // IF A POINT IS FOUND...
data.doDrilldown() // DRILLDOWN TO CHILD MAP
// HERE I MUST WAIT. WHEN DODRILLDOWN ENDS, CONTINUE WITH BELOW CODE
// UNDERSTANDING "ENDS" WHEN NEW MAP AND ITS DATA IS LOADED AND READY
this.internalChart.options.drilldown.series[0].data.forEach(dataInside => { // FOR EACH POINT OF NEW MAP (DRILLDOWN/CHILD MAP)
if (dataInside.name === SelectedName2) { // IF A POINT IS FOUND
this.setState({ province: dataInside['hc-key'] }); // CHANGE STATE
}
});
}
});