css高度动画_动画高度-正确的方法

css高度动画

Let’s be honest. Animating height can be a huge pain. For me, it’s been a constant battle between wanting to have nice animations, and not being willing to pay the enormous performance cost associated with animating height. Now — that’s all done.

说实话。 动画高度可能是一个巨大的痛苦。 对我来说,一直是想要拥有出色的动画与不愿意付出与动画高度相关的巨大性能成本之间的不懈斗争。 现在-全部完成。

It all started when I was working on my side project — a resume builder where you can share links to your resume that are only active for a certain period of time.

这一切都始于我在我的副项目上的工作-简历生成器,您可以在其中共享仅在特定时间段内处于活动状态的简历链接。

I wanted to have a nice animation for all of the sections in the resume, and I built a react component that performed the animation. However, I soon discovered that this component absolutely destroyed performance on lower end devices and in some browsers. Hell, even my high end Macbook pro was struggling to keep smooth fps on the animation.

我想为简历中的所有部分制作一个漂亮的动画,并构建了一个执行动画的react组件。 但是,我很快发现该组件完全破坏了低端设备和某些浏览器的性能。 天哪,甚至我的高端Macbook Pro都在努力使动画保持流畅的fps。

The reason for this is of course that animating the height property in CSS causes the browser to perform expensive layout and paint operations on every frame. There’s a fantastic section on rendering performance over at Google Web Fundamentals, I suggest you check it out.

原因当然是在CSS中设置height属性动画会导致浏览器在每一帧上执行昂贵的布局和绘制操作。 Google Web Fundamentals上有一个精彩的渲染性能部分,建议您查看一下。

In short though — whenever you change a geometric property in css the browser has to adjust and perform calculations on how that change impacts the layout on the page, then it will have to re-render the page in a step called paint.

简而言之,尽管每当您在CSS中更改几何属性时,浏览器都必须调整并执行有关该更改如何影响页面布局的计算,然后,它必须在称为画图的步骤中重新渲染页面。

我们为什么还要关心性能? (Why should we even care about performance?)

It can be tempting to ignore performance. It’s not wise, but it can be tempting. From a business perspective, you save a lot of time that can otherwise be spent building new features.

忽略性能可能很诱人。 这不是明智的做法,但可能很诱人。 从业务角度来看,您可以节省大量时间,而这些时间本可以用于构建新功能。

However, performance can directly influence your bottom line. What good does it do to build a lot of features, if no-one is using them? Multiple studies done by Amazon and Google show that this is true. Performance is directly linked with application usage and bottom line revenue.

但是,性能会直接影响您的利润。 如果没有人使用它们,那么构建许多功能有什么好处? 亚马逊和谷歌进行的多项研究表明,这是事实。 性能与应用程序使用情况和底线收入直接相关。

The other side of performance is equally important. We, as developers, have a responsibility to make sure that the web stays accessible for everyone — we do this because it is right. Because the internet is not for just you and me, it’s for everyone.

绩效的另一面同样重要。 作为开发人员,我们有责任确保每个人都可以访问网络-之所以这样做是因为它是对的。 因为互联网不仅适合您和我,还适合所有人。

As evidenced from Addy Osmani’s excellent article, low-end devices take significantly longer to parse and execute javascript compared to their higher end counterparts.

从Addy Osmani的出色文章中可以看出,与高端设备相比,低端设备解析和执行javascript所花费的时间明显更长。

To avoid creating a class divide on the internet, we need to be relentless in our pursuit of performance. For me this meant being creative, and finding another means of achieving my animations without sacrificing performance.

为了避免在互联网上造成阶级分歧,我们需要不懈地追求表现。 对我来说,这意味着要有创造力,并找到在不牺牲性能的前提下实现动画的另一种方法。

以正确的方式设置高度动画 (Animate height the right way)

If you don’t care about the how, and just want to see a live example, please see the below links for demo site, examples and an npm package for react:

如果您不关心操作方法,而只是想看一个实时示例,请参阅下面的演示站点链接,示例和一个用于响应的npm软件包:

The question I asked myself was how I could avoid the performance cost that is incurred by animating height. Simple answer — you can’t.

我问自己的问题是如何避免动画高度引起的性能损失。 简单的答案-您不能。

Instead I needed to get creative with other CSS properties that does not incur those costs. Namely transforms.

取而代之的是,我需要利用其他CSS属性来发挥创意, 而这些属性不会产生这些费用 。 即变换。

Since transforms have no way of influencing height. We can not simply apply a simple property to an element and be done. We need to be more clever than that.

由于变换无法影响高度。 我们不能简单地将简单属性应用于元素并完成。 我们需要比这更聪明。

The way we will use to achieve performant animation of height is actually by faking it with transform: scaleY. The animation is done in several steps:

实际上,我们将通过以下方法来实现高度的动画效果:通过scaleY对其进行伪造。 动画分几个步骤完成:

Here’s an example:

这是一个例子:

<div class=”ah-outercontainer”>  
<div class=”ah-background” style=”${this.getBackgroundStyle()}”></div>
<div class=”ah-innercontainer”>${this.markup}</div></div>`
  • First we need to get the initial height of the element container. Then we set the outer container height to be explicit to this height. This will cause any changing content to overflow the container instead expanding its parent.

    首先,我们需要获取元素容器的初始高度。 然后,将外部容器的高度设置为对此高度明确。 这将导致任何更改的内容溢出容器,而不是扩展其父容器。
  • Inside the outer container we have another div that is absolutely positioned to span the entire width and height of the div. This is our background, and will be scaled once we toggle the transformation.

    在外部容器内,我们还有另一个div,它的位置绝对可以跨越div的整个宽度和高度。 这是我们的背景,一旦切换转换即可缩放。
  • We also have an inner container. The inner container contains the markup and will change its height according to the content it contains.

    我们还有一个内部容器。 内部容器包含标记,并将根据其包含的内容更改其高度。
  • Here’s the trick:  Once we toggle an event that changes the markup we take the new height of the inner container and calculate the amount that the background needs to scale in order to accommodate the new height. Then we set the background to scaleY by the new amount.

    诀窍是:一旦切换了更改标记的事件,我们就会获取内部容器的新高度,并计算背景需要缩放以适应新高度的数量。 然后,我们将背景设置为scaleY新值。

  • In vanilla javascript, this means some trickery with dual renders. Once to get the height of the inner container to calculate the scale. Then again to apply the scale to the background div so that it will perform the transformation.

    在香草javascript中,这意味着使用双重渲染有些技巧。 一次获取内部容器的高度以计算比例。 然后再次将比例尺应用于背景div,以便它将执行转换。

You can see a live example here in vanilla JS.

您可以在Vanilla JS中看到一个实时示例。

At this point, our background has been properly scaled to create the illusion of height. But what about the surrounding content? Since we are no longer adjusting layout the surrounding content is not afflicted by the changes.

在这一点上,我们的背景已经适当缩放以创建高度的错觉。 但是周围的内容呢? 由于我们不再调整布局,因此周围的内容不会受到更改的影响。

To make the surrounding content move. We need to adjust the content using transformY. The trick is to take the amount that the content expanded, and use this to move the surrounding content with transforms. See the example above.

使周围的内容移动。 我们需要使用transformY调整内容。 诀窍是利用内容扩展的数量,并使用此数量通过转换来移动周围的内容。 请参阅上面的示例。

React中的动画高度 (Animating height in React)

As I previously mentioned, I developed this method while working on a personal project in React. This demo site uses this method exclusively in all of its “height animation”. Check out the demo site here.

如前所述,我在React的一个个人项目中开发了这种方法。 该演示站点在其所有“高度动画”中仅使用此方法。 在此处查看演示站点。

After implementing this with success, I took the time to add this component and some supporting components to a small animation library I have made in React. If you are interested, you can find the relevant information here:

成功实现此功能后,我花了一些时间将这个组件和一些支持组件添加到我在React中制作的一个小型动画库中。 如果您有兴趣,可以在这里找到相关信息:

The most important components in this library is AnimateHeight and AnimateHeightContainer. Let’s examine them:

该库中最重要的组件是AnimateHeight和AnimateHeightContainer。 让我们检查一下它们:

// Inside a React component 
// handleAnimateHeight is called inside AnimateHeight and is passed the 
// transitionAmount and optionally selectedId if you pass that as a prop to // AnimateHeight. This means that you can use the transitionAmount to
// transition your surrounding 

content.const handleAnimateHeight = (transitionAmount, selectedId) => {     this.setState({ transitionAmount, selectedId });
};

// Takes a style prop, a shouldchange prop and a callback. shouldChange 
// determines when the AnimateHeight component should trigger, which is 
// whenever the prop changes. The same prop is used to control which 
// content to show.

<AnimateHeight 
  style={{ backgroundColor: "#f2f2f2" }} 
  shouldChange={this.state.open}   
  callback={this.handleAnimateHeight}
>
  {this.state.open && <Component />}
  {!this.state.open && <AnotherComponent />}
</AnimateHeight>

The above examples shows you how to use AnimateHeight and manually trigger your surrounding content to adjust. But what if you have a lot of content and don’t want to do this process manually? In that case you can use AnimateHeight in conjunction with AnimateHeightContainer.

上面的示例显示了如何使用AnimateHeight并手动触发周围的内容进行调整。 但是,如果您有很多内容并且不想手动执行此过程,该怎么办? 在这种情况下,您可以将AnimateHeight与AnimateHeightContainer结合使用。

To use AnimateHeightContainer you need to provide all of the top level children with a prop called animateHeightId, which also needs to be passed to your AnimateHeight components:

要使用AnimateHeightContainer,您需要为所有顶级子级提供一个名为animateHeightId的道具,该道具还需要传递给AnimateHeight组件:

// Inside React Component
const handleAnimateHeight = (transitionAmount, selectedId) => {     
this.setState({ transitionAmount, selectedId });
};

// AnimateHeight receives the transitionAmount and the active id of the AnimateHeight that fired. 
<AnimateHeightContainer
  transitionAmount={this.state.transitionAmount}
  selectedId={this.state.selectedId}
>
  <div animateHeightId={1}}>
    <AnimateHeight 
      style={{ backgroundColor: "#f2f2f2" }}
      shouldChange={this.state.open}
      callback={this.handleAnimateHeight}
      animateHeightId={1}
    > 
    {this.state.open && <Component />
    {!this.state.open && <AnotherComponent />}  
    <AnimateHeight />
          
    // When AnimateHeight is triggered by state change
    // this content will move because the animateHeightId
    // is greater than the id of the AnimateHeight component above
    <div animateHeightId={2}>I will move</div>
    <div animateHeightId={3}>I will also move</div>
<AnimateHeightContainer />

As you can see from this example AnimateHeight receives the information that it needs to adjust the content when the AnimateHeight component is triggered by changing state.

从该示例中可以看到,当AnimateHeight组件通过更改状态触发时,AnimateHeight会收到需要调整内容的信息。

Once this happens the AnimateHeight component will trigger the callback and set the properties in state. Inside AnimateHeight it looks something like this (simplified):

一旦发生这种情况,AnimateHeight组件将触发回调并将属性设置为state。 在AnimateHeight内部,它看起来像这样(简化):

// Inside AnimateHeight
componentDidUpdate() {
  if (update) {
    doUpdate() 
    callback(transitionAmount, this.props.animateHeightId)
   } 
}

// Equivalent to calling this function: 
const handleAnimateHeight = (transitionAmount, selectedId) => {     
this.setState({ transitionAmount, selectedId });
};

handleAnimateHeight(transitionAmount, this.props.animateHeight)

Now you the amount that the content transitioned in pixels, and the id of the AnimateHeight component that fired. Once you pass these values to the AnimateHeightContainer it will take them and transition the other components within itself, provided you set up incrementing animateHeightIds on the top level children.

现在,您可以看到内容过渡的数量(以像素为单位)以及触发的AnimateHeight组件的ID。 将这些值传递给AnimateHeightContainer后,只要您在顶级子级上设置了递增的animateHeightIds,它将使用它们并转换自身中的其他组件。

More advanced examples:

更高级的示例:

NOTE: If you are using this method to animate height and moving surrounding content, you need to add the transition amount to the height of your page.

注意:如果使用此方法设置高度动画和移动周围的内容,则需要将过渡量添加到页面的高度。

结论 (Conclusion)

You may have noticed in this article that we’re not actually animating height — and calling it that is wrong. You are of course, absolutely right. However, I firmly believe that what we call it does not matter. What matters is that we achieve the desired effect with the lowest possible cost to performance.

您可能已经在本文中注意到,我们实际上并没有设置动画高度,并称其为错误。 您当然是绝对正确的。 但是,我坚信我们所说的没关系。 重要的是,我们以最低的性能成本来达到预期的效果。

While I think I found a way that is better than animating the height property directly, I make no claims to have invented or otherwise thought of something that hasn’t been discovered before. Nor do I judge. Perhaps animating height works for you in your scenario — No problem.

虽然我认为我找到了一种比直接对height属性进行动画制作更好的方法,但我没有声称已经发明或以其他方式想到了以前未发现的东西。 我也不判断。 动画高度可能适合您的情况-没问题。

All I want is to enable and simplify effects that we all need to do, but sometimes incur costs that are difficult to bear. At the very least, I want to spark a discussion that is worth having. How can we improve the internet for everyone?

我想要的只是启用和简化我们都需要做的效果,但是有时会产生难以承受的成本。 至少,我想引发一个值得进行的讨论。 我们如何为每个人改善互联网?

翻译自: https://www.freecodecamp.org/news/animating-height-the-right-way/

css高度动画

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好,您的问题是关于CSS3蒲公英飘动效果和CSS3云朵飘动效果的实现方法,我能够为您提供相关的代码和实现思路。 首先,让我们来看看如何实现CSS3蒲公英飘动效果: HTML代码: ``` <div class="dandelion"></div> ``` CSS代码: ``` .dandelion { width: 100px; height: 100px; background-image: url("dandelion.png"); background-repeat: no-repeat; background-size: contain; position: relative; animation: dandelion 5s ease-in-out infinite; } @keyframes dandelion { 0% { transform: scale(1) translateY(0); } 50% { transform: scale(0.5) translateY(-200px); } 100% { transform: scale(1) translateY(0); } } ``` 上述代码中,我们首先定义了一个空的`<div>`元素,并为其添加了一个名为`dandelion`的class。接着,在CSS代码中,我们为这个`<div>`元素设置了一些基本样式,包括宽度、高度、背景图片等等。同时,我们还将其定位为相对定位(position: relative),以便后面设置其运动轨迹。 接下来,我们定义了一个名为`dandelion`的关键帧动画。在这个动画中,我们设置了三个关键帧,分别对应动画的开始、中间和结束状态。通过`transform`属性,我们实现了元素的缩放和位移,从而让元素沿着一定的轨迹进行运动。最后,我们将这个动画应用到了之前定义的`dandelion`类中,并设置其无限循环。 下面是CSS3云朵飘动效果的实现方法HTML代码: ``` <div class="cloud"></div> ``` CSS代码: ``` .cloud { width: 200px; height: 100px; background-image: url("cloud.png"); background-repeat: no-repeat; background-size: contain; position: relative; left: -200px; animation: cloud 10s linear infinite; } @keyframes cloud { 0% { left: -200px; } 100% { left: 100%; } } ``` 在这段代码中,我们同样定义了一个空的`<div>`元素,并为其添加了一个名为`cloud`的class。接着,在CSS代码中,我们为这个`<div>`元素设置了一些基本样式,包括宽度、高度、背景图片等等。同时,我们将其定位为相对定位(position: relative),并设置了一个初始的`left`值,以便后面设置其运动轨迹。 接下来,我们定义了一个名为`cloud`的关键帧动画。在这个动画中,我们设置了两个关键帧,分别对应动画的开始和结束状态。通过改变元素的`left`属性,我们实现了元素沿着一定的轨迹进行运动。最后,我们将这个动画应用到了之前定义的`cloud`类中,并设置其无限循环。 希望这些代码和实现思路能够帮助到您,如有任何疑问,请随时向我提问!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值