When we use <ngx-charts-number-card> we need to specify results property as chart data, and animations property is default to true to enable animation effects. However, if we change results very quickly (suppose we change value inside results from 0 to 100), the card would remain to display 0 rather the 100 we want.
To Reproduce
Steps to reproduce the behavior (GIST):
it would check if we initialize chart (as well as hasValue) and then call startCount in 20ms later (with setTimeout API), in which we establish a requestAnimationFrame calling (fixed to 1000ms as the third input parameter to count method):
but the problem is if we do update the input results within 1000ms (which is expected as the end of animation), we may have the animations already start but with following condition to be false:
so updated results may get updated first in this.scaleText() within update() calling, but get back to old value with animation still runs with callback, since we update this.initialized immediately after we start the counting animation.
A solution and it's expected result is to set this.initialized to true only if the animation ends, which is 1000ms later, and to do so, we may need another parameter to count to specify another callback when this condition to evaluate to false:
Describe the bug
When we use
<ngx-charts-number-card>
we need to specifyresults
property as chart data, andanimations
property is default to true to enable animation effects. However, if we changeresults
very quickly (suppose we change value insideresults
from 0 to 100), the card would remain to display0
rather the100
we want.To Reproduce Steps to reproduce the behavior (GIST):
data
as an input property to update component and setanimations
to true ( https://gist.github.com/hijiangtao/5ebc7559d7fd781320258465341b7eac#file-ux-text-card-component-ts );setTimeout
API)Demo
https://gist.github.com/hijiangtao/5ebc7559d7fd781320258465341b7eac
ngx-charts version
v16.0.0
Additional context
Here's the problem I found in codes, as well as my solution to it.
It's a bug caused by
animations
property mixed withinitialized
property, since the animation duration is set to a fixed time as 1000ms.Looking into
update()
part in https://github.com/swimlane/ngx-charts/blob/48dc53364602cc08269ee0fa0ae36e386c040b20/projects/swimlane/ngx-charts/src/lib/number-card/card.component.ts#L148-L154it would check if we initialize chart (as well as
hasValue
) and then callstartCount
in 20ms later (with setTimeout API), in which we establish arequestAnimationFrame
calling (fixed to 1000ms as the third input parameter tocount
method):https://github.com/swimlane/ngx-charts/blob/48dc53364602cc08269ee0fa0ae36e386c040b20/projects/swimlane/ngx-charts/src/lib/number-card/card.component.ts#L184
but the problem is if we do update the input
results
within 1000ms (which is expected as the end of animation), we may have the animations already start but with following condition to be false:https://github.com/swimlane/ngx-charts/blob/48dc53364602cc08269ee0fa0ae36e386c040b20/projects/swimlane/ngx-charts/src/lib/number-card/card.component.ts#L166
then it wouldn't cancel
this.animationReq
sothis.value
would become unstable in rendering html:https://github.com/swimlane/ngx-charts/blob/48dc53364602cc08269ee0fa0ae36e386c040b20/projects/swimlane/ngx-charts/src/lib/number-card/card.component.ts#L61
In other words, we can change
this.value
in many places, and trigger Angular change detection in boththis.scaleText()
:https://github.com/swimlane/ngx-charts/blob/48dc53364602cc08269ee0fa0ae36e386c040b20/projects/swimlane/ngx-charts/src/lib/number-card/card.component.ts#L205
and requestAnimationFrame's callback:
https://github.com/swimlane/ngx-charts/blob/48dc53364602cc08269ee0fa0ae36e386c040b20/projects/swimlane/ngx-charts/src/lib/number-card/card.component.ts#L180
so updated results may get updated first in
this.scaleText()
withinupdate()
calling, but get back to old value with animation still runs with callback, since we updatethis.initialized
immediately after we start the counting animation.A solution and it's expected result is to set
this.initialized
to true only if the animation ends, which is 1000ms later, and to do so, we may need another parameter tocount
to specify another callback when this condition to evaluate to false:https://github.com/swimlane/ngx-charts/blob/48dc53364602cc08269ee0fa0ae36e386c040b20/projects/swimlane/ngx-charts/src/lib/common/count/count.helper.ts#L44
I would like to PR for it if you confirm this bug.