Динамически изменяющаяся легенда AmCharts4

Столбцы, которые имеют (максимальное дополнительное хеджирование), иногда находятся на диаграмме, а иногда это не определяется динамическими данными, которые можно постоянно изменять с помощью перетаскиваемой полосы над диаграммой. Я хочу, чтобы легенда диаграммы удаляла эти элементы, когда их нет, и возвращала их, когда они были на диаграмме. В настоящее время это работает над версией диаграммы AmCharts3, но я их обновляю.

var chart = am4core.create("fxExposureHedgingChart", am4charts.XYChart);


let title = chart.titles.create();
title.text = this.props.title;
title.fontSize = 25;
title.marginBottom = 30;

chart.data = this.props.dataProvider;
chart.dateFormatter.inputDateFormat = "yyyy-MM-dd";
chart.orderByField = "name"

var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "category";
categoryAxis.title.text = "Time";
categoryAxis.renderer.startLocation = 0;
categoryAxis.renderer.cellStartLocation = 0.10;
categoryAxis.renderer.cellEndLocation = 0.90;
categoryAxis.renderer.labels.template.location = 0.5 ;
categoryAxis.renderer.labels.template.wrap = false;
categoryAxis.renderer.labels.template.truncate = false;

categoryAxis.renderer.minGridDistance = 30;
categoryAxis.layout = "horizontal";
// Create value axis
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.title.text = "Amount " + this.state.displayCurrency;
valueAxis.max = 140000;
valueAxis.min = 0;


let valueAxis2 = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis2.title.text = "Rate";
valueAxis2.renderer.opposite = true;
valueAxis2.min = 1.1000;
valueAxis2.max = 1.4500;


let createColumnSeries = () => {
    var series = chart.series.push(new am4charts.ColumnSeries());
    series.dataFields.valueY = "exposure";
    series.dataFields.categoryX = "category";
    series.name = "Forecasted Cashflows";
    series.yAxis = valueAxis;
    series.columns.template.width = am4core.percent(85);
    series.stacked = false;

    series.tooltip.dy = -8;
    series.tooltip.pointerOrientation = "vertical";
    var columnTemplate = series.columns.template;
        columnTemplate.column.fillOpacity = 0.8;
        columnTemplate.tooltipText = "{name} ({category}): {valueY}";
        columnTemplate.tooltipY = 0;
    var columnHoverState = columnTemplate.column.states.create("hover");
        columnHoverState.properties.fillOpacity = 1;
        columnHoverState.properties.cornerRadiusTopLeft = 35;
        columnHoverState.properties.cornerRadiusTopRight = 35;

    return series;
}

let createLineSeries1 = () => {
    var series = chart.series.push(new am4charts.LineSeries());
        series.dataFields.valueY = "achieveableRate";
        series.dataFields.categoryX = "category";
        series.name = "Achieveable Rate";
        series.tooltipText = "{valueY.value}";
        series.strokeWidth = 2;
        series.yAxis = valueAxis2;

        let bullet = series.bullets.push(new am4charts.Bullet());
        let square = bullet.createChild(am4core.Rectangle);
        square.width = 5;
        square.height = 5;
        square.horizontalCenter = "middle";
        square.verticalCenter = "middle";
        series.bullets.getIndex(0).tooltipText = "{name}: {valueY}";



        return series;
}




let getDealGraphInfo = (classIds,data) =>{
    let maxHedgingClassIDs = classIds.map( id => (data.reduce((accum, row) => accum+ (row["maxAmount_"+id]),0)) > 0 ? id: null);
    let maxAmounts = maxHedgingClassIDs.map((id, index) => {

        if(id === null){} else {
            let HedgingSeries = chart.series.push(new am4charts.ColumnSeries());
            HedgingSeries.dataFields.valueY = "maxAmount_" + id;
            HedgingSeries.dataFields.categoryX = "category";
            HedgingSeries.name = classIDtoDisplayName(id).replace(/FX\s/,"") + " (Maximum Additional Hedging)";
            HedgingSeries.tooltip.dy = -8;
            HedgingSeries.tooltip.pointerOrientation = "vertical";
            HedgingSeries.columns.template.width = am4core.percent(70);
            HedgingSeries.id = classIDtoDisplayName(id).replace(/\s/g,"").toLowerCase() + "_maxAmount";
            HedgingSeries.stacked = true;

            var columnTemplate = HedgingSeries.columns.template;
            columnTemplate.column.fillOpacity = 0.8;
            columnTemplate.tooltipText = HedgingSeries.name;
            columnTemplate.tooltipY = 0;
    }}).filter(c => c);


    return classIds.map((id, index) => {
        let Series = chart.series.push(new am4charts.ColumnSeries());
        Series.dataFields.valueY = "amount_" + id;
        Series.dataFields.categoryX = "category";
        Series.name = classIDtoDisplayName(id).replace(/FX\s/,"");
        Series.tooltip.dy = -8;
        Series.tooltip.pointerOrientation = "vertical";
        Series.columns.template.width = am4core.percent(70);
        Series.id = classIDtoDisplayName(id).replace(/\s/g,"").toLowerCase();
        Series.strokewidth = 1;
        Series.stacked = true;

        var columnTemplate = Series.columns.template;
        columnTemplate.column.fillOpacity = 0.8;
        columnTemplate.tooltipText = Series.name;
        columnTemplate.tooltipY = 0;

        return Series;

    }).concat(maxAmounts).sort((a,b) => (a.name < b.name ? -1:1));

}

let budgetRateName = getBudgetRateName(this.props.budgetRate);

getDealGraphInfo(this.props.dealClassIds,this.state.data).concat(createColumnSeries(),
createLineSeries1(),
createLineSeries2(),
createLineSeries3(),
createLineSeries4(budgetRateName)
).sort((a,b) => (a.name < b.name ? -1:1));

    chart.legend = new am4charts.Legend();
    chart.legend.itemContainers.template.paddingTop = 5;
    chart.legend.itemContainers.template.paddingBottom = 5;
    chart.legend.labels.template.wrap = true;
    chart.legend.labels.template.maxWidth = 350;
    chart.legend.labels.template.truncate = true;
    chart.legend.useDefaultMarker = true;
    chart.exporting.menu = new am4core.ExportMenu();
    var plugin = chart.plugins.push(new am4plugins_annotation.Annotation());



    var markerTemplate = chart.legend.markers.template
    markerTemplate.width = 10;
    markerTemplate.height = 10;

    this.setState({chart: chart})
  }

  componentDidUpdate(oldProps, prevState){
    if (oldProps.dataProvider !== this.props.dataProvider){
        this.state.chart.data = this.props.dataProvider;
    } 
}

  componentWillUnmount() {
    if (this.chart) {
      this.chart.dispose();
    }
  }

getDealGraphInfo - это добавляемые / удаляемые столбцы. Обратите внимание, что у объекта всегда есть эти столбцы, но когда они не имеют значения, он устанавливается на «null», в противном случае он имеет значение. Когда я перетаскиваю полосу над диаграммой, я использую componentDidUpdate для изменения данных на диаграмме. Так что я считаю, что здесь можно чем-то заняться.


person AlexSoftware    schedule 12.11.2019    source источник
comment
Итак, я обнаружил, что при создании диаграммы создается легенда с конкретными данными. Но легенда не обновляется по мере добавления / удаления данных. Даже сама диаграмма не обновляется при добавлении / удалении данных. Под этим я подразумеваю, что диаграмма обновит данные внутри себя, но если необходимо добавить новый столбец, диаграмма не будет добавлять его, вместо этого она сохранит те же столбцы, с которыми она была создана.   -  person AlexSoftware    schedule 13.11.2019


Ответы (1)


Я нашел временное исправление, когда в componentDidUpdate я удаляю диаграмму и воссоздаю всю диаграмму, когда получаю новые реквизиты. Но это очень тормозит при использовании ползунка. Я бы предпочел просто обновлять легенду / данные в диаграмме, чем заново создавать диаграмму каждый раз.

person AlexSoftware    schedule 13.11.2019