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

Rotate #34

Open
babakness opened this issue May 19, 2015 · 5 comments
Open

Rotate #34

babakness opened this issue May 19, 2015 · 5 comments

Comments

@babakness
Copy link

Any chance this will work with certain CSS transformations like rotate, i.e.:

#a{
  ...
}

#b{
  ...
  transform: rotate(90deg);
}

Also, rotating twice from beginning to end on something like

#b{
  ...
  transform: rotate(720deg);
}

would be super cool!

@Rich-Harris
Copy link
Owner

@babakness Good question! I've been a little quite on this repo lately as I've been working on some other projects, but I do have an experimental branch which gets us halfway there.

It's a little tricky though. Because the elements could be inside layers of elements with their own transformations, and they then need to be transformed further so that they can move as one, it's not practical to describe the start and end transformations as a series of rotate/scale/translate commands - instead we have to multiply transformation matrices.

This makes rotation difficult, because if you interpolate between two transformation matrices that describe different rotations, the effect doesn't look like rotation, because the corners of the box travel in a straight line to their destination. It looks more like shearing than rotation. The best we can hope for is to use matrix decomposition to figure out a path that looks more natural. That's my plan, anyway. (A long time ago, I wrote a small matrix utility library which does decomposition among other things. Hopefully the code still works...)

This is what the experimental branch looks like right now:

transform

With matrix decomposition it should look slightly better. (The next trick will be to get it working with 3d transforms...)

Unfortunately, rotating 720 degrees is totally impossible with this technique. As soon as you go past 180 degrees you lose information (i.e. 240 degrees is assumed to mean -120 degrees, and 360 degrees means no change) - there's just no way to recover it. I've wondered about providing a hook for a custom interpolation function which would be able to do that sort of ad hoc transformation - possibly in a future version.

@babakness
Copy link
Author

@Rich-Harris Cool! I think I understand what you're saying.

transform: rotate(45deg);
transform: rotate(720deg);
transform: matrix(0.707106781186549, 0.707106781186547, -0.707106781186547, 0.707106781186549, 0, 0);

are all the same. I was thinking that the text of the original css would be preserved but its not!

The shearing effect looks great too, more like morphing than rotating. It has a more liquid feel. Actually wiggling and jiggling the end points of the animation, sort of like the demos do spatially, but with a shear effect, would be lively and organic.

Thanks for the info, I learned from this!

@Martin-Pitt
Copy link

Hi @Rich-Harris, last year I began working on a material design inspired view transition library and one of the big challenges was animating transforms.

Actually, it turns out that it IS practical to interpret start/end transformations as a series of transform function as that was the point of transform function lists.

Here is the URL to the official W3C standard on interpolation transforms, along with a snippet of the important bit:
http://www.w3.org/TR/css3-transforms/#interpolation-of-transforms

Four rules for interpolating transform lists:

  • If both lists are none, return nothing.
  • If one of the lists is none, create a equivalent identity list, continue to next rule.
  • If both lists have the same amount of arguments (having a common primitive), interpolate each pair of transform function and return computed value.
  • else in worst case, convert both lists to matrices and interpolate those, return computed value.

Here is a library I had worked on in the past that interpolated transform strings using the above rules:
https://gist.github.com/Martin-Pitt/3a6f2168a03a7502575a
It is incomplete and only supports common set of transform functions but has worked really well for me.

Recently for my library though and for future proofing I have switched over entirely to the Web Animations API, which has it's own handler which I would also recommend checking out:
https://github.com/web-animations/web-animations-js/blob/master/src/transform-handler.js

On my day job as a mobile web app developer I have found the libraries efficient enough to create very smooth animations.

@Rich-Harris
Copy link
Owner

@Martin-Pitt Unfortunately the problem is that we don't have access to the original transform strings - ramjet has to use the transform reported by getComputedStyle (otherwise you can only detect transforms applied as inline styles), and getComputedStyle converts everything to matrix(...). I guess you could try and figure things out on a 'best effort' basis (reading inline styles and <style> tags, making AJAX requests for linked stylesheets and parsing their contents), but it would add a huge amount of complexity, where as a hook that allowed developers to supply their own interpolator would solve the problem (at the cost of a little bit more work for the developer) without any of that brittle magic.

@Martin-Pitt
Copy link

I just ran this script in the console for github here:

var test = document.querySelector('.comment-form-textarea');
var s = document.styleSheets.length;
while(s-->0)
{
  var styleSheet = document.styleSheets[s];
  var r = styleSheet.cssRules.length;
  while(r-->0)
  {
    var rule = styleSheet.cssRules[r];
    if(test.matches(rule.selectorText))
    {
      console.log(rule.selectorText, rule.style.transform);
      break;
    }
  }
}

output

.comment-form-textarea translateZ(0px)

Do-able?
Compatibility for .cssRules: http://www.quirksmode.org/dom/w3c_css.html#t10

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

No branches or pull requests

3 participants