-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable animation on inner nodes of the element and options #11173
base: master
Are you sure you want to change the base?
Conversation
@kurkle I have tried to implement the animation on properties of inner objects in element or options. This should address the following #11129 (comment) |
Set as draft to improve some checks |
Set ready for review |
This should be checked for performance regressions with large datasets |
@kurkle Good point. What do you suggest to address it? A test case with many elements as fixture or as specs? |
Just for info. I did a test, locally, with and without this PR, using a scatter chart with 10000 points. I measured the time from |
I'd try to find the breakking points, it used to be somewhere around million points on my old machine, but single dataset could not handle 500M points (if my memory serves). Anyway, with extreme numbers, possible regressions are easier to spot. Having this in CI is not trivial, because performance of the runnen varies greatly. Would need to run both, master and pr benchmarks in the same runner to get a hint of the performance impact of a pull request. For me the unknowns are: how to checkout and build both branches and how to report the results. Also the benchmarks itself require a good amount of consideration for not taking too long but still having good results. |
@kurkle I'll do additional tests (if I have time today). I'm not an expert on JS, you know, but I'm trying to use my knowledge on other languages to understand better where we could have a bottleneck based on the amount of data elements. To be honest, the first implementation I did locally, I was using a Map (and a different flow) instead of an array but, having to check the start name of the property during the scan of the values, I preferred to use an array. In the Animations Instead, in const matched = pathAnimatedProps.filter(item => item.prop.startsWith(prop));
if (matched.length) { With this code, for every animated property (also the normal ones) it returns an "array" (maybe new one, always empty if there is not any path property). To avoid it, I can change the PR going back to my first local impl where I had 2 cycles, 1 for path props and 1 for normal ones and where those "array" were not created. And I was using Map which should be better performed accessing by an indexed key. @kurkle what do you think? |
@kurkle have a look now. I did some checks and indeed Map is really more performed. The time spent to check if the animation property is flat one or not, is almost 0 (in my test with 10K). Now I try with more items (try to avoid to crash my FF). |
Test with 100K data elements (with the same conditions, FF opened after clearing cache).
|
rebased |
Conflicts: .size-limit.cjs
Conflicts: .size-limit.cjs
src/core/core.animations.js
Outdated
if (pathAnimatedProps.has(prop)) { | ||
pathAnimatedProps.forEach(function(item) { | ||
const newTarget = getInnerObject(target, item); | ||
const newValues = getInnerObject(values, item); | ||
if (newTarget && newValues) { | ||
manageItem(newTarget, newValues, item.prop, item.key); | ||
} | ||
}); | ||
} else { | ||
manageItem(target, values, prop); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like each "path" prop would be managed multiple times if there are multiple "path" props?
I think most of the new helpers could be omitted(?):
if (pathAnimatedProps.has(prop)) { | |
pathAnimatedProps.forEach(function(item) { | |
const newTarget = getInnerObject(target, item); | |
const newValues = getInnerObject(values, item); | |
if (newTarget && newValues) { | |
manageItem(newTarget, newValues, item.prop, item.key); | |
} | |
}); | |
} else { | |
manageItem(target, values, prop); | |
} | |
if (prop.includes('.')) { | |
const newTarget = resolveObjectKey(target, prop); | |
const newValues = newTarget && resolveObjectKey(values, prop); | |
if (newValues) { | |
manageItem(newTarget, newValues, prop, prop.split('.').pop()); | |
} | |
} else { | |
manageItem(target, values, prop); | |
} |
Did I miss something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kurkle I think the IF statement, you suggested, is wrong because the "prop" is not an item of "properties" animation configuration but one of the keys of the config object, therefore it will never have a dot.
The for cycle is on the config properties and not on the animation config one. That's why I used a map, reading the anim config, where the K is the fist part of the path (to check with the prop
) and the V the whole path (an object with prop and whole path as array).
EDIT: I have merged your suggestion anyway because I didn't recall all logic of this PR... 4 months is to big period for my memory, getting old. 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Furthermore, I cannot use resolveObjectKey
helper because this function is returning the value of the key and not the object where the key belongs to and therefore I cannot reuse the manageItem
function for both normal and path anim options, where the function needs the object with key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kurkle I have improved a bit removing the for Each statemenet. Anyway forEach should be needed. Need to time to review. Apologize
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kurkle now I recall why we need to scan the map but was wrong. Now I fixed.
The map has:
K = string = the first item of the path (i.e. 'font'
if animation properties config has 'font.size'
)
V = array = the array of objects with the animation properties config
The V is an array because you can configure more than 1 anim prop as path (i.e. ['font.size', 'font.weight']
)
Co-authored-by: Jukka Kurkela <[email protected]>
Fix #11172