amcharts / amcharts5

The newest, fastest, and most advanced amCharts charting library for JavaScript and TypeScript apps.
338 stars 91 forks source link

Amcharts 5 Pyramid Chart Animation #1528

Closed canesen7 closed 3 months ago

canesen7 commented 3 months ago

Hi. I've a question about set data and yAxis. I try to animate pyramid chart with slider. I can do this with all categories like this.

https://github.com/amcharts/amcharts5/assets/67913330/7007fb28-abd9-4ec1-b104-80888d7fd28e

But when I try to category change with

chart.yAxes._values[0].data.setIndex(0, data)

https://github.com/amcharts/amcharts5/assets/67913330/236147bb-8122-4cd5-acb5-c8b3bbc514fc

As you can see it doesn't change the category.

So I tried to setAll instead of setIndex, this can set the category but animation not work clearly as you can see.

chart.yAxes._values[0].data.setAll(data)

https://github.com/amcharts/amcharts5/assets/67913330/847fdeee-3c80-4275-a4f4-bf7af7f82f3a

It doesn't work with clearly. What can I do for clear animation and change the yAxis category area.

Here is my code

slider.events.on("rangechanged", () => setTimeout(() => {
      let data = this.findAnimatedDatas()
      let animationKeys = Array.from(data.keys())
      let index = Math.round(slider.get("start", 0) * (animationKeys.length - 1));

      if (this.currentAnimation !== animationKeys[index]) {
        this.currentAnimation = animationKeys[index]

        if (this.state.columnMap?.animation?.data[0]) {
          animationText.setAll({
            text: getFormattedValue(this.state.columnMap?.animation?.data[0], animationKeys[index])
          })
        }
      } else {
        return
      }

      let convertedDataForAnimation = this.findAnimatedDatas(this.props.plugin.data)
      let animationValues = Array.from(convertedDataForAnimation.values())

      let convertedDataForOther = this.convertDataForOther(animationValues[index], this.state)
      let convertedDataForEither = this.convertDataForEither(animationValues[index], this.state)
      let convertedDataForOtherBefore = index !== 0 ? this.convertDataForOther(animationValues[index - 1], this.state) : convertedDataForOther
      let convertedDataForEitherBefore = index !== 0 ? this.convertDataForEither(animationValues[index - 1], this.state) : convertedDataForEither
      let isOtherAvailableProps = this.props.plugin.columnMap.other.data.length > 0 && !this.props.plugin.columnMap.other.data[0]?.isDisabledColumn
      let maxValue = 0

      if (chart.yAxes._values.length > 0) {
        chart.yAxes._values[0].data.setAll(convertedDataForOther)
      }

      if (chart.series._values.length > 0) {
        for (let i = 0; i < convertedDataForEither.length; i++) {
          if (chart.series._values[1].data._values.length <= convertedDataForEither.length) {
            if (chart.series._values[1].data._values[i] !== undefined) {             
              chart.series._values[1].data.setIndex(i, convertedDataForEither[i])
            } else {
              chart.series._values[1].data.insertIndex(i, convertedDataForEither[i])
            }
          } else {
            chart.series._values[1].data.removeIndex(convertedDataForEitherBefore.length - 1)

            if (chart.series._values[1].data._values[i] !== undefined) {
              chart.series._values[1].data.setIndex(i, convertedDataForEither[i])
            } else {
              chart.series._values[1].data.insertIndex(i, convertedDataForEither[i])
            }
          }

          let convertedDataEitherData = isOtherAvailableProps ? -convertedDataForEither[i].either : convertedDataForEither[i].either

          if (maxValue < convertedDataEitherData) {
            maxValue = convertedDataEitherData
          }
        }

        for (let i = 0; i < convertedDataForOther.length; i++) {
          if (chart.series._values[0].data._values.length <= convertedDataForOther.length) {
            if (chart.series._values[0].data._values[i] !== undefined) {
              chart.series._values[0].data.setIndex(i, convertedDataForOther[i])
            } else {
              chart.series._values[0].data.insertIndex(i, convertedDataForOther[i])
            }
          } else {
            chart.series._values[0].data.removeIndex(convertedDataForOtherBefore.length - 1)

            if (chart.series._values[0].data._values[i] !== undefined) {
              chart.series._values[0].data.setIndex(i, convertedDataForOther[i])
            } else {
              chart.series._values[0].data.insertIndex(i, convertedDataForOther[i])
            }
          }

          if (maxValue < convertedDataForEither[i].other) {
            maxValue = convertedDataForEither[i].other
          }
        }
      }
    }));
canesen7 commented 3 months ago

@martynasma have you any idea for this problem? How can I set the category chart instead of setAll for smooth animation?

martynasma commented 3 months ago

Maybe you can just override the label directly:

xAxis.dataItems[1].get("label").setAll({
  text: "New label"
});
canesen7 commented 3 months ago

Yeah this can change the category axis label but y axis data's category not equals with serie data in animation. So second data's bar not shown. I need to set yAxis's data without setAll @martynasma

martynasma commented 3 months ago

I'm not entirely sure I understand what you're trying to achieve.

With each "slide" you want to change both number of categories and their names, but still want to animate the values?

canesen7 commented 3 months ago

Yeah, sorry for my bad english. This is exactly what I want. I want the change values and category axis with each slide and smooth animated values. Like last video but with smooth animations @martynasma

martynasma commented 3 months ago

Well, if you want to animate values, you need the data item to stay the same.

The easiest way to do that would be to just override label text for an existing item, then update data item's values.

I'm not aware of any other workaround.

canesen7 commented 3 months ago

Yeah I understand. I encounter this problem with serie values. setIndex, insertIndex and removeIndex was solved this problem. Data items not stay the same but I've smooth animations so I think the workaround is that. Instead of setall, change the data items one by one may be the workaround. So I tried exactly same the yAxis data items but insertIndex, setIndex or removeIndex not work this class. Why is that? @martynasma

canesen7 commented 3 months ago

In 5.9.9 version setIndex, removeIndex and insertIndex works correctly, so this is solved my issue.