react 使用css文件_使用React构建Tesla的电池范围计算器(第3部分:CSS动画)

react 使用css文件

by Matthew Choi

由Matthew Choi

使用React构建Tesla的电池范围计算器(第3部分:CSS动画) (Building Tesla’s Battery Range Calculator with React (Part 3: CSS Animation))

This is the third part of Building Tesla’s Battery Range Calculator with React series.

这是使用React系列构建特斯拉电池范围计算器的第三部分。

In part 1, we’ve created the application with only the React core, and in part 2 we’ve transformed the application by introducing Redux, a state management solution.

在第1部分中,我们仅使用React核心创建了应用程序,在第2部分中,我们通过引入状态管理解决方案Redux对应用程序进行了转换。

Part 1, which focuses on React, is here:

第一部分,重点是React, 在这里

Building Tesla’s Battery Range Calculator with React (Part 1)In this series of articles, I will walk you through the process of building Tesla’s battery range calculator with React…medium.freecodecamp.com

使用React构建Tesla的电池范围计算器(第1部分) 在本系列文章中,我将引导您完成使用React构建Tesla的电池范围计算器的过程 。medium.freecodecamp.com

Part 2, which focuses on Redux, is here:

第2部分,重点介绍Redux, 在这里

Building Tesla’s Battery Range Calculator with React (Part 2: Redux version)This tutorial is the second part of building Tesla’s battery range calculator with React.medium.freecodecamp.com

使用React构建Tesla的电池范围计算器(第2部分:Redux版本) 本教程是 使用React构建Tesla的电池范围计算器 的第二部分。 medium.freecodecamp.com

If you look at the application we’ve built so far, it’s a bit plain and boring. It would look cooler if we could give it dynamic car showroom feel.

如果您看一下到目前为止我们已经构建的应用程序,它会显得有些枯燥乏味。 如果我们可以给它动感十足的汽车展示厅感觉,它将看起来更酷。

When the app is loaded, it would be nice if our stunning Tesla car images were in motion. With a little Transformer feel. The Tesla header is also shown as a fade-in effect, and the rest of the components should look a little nicer.

加载应用程序后,如果我们令人惊叹的特斯拉汽车图像动起来,那就太好了。 带有一点变形金刚的感觉。 Tesla标头还显示为淡入效果,其余组件应该看起来更好一些。

Even when the user event occurs after loading, it will be more impactful to show a noticeable visual effect instead of just changing the numerical value.

即使在加载后发生用户事件,显示效果也要比更改数值更显眼。

Just like this:

像这样:

You can check out live demo.

您可以查看现场演示

And here’s the full source code.

这是完整的源代码

In Part 3, we’ll take a step-by-step look at the process of making our finished apps more stylish using CSS animation.

第3部分中 ,我们将逐步介绍使用CSS动画使完成的应用程序更加时尚的过程。

1.热身 (1. Warming up)

Let’s start with the warming up before starting.

让我们从开始前的热身开始。

1-1。 基本示例CSS动画 (1–1. Basic example CSS animation)

CSS animation lets an element gradually change from one style to another.

CSS动画使元素逐渐从一种样式变为另一种样式。

CSS animation consist of two components :

CSS动画包含两个组件:

  • A style describing the CSS animation

    描述CSS动画的样式
  • A set of keyframes that indicate the start and end states of animation’s style

    一组关键帧,用于指示动画样式的开始和结束状态

Here is a simple example. In this example, the background color of one element is gradually changed from red to yellow over 5 seconds.

这是一个简单的例子。 在此示例中,一个元素的背景颜色在5秒钟内从红色逐渐变为黄色。

To create a CSS animation, you need two steps :

要创建CSS动画,您需要执行两个步骤:

Check out Using CSS animations for more details

查看使用CSS动画以了解更多详细信息

1–2。 另一个CSS动画示例 (1–2. Another example CSS animation)

Here’s what we’re starting with. It’s got a Tesla header, some title and a nice Tesla car image.

这就是我们的开始。 它有一个特斯拉头,一些标题和一个很好的特斯拉汽车形象。

1-3使它弹跳 (1–3 Making it bounce)

Here are three elements nicely placed. Let’s see these three elements slowly appear on a white screen, as one or two actors dancing on a stage with nothing on the white background.

这三个元素放置得很好。 让我们看看这三个元素在白色屏幕上缓慢出现,一个或两个演员在舞台上跳舞,而白色背景上什么也没有。

First, define the animation sequence using keyframes. Then apply the animate-pop-in class with the animation property defined to the div and h1 elements.

首先,使用关键帧定义动画序列。 然后将animate-pop-in类应用于div和h1元素,并将其animation属性定义为。

Now you can see that the three elements appear slowly increasing in size over 6 seconds.

现在您可以看到三个元素的大小在6秒内逐渐增加。

1–4立方贝塞尔曲线 (1–4 Cubic Bezier)

In our example we used ease-out with an animation-timing-function. Easing functions specify the rate of change of a parameter over time. There are four predefined timing functions we can use, they are ease, ease-in, ease-out, ease-in-out and linear.

在我们的示例中,我们使用了带有动画定时功能的缓动。 缓动函数指定参数随时间的变化率。 我们可以使用四种预定义的定时功能,分别是缓动,缓动,缓动,缓动和线性。

  • ease — speeds up a little through the middle, and then slows down towards the end

    缓解 —从中间加速一点,然后向终点减速

  • ease-in — starts of slowly, and accelerates through to the end

    缓入 —开始缓慢,并一直加速到结束

  • ease-out — starts of quickly, and decelerates through to the end

    缓和 —快速开始,然后一直减速到结束

  • ease-in-out — starts slowly, accelerates through to the middle, then decelerates through to the end

    缓入 —缓慢开始,加速到中间,然后减速到终点

  • linear — constant animation speed throughout

    线性 —始终保持恒定的动画速度

It’s important that they are essentially based on the Bezier curve.

重要的是它们基本上基于Bezier曲线

1–5创建自定义速度 (1–5 Creating Custom Speed)

As in our real life, not all objects move at a constant speed, giving these variable speeds to the elements on the screen will give a more realistic movement. Using Cubic-bezier function, we are able to create custom speed.

在我们的现实生活中,并非所有对象都以恒定的速度运动,因此将这些可变的速度赋予屏幕上的元素将使运动更加逼真。 使用三次贝塞尔函数,我们能够创建自定义速度。

However, defining the animation speed in the cubic-bezier function format is not intuitive.

但是,以三次方贝塞尔函数格式定义动画速度并不直观。

Here is a fantastic tool to visualize how cubic-bezier works.

这是一个出色的工具,可以直观地展示三次贝塞尔曲线的工作原理。

Here’s an example of applying custom speed instead of ease-out.

这是一个应用自定义速度而不是轻松进行操作的示例。

Now that the warm-up is over, let’s get started.

现在预热已经结束,让我们开始吧。

2.锻炼 (2. Excersize)

As we saw in the demo, we’ll apply animation to two points in our application:

正如在演示中所看到的,我们将在应用程序中将动画应用于两点:

  • when an application is loaded

    加载应用程序时
  • When a user action occurs

    发生用户动作时

2.1何时加载应用程序 (2.1 when an application is loaded)

Let’s look at the entire layout of our app. The component structure of the app we created in Part 1, Part 2 does not change at all. Just it needs to define animation attribute and @keyframes in the corresponding CSS file. The CSS file to be modified is marked in green.

让我们看一下应用程序的整体布局。 我们在第1部分,第2部分中创建的应用程序的组件结构完全不变。 只是需要在相应CSS文件中定义动画属性和@keyframes。 要修改CSS文件以绿色标记。

2.1.1 Animista简介 (2.1.1 Introducing Animista)

Wouldn’t it be nice to have a tool that lets us see what effect animations are possible before applying them? And how effects would look once you applied them? How you could combine multiple animation properties in a single place? There’s precisely a tool for that: Animista.

有一个工具可以让我们在应用动画之前先看一下可能的效果动画,这不是很好吗? 应用效果后效果如何? 如何在一个地方合并多个动画属性? 正是有一个工具可以实现这一点: Animista

With this tool, we can touch and test animated effects at will. Once you find the animation you like, click on the Generate code button to copy the animation property value and apply it to the corresponding CSS in our app.

使用此工具,我们可以随意触摸和测试动画效果。 找到喜欢的动画后,单击“生成代码”按钮以复制动画属性值,并将其应用于我们应用中的相应CSS。

Don’t forget to click the Add to Favorites button and grab the keyframes code from the download page.

不要忘记单击“添加到收藏夹”按钮,并从下载页面获取关键帧代码。

2.1.2设置第2部分项目代码库 (2.1.2 Set up part 2 project code base)

If you want to go directly to part 3 without looking at part 2, you need to build the codebase first by cloning the part 2 code.

如果您想直接进入第3部分而不看第2部分,则需要首先通过克隆第2部分代码来构建代码库。

After the npm start, let’s make sure the application works.

在npm启动之后,让我们确保该应用程序正常运行。

2.1.3 Tesla接头 (2.1.3 Tesla Header)

The Tesla Header component should have a fade-in effect that gradually displays the logo.

Tesla Header组件应具有逐渐显示徽标的淡入效果。

First, open the Header.css file and paste the animation properties and keyframes values copied from Animista. Then modify it to refer to this class in the Header.js file.

首先,打开Header.css文件,然后粘贴从Animista复制的动画属性和关键帧值。 然后修改它以引用Header.js文件中的此类。

2.1.4 <h1>标题 (2.1.4 <h1> title)

The focus-in-contract-bck effect is likely to work for Tesla title. Give the animation effect the same way you did in Tesla Header.

合同中焦点效应很可能适用于特斯拉的头衔。 赋予动画效果的方式与在Tesla Header中相同。

Note that the title <h1> element is defined in App.js / App.css.

请注意,标题<h1>元素是在App.js / App.css中定义的。

2.1.5特斯拉汽车 (2.1.5 TeslaCar)

For the TeslaCar component, which has the most dynamic effects, let’s apply the following two effects.

对于具有最大动态效果的TeslaCar组件,让我们应用以下两个效果。

  • Tesla Car : slide-in-elliptic-bottom-fwd

    特斯拉汽车: 椭圆底前轮滑

  • Tesla Wheels : bounce-in-top

    特斯拉车轮: 顶部反弹

/src/Components/TeslaCar/TeslaCar.css

/src/Components/TeslaCar/TeslaCar.css

.tesla-car-animation {  -webkit-animation: slide-in-elliptic-bottom-fwd 0.7s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;	-moz-animation: slide-in-elliptic-bottom-fwd 0.7s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;	animation: slide-in-elliptic-bottom-fwd 0.7s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;  }
.tesla-wheels-animation {  -webkit-animation: bounce-in-top 2.3s both;  -moz-animation: bounce-in-top 2.3s both;  animation: bounce-in-top 2.3s both;}
@-webkit-keyframes slide-in-elliptic-bottom-fwd{0%{-webkit-transform:translateY(600px) rotateX(30deg) scale(0);transform:translateY(600px) rotateX(30deg) scale(0);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}100%{-webkit-transform:translateY(0) rotateX(0) scale(1);transform:translateY(0) rotateX(0) scale(1);-webkit-transform-origin:50% -1400px;transform-origin:50% -1400px;opacity:1}}@keyframes slide-in-elliptic-bottom-fwd{0%{-webkit-transform:translateY(600px) rotateX(30deg) scale(0);transform:translateY(600px) rotateX(30deg) scale(0);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}100%{-webkit-transform:translateY(0) rotateX(0) scale(1);transform:translateY(0) rotateX(0) scale(1);-webkit-transform-origin:50% -1400px;transform-origin:50% -1400px;opacity:1}}
@-webkit-keyframes bounce-in-top{0%{-webkit-transform:translateY(-500px);transform:translateY(-500px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}38%{-webkit-transform:translateY(0);transform:translateY(0);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out;opacity:1}55%{-webkit-transform:translateY(-65px);transform:translateY(-65px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}72%{-webkit-transform:translateY(0);transform:translateY(0);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}81%{-webkit-transform:translateY(-28px);transform:translateY(-28px);-webkit-animation-timing-function:ease-in}90%{-webkit-transform:translateY(0);transform:translateY(0);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}95%{-webkit-transform:translateY(-8px);transform:translateY(-8px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:translateY(0);transform:translateY(0);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}
@keyframes bounce-in-top{0%{-webkit-transform:translateY(-500px);transform:translateY(-500px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}38%{-webkit-transform:translateY(0);transform:translateY(0);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out;opacity:1}55%{-webkit-transform:translateY(-65px);transform:translateY(-65px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}72%{-webkit-transform:translateY(0);transform:translateY(0);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}81%{-webkit-transform:translateY(-28px);transform:translateY(-28px);-webkit-animation-timing-function:ease-in}90%{-webkit-transform:translateY(0);transform:translateY(0);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}95%{-webkit-transform:translateY(-8px);transform:translateY(-8px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:translateY(0);transform:translateY(0);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}

/src/Components/TeslaCar/TeslaCar.js

/src/Components/TeslaCar/TeslaCar.js

const TeslaCar = (props) => (  <div className="tesla-car tesla-car-animation">    <div className="tesla-wheels tesla-wheels-animation">          <;/div>  </div>);

At this point, you should see this:

此时,您应该看到以下内容:

2.1.6 TeslaStats (2.1.6 TeslaStats)

This time, let’s give the TeslaStats component a slit-in-horizontal animation effect. Give the delay 2 seconds to start after the TeslaCar animation runs.

这次,让我们为TeslaStats组件提供水平裂缝动画效果。 在TeslaCar动画运行后,给延迟2秒开始播放。

2.1.7特斯拉控件 (2.1.7 Tesla Controls)

The Speed counter, the Temperature counter, and the Climate and Wheels components are wrapped in the tesla-controls class, so we can simply modify App.css and App.js as follows, without modifying the CSS of each component.

速度计数器,温度计数器以及“气候和车轮”组件包装在tesla-controls类中,因此我们可以按如下所示简单地修改App.css和App.js,而无需修改每个组件CSS。

Provide the same animation effects as applied to the TeslaStats component. Give the delay 2.5 seconds to start after the TeslaStats animation runs.

提供与应用于TeslaStats组件相同的动画效果。 给TeslaStats动画运行后2.5秒开始延迟。

Here’s what you should be seeing:

这是您应该看到的:

We have implemented all the animation at the time the application is loaded. Now let’s implement animation when user action occurs.

在加载应用程序时,我们已经实现了所有动画。 现在,让我们在发生用户操作时实现动画。

2.2发生用户操作时 (2.2 When a user action occurs)

When user clicks the Speed, Temperature counters and Wheels, we are going to give the following animation effect.

当用户单击“速度”,“温度”计数器和“车轮”时,我们将给出以下动画效果。

2.2.1速度计数器 (2.2.1 Speed counter)

First, consider what happens when you click Speed ​​counter up.

首先,请考虑单击加速计数器时会发生什么。

We defined mapStateToProps and mapDispatchToProps as a way to create a TeslaSpeedCounter container in part 2 and communicate with the Redux Store. Then, we refer to the state in the TeslaCounter component through connect and when the action occurs, we dispatch it to the Redux Store to update the new state and render the view.

我们定义了mapStateToPropsmapDispatchToProps作为在第二部分中创建TeslaSpeedCounter容器并与Redux Store通信的一种方式。 然后,我们通过connect引用TeslaCounter组件中的状态,当操作发生时,我们将其分派到Redux Store以更新新状态并呈现视图。

The following figure shows this flow well.

下图很好地显示了此流程。

So how do you animate when a new state is rendered by a speed up click event? After defining the animation in TeslaCounter.css, would you like to add the flip-in-hor-top class that you want to apply as follows?

那么,如何通过加速单击事件呈现新状态时进行动画处理? 在TeslaCounter.css中定义了动画之后,是否要添加您想要应用的水平翻转类,如下所示?

<div className="flip-in-hor-top">  <p className="tesla-counter__number ">    { currentValue }    <span>{ initValues.unit }<;/span>  </p></div>

This will have no effect. Because only the currentValue that is updated when the event occurs is re-rendered. In addition, we are trying to apply different orientations to the up and down events. If so, we need to know the direction of the animation along with the event, and then make sure that the corresponding class is applied and re-rendered.

这将无效。 因为仅重新渲染事件发生时更新的currentValue。 此外,我们正在尝试对上下事件采用不同的方向。 如果是这样,我们需要与事件一起了解动画的方向,然后确保应用并重新渲染了相应的类。

2.2.2 TeslaCounter.css (2.2.2 TeslaCounter.css)

First, let’s define the animation code that we want to apply through Animista to the CSS file after copying. Add the following animation class and keyframes.

首先,让我们定义要在复制后通过Animista应用到CSS文件的动画代码。 添加以下动画类和关键帧。

  • flip-in-hor-bottom

    底部翻转
  • flip-in-hor-top

    翻盖
  • keyframes flip-in-hor-bottom

    底部翻转关键帧
  • keyframes flip-in-hor-top

    关键帧翻转

2.2.3 TeslaCounter.js (2.2.3 TeslaCounter.js)

To apply different animation effects according to the speed up/down event, we need to know the type of the event, update it in the Redux store with reducer, and have the new state value passed to the TeslaCounter through props. Instead of adding this event type to the Redux store, let’s implement it in a way that manages to the local state of the TeslaCounter. Since the local state is required, modify the current functional component TeslaCounter as a class component.

要根据加速/减速事件应用不同的动画效果,我们需要了解事件的类型,使用reduceer在Redux存储中对其进行更新,并通过道具将新的状态值传递给TeslaCounter。 与其将这种事件类型添加到Redux存储中,不如以一种对TeslaCounter的本地状态进行管理的方式来实现它。 由于需要本地状态,因此将当前功能组件 TeslaCounter修改为类组件

We also need the update life cycle method componentWillReceiveProps() here. This method is called when props are passed to the TeslaCounter component. TeslaCounter component has two up/down button that allow the user to change counter value by clicking it. The button is bound to the onClick event and sets the state on the Redux store through dispatching an action. The new state value is then passed to the TeslaCounter component as a prop through connect() in TeslaCounter container.

在此,我们还需要更新生命周期方法componentWillReceiveProps() 。 将道具传递给TeslaCounter组件时,将调用此方法。 TeslaCounter组件具有两个向上/向下按钮,允许用户单击它来更改计数器值。 该按钮绑定到onClick事件,并通过调度操作来设置Redux存储上的状态。 然后将新的状态值作为道具通过TeslaCounter容器中的connect()传递给TeslaCounter组件。

Any time the user clicks the up/down button this begins an Update for the TeslaCounter component. The first method called on the Component is componentWillReceiveProps(nextProps) passing in the new prop value. This allows us to compare the incoming props against our current props and make logical decisions based on the value. We can get our current props by calling this.props and the new value is the nextProps argument passed to the method.

每当用户单击上/下按钮时,都会启动TeslaCounter组件的更新。 在Component上调用的第一个方法是componentWillReceiveProps(nextProps)传入新的prop值。 这使我们可以将传入的道具与当前的道具进行比较,并根据价值做出合理的决策。 我们可以通过调用this.props获得当前的道具,新值是传递给该方法的nextProps参数。

So why do we need componentWillReceiveProps? This is a hook that allows us to look into the upcoming Update. If we have a state that is a calculation of props, we can safely apply the logic here and store the result using this.setState().

那么,为什么我们需要componentWillReceiveProps? 这是一个使我们能够查看即将发布的Update的挂钩。 如果我们的状态是道具计算,则可以在此处安全地应用逻辑并使用this.setState()存储结果。

Here we need a direction state, which is the animation direction, which can be obtained by comparing the current value with the updated value.

这里我们需要一个方向状态,即动画方向,可以通过将当前值与更新后的值进行比较来获得。

You can see the whole flow through the following image.

您可以通过下图查看整个流程。

Now click on the Speed ​​and Temperature counters to confirm that the animation has been applied. But there is one problem. If you click the Up / Down button alternately, they work normally. If you click the same button continuously, the animation will not be applied. This is because the animation class changes only when the event type changes.

现在单击速度和温度计数器以确认已应用动画。 但是有一个问题。 如果您交替单击“向上/向下”按钮,它们将正常工作。 如果连续单击同一按钮,将不会应用动画。 这是因为动画类仅在事件类型更改时才更改。

To solve this problem, add animationEffect to the local state and setTimeout to initialise the applied animation class after 0.5 seconds.

若要解决此问题,请在本地状态上添加animationEffect并使用setTimeout在0.5秒后初始化应用的动画类。

Now you can see that it works fine even if you click the same button continuously.

现在,即使您连续单击同一按钮,也可以正常运行。

2.2.4 TeslaWheels动画 (2.2.4 TeslaWheels animation)

Finally, let’s apply animation effects when clicking on Wheels.

最后,让我们在单击Wheels时应用动画效果。

First, bounce-in-top is already defined in TeslaCar.css, so let’s define additional bounce-in-bottom animation. Then open the TeslaCar.js file and replace the tesla-car-animation that was already applied in the 2.1.5 TeslaCar section with tesla-wheel-animation-${props.wheelsize}.

首先,已经在TeslaCar.css中定义了顶部反弹 ,因此让我们定义其他底部反弹动画。 然后打开TeslaCar.js文件,并用tesla-wheel-animation-$ {props.wheelsize}替换2.1.5 TeslaCar节中已应用的tesla-car-animation。

You should have a fully working Tesla range calculator with animation:

您应该有一个带有动画的功能齐全的Tesla范围计算器:

翻译自: https://www.freecodecamp.org/news/building-teslas-battery-range-calculator-with-react-part-3-css-animation-797476dc1b37/

react 使用css文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值