Skip to content
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

Animations: extract keyframes from styles #9623

Merged
merged 4 commits into from
May 31, 2017

Conversation

dvoytenko
Copy link
Contributor

Partial for #9129.

@dvoytenko dvoytenko requested a review from aghassemi May 30, 2017 22:21
class CSSKeyframesRuleDef {
constructor() {
/** @type {string} */
this.name;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to set these values, declaring them like this doesn't help the JS engine's internal structure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just the definition for closure, in place of extern. Per closure it's fine. The class itself is not used - only its type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you mark as an interface, then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried, but unfortunately can't. The underlying CSSRule is declared as a class, not interface. See this. This is kind of what our Def suffix means at this point. I'm going to contribute the same declarations to them, but we are slightly behind their externs version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, to remove this inconsistency, I just moved this declaration to our closure externs. So this should be now cleaner.

keyframeRule.keyText == 'from' ? 0 :
keyframeRule.keyText == 'to' ? 1 :
parseFloat(keyframeRule.keyText) / 100;
for (let j = 0; j < keyframeRule.style.length; j++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: store style in a variable. Some engines do weird things (like re-initialize) when accessing native objects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

return null;
}
// Exlcude AMP's own styles.
if (styleNode.hasAttribute('amp-boilerplate') ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could this be if (!styleNode.hasAttribute('amp-custom'))?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

if (rule.name == name && isEnabled(win, rule)) {
return buildKeyframes(keyframesRule);
}
} else if (rule.type == /* CSSMediaRule */ 4) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checking media match before the recursion should be a decent optimization

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I didn't do this is because there are potentially a lot more @media definitions than @keyframes. And checking in each case is somewhat expensive. So instead I first find a likely candidate @keyframes name and then check if its parents are enabled recursively.

for (let j = 0; j < keyframeRule.style.length; j++) {
const styleName = keyframeRule.style[j];
let propName = styleName;
if (styleName == 'animation-timing-function') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end with to account for vendor prefixes?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(TIL you could specify animation-timing-function in keyframe def, totally did not know this is possible)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Done.

const array = [];
for (let i = 0; i < keyframesRule.cssRules.length; i++) {
const keyframeRule = keyframesRule.cssRules[i];
const keyframe = {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cssRules are of type CSSRuleList, so it's not an array :(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map returns an object?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @aghassemi meant map on all, e.g. const array = keyframesRule.cssRules.map(rule => {}). Unfortunately cssRules is not an array and I thought we decided to avoid simple toArray conversions just for better for-loops?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants