问题
How do I make the last keyframe rotate my rectangle to a 35deg angle using popmotion pure?
https://codepen.io/matthewharwood/pen/XWmRPaK?editors=1111
HTML:
<div class="flex h-screen w-screen justify-center items-center">
<div class="portal-b">
<h1 class="left"></h1>
</div>
</div>
<button class="trigger fixed z-10 left-0 top-0">
B replace A
</button>
CSS:
.portal-b {
background: blue;
width: 1px;
height: 100px;
}
JS
const { easing, keyframes, styler } = window.popmotion;
const trigger = document.querySelector('.trigger');
const [_, portalB] = [document.querySelector('.portal-a'), document.querySelector('.portal-b')];
trigger.addEventListener('click', () => {
const portalS = styler(portalB);
keyframes({
values: [
{ translateX: 0, scaleX: 0, rotateZ: 0, transformOrigin: 'left center' },
{ translateX: 200, scaleX: 400, rotateZ: 0, transformOrigin: 'left center' },
{ translateX: 200, scaleX: 400, rotateZ: 90, transformOrigin: 'left center' },
],
duration: 3000,
easings: easing.easeInOut,
}).start(portalS.set)
})
回答1:
For this kind of problem I recommend stepping through the values in plain CSS in your browser. I found that the following CSS rule provided the final state you wanted
.portal-b {
background: blue;
width: 1px;
height: 100px;
transform: translateX(200px) rotate(-35deg) scaleX(400);
}
Then all you need is for your keyframes to step their way there, stating explicitly the values they expect like so
values: [
{ transform: "translateX(0px) rotate(0deg) scaleX(1)" },
{ transform: "translateX(200px) rotate(0deg) scaleX(400)" },
{ transform: "translateX(200px) rotate(-35deg) scaleX(400)"},
],
Here's your pen with my changes: https://codepen.io/kcerb/pen/wvKyWLv?editors=1111
回答2:
Here's a solution using Popmotion Pure, using the built-in transform options rather than a transform string: https://jsfiddle.net/rqjahwLt/
You're correct that the trouble is math-based. You need to set the dimensions of your rectangle in your CSS to be what you want at the end of the animation.
The trouble is Popmotion Pure will apply rotateZ
, before it applies scaleX
.
The solution:
The CSS uses width to set the dimensions desired at the end of the animation, and transform to set the dimensions desired at the beginning. If you set width: 1px
, then your rotateZ
is applied before scaleX
, which leaves you with a rhombus (i.e. skewed rectangle) instead of a rotated rectangle as desired.
.portal-b {
background: blue;
width: 300px; /* set the width to what you want at the end */
height: 100px;
transform: scaleX(0.001); /* transform the width to what you want at the start */
}
The Javascript then only has to un-set our transform: scaleX(0.001)
from above. The second keyframe will animate the rectangle from being width = 0.3px to width = 300px. Then the final keyframe rotates this to -35deg around the Z axis.
values: [
{ translateX: 0, scaleX: 0.001, rotateZ: 0, transformOrigin: 'left center' },
{ translateX: 200, scaleX: 1, rotateZ: 0, transformOrigin: 'left center' },
{ translateX: 200, rotateZ: -35, transformOrigin: 'center' },
],
来源:https://stackoverflow.com/questions/61472809/how-do-i-rotate-translate-and-scale-rectangle-from-a-keyframe-using-popmotion