framer x使用教程_如何使用Framer Motion将交互式动画和页面过渡添加到Next.js Web应用程序

framer x使用教程

The web is vast and it's full of static websites and apps. But just because those apps are static, it doesn't mean they have to be boring.

网络非常庞大,到处都是静态的网站和应用。 但是,仅仅因为这些应用程序是静态的,并不意味着它们一定很无聊。

How can we use Framer Motion to add some animations to our web apps and provide a more interactive experience?

我们如何使用Framer Motion将一些动画添加到我们的Web应用程序中并提供更具交互性的体验?

什么是成帧器运动? (What is Framer Motion?)

Framer Motion is an API that comes straight from the Framer API. It provides ready-to-go animations and gesture controls that makes it easy to create dynamic effects.

Framer Motion是直接来自Framer API的API。 它提供了随时可用的动画和手势控件,可轻松创建动态效果。

What is Framer? Framer itself is a UI prototyping tool that allows you to create interactive interfaces with animations that you can hand off to your team, while the Framer API is a Javascript library that lets you do that with code.

什么是成帧器 ? Framer本身是一个UI原型制作工具,可让您创建带有动画的交互式界面,您可以将该动画传递给您的团队,而Framer API是一个Javascript库,可用于编写代码。

The Motion API stems from that work, but is conveniently available as a separate package that we can use for animation control.

Motion API源自这项工作,但是可以作为单独的软件包方便地使用,我们可以将其用于动画控制。

我们要建造什么? (What are we going to build?)

We’re going to use the concepts of Framer Motion to add interaction and page transition effects to our app.

我们将使用Framer Motion的概念向我们的应用程序添加交互和页面过渡效果。

We’ll start off with some basic animations that happen when the page load, learn how to trigger them on hover, and build out a wrapper that allows us to gracefully transition our pages in Next.js.

我们将从页面加载时发生的一些基本动画开始,学习如何在悬停时触发它们,并构建一个包装器,使我们能够在Next.js中正常转换页面。

开始之前 (Before getting started)

This is the second part of series of articles walking through building a Rick and Morty wiki. The first part focuses on requesting the data from the Rick and Morty API and creating dynamic pages.

这是构建Rick and Morty Wiki的系列文章的第二部分。 第一部分着重于从Rick and Morty API请求数据并创建动态页面。

How to Create a Dynamic Rick and Morty Wiki Web App with Next.js

如何使用Next.js创建动态的Rick and Morty Wiki Web App

While you can follow along without walking through the first one, it might be helpful to have a place to start from. Otherwise, you should be able to follow along most of this with any React app.

尽管您可以不遵循第一个步骤地进行学习,但是找到一个起点可能会有所帮助。 否则,您应该能够在任何React应用程序中遵循大部分内容。

步骤0:在Next.js应用中安装Framer Motion (Step 0: Installing Framer Motion in your Next.js app)

Since we’re going to use Framer Motion to provide our animation features, the first thing we want to do is install it!

由于我们将使用Framer Motion提供动画功能,因此我们要做的第一件事就是安装它!

Once you have the app running locally, you can install it with:

在本地运行应用程序后,可以使用以下命令进行安装:

yarn add framer-motion
# or
npm install framer-motion

And at this point you can start back up your development server and we’ll be ready to go!

现在,您可以启动您的开发服务器了,我们就可以开始了!

Follow along with the commit!

跟随提交!

第1步:在Next.js应用中使用Framer Motion对页面标题进行动画处理 (Step 1: Animating the page title with Framer Motion in a Next.js app)

To get started, we’re going to animate the page title in our wiki app. Particularly, we’re going to configure Framer Motion to make the title fade in and grow when the page first loads.

首先,我们将为Wiki应用程序中的页面标题设置动画。 特别是,我们将配置成帧器运动以使标题淡入并在页面首次加载时增长。

First things first, we need to import Motion into our app.

首先,我们需要将Motion导入到我们的应用程序中。

Start off by adding the following import statement to the top of pages/index.js:

首先将以下import语句添加到pages/index.js的顶部:

import { motion } from 'framer-motion';

And now that we’re ready to use motion, we can get started by wrapping out <h1> title with a motion component:

现在我们已经准备好使用motion ,我们可以通过将<h1>标题包装到运动组件<h1>开始使用:

<motion.div>
  <h1 className="title">
    Wubba Lubba Dub Dub!
  </h1>
</motion.div>

Wrapping our element is what’s going to allow us to hook into the Motion API.

包装元素是使我们能够连接到Motion API的基础

If we reload our page though, it won’t be doing anything yet. That’s because we haven’t yet configured our animation, so let’s do that!

但是,如果我们重新加载页面,它将不会做任何事情。 那是因为我们还没有配置动画,所以让我们开始吧!

When using the Motion API with our <motion.x> component, we have two basic concepts we need to use:

将Motion API与<motion.x>组件一起使用时,我们需要使用两个基本概念:

  • Animation lifecycle

    动画生命周期
  • Variants

    变体

Each of the animation lifecycle props such as initial and animate allow us to define our animation’s name as a variant.

每个动画生命周期道具(例如initial animateanimate允许我们将动画名称定义为一个变体。

Our variants prop is where we configure those animations by defining variant names along with the animation we’d like them to perform.

我们的variants道具是通过定义变体名称以及我们希望它们执行的动画来配置这些动画的地方。

So to start, let’s add two lifecycle definitions to our title component by adding two lifecycle props:

首先,让我们通过添加两个生命周期道具,将两个生命周期定义添加到标题组件中:

<motion.div initial="hidden" animate="visible">
  <h1 className="title">
    Wubba Lubba Dub Dub!
  </h1>
</motion.div>

Now, we want to define those:

现在,我们要定义这些:

<motion.div initial="hidden" animate="visible" variants={{
  hidden: {},
  visible: {},
}}>
  <h1 className="title">
    Wubba Lubba Dub Dub!
  </h1>
</motion.div>

We’re defining two variants — hidden and visible — which we then reference in the initial and animate lifecycle props.

我们定义了两个变体-隐藏的和可见的,然后在initialanimate生命周期道具中引用它们。

Now again, reloading the page, it still won’t do anything since we still haven’t defined the animations themselves, so let’s do that:

再一次,重新加载页面,由于我们还没有定义动画本身,它仍然不会做任何事情,所以让我们这样做:

<motion.div initial="hidden" animate="visible" variants={{
  hidden: {
    scale: .8,
    opacity: 0
  },
  visible: {
    scale: 1,
    opacity: 1,
    transition: {
      delay: .4
    }
  },
}}>
  <h1 className="title">
    Wubba Lubba Dub Dub!
  </h1>
</motion.div>

Here’s what’s going on:

这是怎么回事:

  • We have two different lifecycles, an initial and an animate. The initial is what “initially” loads when the page loads where animate is what happens after the page loads

    我们有两个不同的生命周期,一个初始生命周期和一个生命周期。 初始是页面加载时“初始”加载的内容,动画是页面加载后发生的动画
  • In our initial state, we’re setting the element to be slightly scaled down with a 0 opacity

    在我们的初始状态下,我们将元素设置为以0不透明度稍微缩小
  • When the page loads and triggers our animation, we set the scale back to 1 and the opacity back to 1

    当页面加载并触发动画时,我们将比例设置回1,将不透明度设置回1
  • We’re also setting a delay on our transition so that it ways .4s before firing the animation. This is just to help let things load a tiny bit before triggering

    我们还为过渡设置了延迟,以便在触发动画之前它的延迟为.4s。 这只是为了让事情在触发之前加载一点点

So in the above, what’s actually happening is .4s after the page loads, we’re going to fade in the title and make it look like it’s slightly growing.

因此,在上面,实际发生的是页面加载后的0.4秒,我们将淡入标题,使其看起来略有增长。

And if we save that and reload the page, we can see our title’s effect!

如果保存并重新加载页面,我们可以看到标题的效果!

Follow along with the commit

跟着提交

步骤2:使用Framer Motion将动画悬停效果添加到Next.js应用程序中的元素 (Step 2: Adding animated hover effects with Framer Motion to elements in a Next.js app)

Now that we have a basic understanding of how to add animations when the page loads, let’s starting adding some interaction.

现在,我们对如何在页面加载时添加动画有了基本的了解,让我们开始添加一些交互。

We’re going to add some hover effects to each character card. That way, when your cursor moves over one of the cards, we’ll trigger our animation.

我们将为每个角色卡添加一些悬停效果。 这样,当您的光标移到其中一张卡片上时,我们将触发动画。

First, inside of our unordered list grid <ul className=“grid”>, let’s update the list element <li> to be a <motion.li> element:

首先,在我们的无序列表网格<ul className=“grid”> ,让我们将列表元素<li>更新为<motion.li>元素:

<motion.li key={id} className="card">
  ...
</motion.li>

If you save and reload the page, you’ll notice that we actually have an issue.

如果您保存并重新加载页面,您会注意到我们实际上存在问题。

Because of the integration between motion and the Next.js CSS integration, our app is getting tripped up on the class name.

由于motion和Next.js CSS集成之间的集成,我们的应用程序在类名上被绊倒了。

While this isn’t fixing it at it’s “core”, we can fix this for our demo by removing the jsx prop from our top <style> block where inside, we have our .card definition.

虽然这不能解决它的“核心”问题,但是我们可以通过从顶部的<style>块中移除jsx道具来解决此问题,其中我们在其中拥有.card定义。

Change:

更改:

<style jsx>{`

To:

至:

<style>{`

Now if we reload our page, we’re back to where we started off.

现在,如果我们重新加载页面,我们将回到开始的地方。

In order to add our hover effect, we’re going to create a new prop on our <motion.li> component called whileHover and fill it with some base styles:

为了添加悬停效果,我们将在<motion.li>组件上创建一个名为whileHover的新道具,并用一些基本样式填充它:

<motion.li key={id} className="card" whileHover={{
  scale: 1.2,
  transition: {
    duration: .2
  }
}}>

Above, we’re telling motion that when someone hovers over our element, we want it to grow by scaling it to 1.2 and we want that animation to last .2s.

上面,我们告诉运动,当有人将鼠标悬停在元素上时,我们希望通过将其缩放到1.2来使其增长,并且希望该动画持续0.2s。

And if we reload the page, we can see our animation!

如果重新加载页面,我们可以看到动画!

If you look at the bottom of the effect though, when the card grows, it’s overlapping with the card below it and looks a bit broken. We can fix that by applying some z-indexing and a background color!

但是,如果您查看效果的底部,则当卡片长大时,它与下面的卡片重叠,看起来有点破损。 我们可以通过应用一些z索引和背景色来解决此问题!

<motion.li key={id} className="card" whileHover={{
  position: 'relative',
  zIndex: 1,
  background: 'white',
  scale: 1.2,
  transition: {
    duration: .2
  }
}}>

And if we reload the page again, we can now see that as our card grows, it appears on top of the card below it!

而且,如果我们再次重新加载页面,现在我们可以看到随着卡片的增加,它会显示在卡片下方的顶部!

Follow along with the commit!

跟随提交!

步骤3:使用Framer Motion将页面过渡添加到Next.js应用程序 (Step 3: Adding page transitions with Framer Motion to a Next.js app)

Triggering some animations when the page loads and hover effects is cool, but it’s a nice touch when your app can provide graceful transitions between pages. That can be part of what makes it feel more like a “web app” as opposed to a static “website”.

在页面加载和悬停效果时触发一些动画很酷,但是当您的应用可以在页面之间提供优美的过渡时,这是一个很好的选择。 这可能是使其感觉更像是“网络应用程序”而不是静态“网站”的一部分。

To do this, we’ll need to configure our Next.js app with a wrapper around the root pages of the website. This will allow us to hook into the navigation lifecycle and properly animate our pages.

为此,我们需要在网站的根页面周围使用包装器配置Next.js应用程序 。 这将使我们能够进入导航生命周期并正确地为页面设置动画。

Getting started, we need to create a new file under the pages directory called _app.js:

开始之前,我们需要在pages目录下创建一个名为_app.js的新文件:

// In pages/_app.js
function App({ Component, pageProps }) {
  return (
    <Component {...pageProps} />
  )
}

export default App;

While we don’t necessarily have to understand the specifics of what’s happening, we’re basically creating a wrapper where we can patch in additional functionality.

虽然我们不必一定要了解发生的事情的细节,但是我们基本上是在创建包装器,在其中可以修补其他功能。

With this new file, if you reload the page, you shouldn’t see any changes yet.

有了这个新文件,如果您重新加载页面,那么您应该不会看到任何更改。

Next, we’re going to add our foundation that allows us to set up our page transitions.

接下来,我们将添加基础,使我们可以设置页面过渡。

First, let’s import motion at the top of our page:

首先,让我们在页面顶部导入动作:

import { motion } from 'framer-motion';

Then, similar to our other animations, let’s create a new <motion.div> component that wraps around our page.

然后,与其他动画类似,让我们创建一个新的<motion.div>组件,该组件环绕我们的页面。

<motion.div initial="pageInitial" animate="pageAnimate" variants={{
  pageInitial: {
    opacity: 0
  },
  pageAnimate: {
    opacity: 1
  },
}}>
  <Component {...pageProps} />
</motion.div>

Here, we’re setting an initial state with an opacity of 0 and an animate state with an opacity of 1, with the idea that it will fade in.

在这里,我们将设置不透明度为0的初始状态和不透明度为1的动画状态,以使其逐渐消失。

Now if you hit refresh, you’ll notice that the page fades in. But if you click on one of the characters, when the character page loads, it doesn’t fade in.

现在,如果单击刷新,您会注意到页面淡入。但是,如果单击一个字符,则在加载字符页面时,它不会淡入。

The issue is, currently, the motion component doesn’t understand it’s a new route, so we need to force it to recognize that and update.

问题是,当前,运动组件不知道这是一条新路线,因此我们需要强制其识别并更新。

To do this, we’re going to destructure the router argument in our App props:

为此,我们将在App道具中分解router参数:

function App({ Component, pageProps, router }) {

And on our motion component, we’re going to use it as a key:

在运动组件上,我们将其用作键:

<motion.div key={router.route} initial="pageInitial" animate="pageAnimate" variants={{

Now if we reload the page and navigate between our character page and our homepage, you’ll see it’s now fading in the content!

现在,如果我们重新加载页面并在角色页面和主页之间导航,您将看到内容正在逐渐消失!

Follow along with the commit!

跟随提交!

步骤4:将Framer Motion关键帧用于高级动画 (Step 4: Using Framer Motion keyframes for advanced animations)

Now that we’ve got the basics of setting up animations in our app’s lifecycle, we can get more advanced by using keyframes.

现在,我们已经拥有在应用程序生命周期中设置动画的基础知识,我们可以通过使用关键帧来获得更高级的设置。

The way keyframes work, is when we define an animation, we can set that animation to move through a set of different values for our given property,  allowing us to build custom animations to our liking.

关键帧的工作方式是在定义动画时,可以将动画设置为针对给定属性在一组不同的值之间移动,从而使我们可以根据自己的喜好创建自定义动画。

For instance, say we want to make an element on hover grow to 2x the size, make it a little bit smaller to 1.5x the size, and then back up to 2x the size all in one animation sequence. We can do that with keyframes!

例如,假设我们要使一个悬停的元素增长到2倍的大小,使其稍小到1.5倍的大小,然后在一个动画序列中将其全部恢复到2倍的大小。 我们可以使用关键帧做到这一点!

The syntax for that would look like this:

其语法如下所示:

scale: [1, 2, 1.5, 2]

We’re specifying our sequence using an array that says we want our element to start off at it’s normal size at 1x, then the next frame it will grow to 2x, then shrink a little to 1.5x, then finally grow back to 2x.

我们使用一个数组指定序列,该数组表示我们希望元素以其正常大小1x开始,然后下一帧将增长到2x,然后缩小到1.5x,最后再增长回2x。

To test this out, we’re going to make some changes on our hover effect that we’ve already configured for our character cards.

为了验证这一点,我们将对已经为角色卡配置的悬停效果进行一些更改。

In pages/index.js, update the whileHover property on our motion list elements to:

pages/index.js ,将运动列表元素上的whileHover属性更新为:

<motion.li key={id} className="card" whileHover={{
  position: 'relative',
  zIndex: 1,
  background: 'white',
  scale: [1, 1.4, 1.2],
  rotate: [0, 10, -10, 0],
  transition: {
    duration: .2
  }
}}>

We’re specifying 2 sets of keyframes, which are the following:

我们指定了2组关键帧,如下:

  • It’s initial size is 1x and has 0 rotation (or no rotation)

    初始大小为1x,旋转0(或不旋转)
  • It then scales to 1.4x the size and rotates 10 degrees

    然后缩放到1.4倍大小并旋转10度
  • It then scales back down to 1.2x the size and rotates the other way to -10 degrees

    然后将其缩小为大小的1.2倍,并以另一种方式旋转到-10度
  • At this point, the scale keyframes are complete, so we wouldn’t be scaling anything more, but we have 1 last rotation, where we rotate back to our initial position of 0 (or no rotation)

    至此,缩放关键帧已完成,因此我们将不再缩放任何缩放,但最后旋转1次,然后旋转回到初始位置0(或不旋转)

And if we reload the page and hover over our elements, we can see our effects in action!

而且,如果我们重新加载页面并将鼠标悬停在元素上,那么我们可以看到效果在起作用!

Without keyframes, we can only do animation effects from a single initial state to another single value. But with our keyframes, we can add more dynamic animations moving around to different values.

没有关键帧,我们只能将动画效果从单个初始状态转换为另一个单个值。 但是有了关键帧,我们可以添加更多动态动画,以移动到不同的值。

Follow along with the commit!

跟随提交!

奖励步骤:在Next.js Rick and Morty应用程序中获得一些动画怪异 (Bonus Step: Getting a little weird with animations in our Next.js Rick and Morty app)

To add another layer of fun to this, we can play with other properties that make our animations even more dynamic.

要为此增加更多的乐趣,我们可以使用其他属性使动画更加动态。

To start, we’re going to kick our hover effects up a notch.

首先,我们将悬停效果提高一个档次。

On our pages/index.js file inside the whileHover prop of our <motion.li> card element, let’s add the following property:

<motion.li>卡元素的whileHover内的pages/index.js文件中,让我们添加以下属性:

filter: [
  'hue-rotate(0)',
  'hue-rotate(360deg)',
  'hue-rotate(45deg)',
  'hue-rotate(0)'
],

Here, we’re setting up a new set of keyframes that will “rotate” the hue of the image based on the hue-rotate CSS function.

在这里,我们将设置一组新的关键帧,这些关键帧将基于hue-rotate CSS函数 “旋转”图像的色调

And if we save and reload our page, this gives us a nice little color effect.

而且,如果我们保存并重新加载页面,这将为我们带来很好的色彩效果。

But that’s too subtle enough for me — I want it a little more weird.

但这对我来说太微妙了-我想要它更奇怪。

Let’s update our filter property to the following:

让我们将filter属性更新为以下内容:

filter: [
  'hue-rotate(0) contrast(100%)',
  'hue-rotate(360deg) contrast(200%)',
  'hue-rotate(45deg) contrast(300%)',
  'hue-rotate(0) contrast(100%)'
],

Now, not only does the color  change, we use the contract CSS function to make the colors more extreme giving us an even stranger effect.

现在,不仅颜色发生了变化,我们还使用了Contract CSS函数使颜色更加极端,从而给我们带来了更加陌生的效果。

Next, we can do something a bit similar with our page transitions!

接下来,我们可以对页面过渡做一些类似的事情!

To do this, we’re going to use a new part of the Motion component lifecycle — the exit. To do this, we need to make use of Motion’s AnimatePresence  component which allows us to animate components when they’re removed from the React tree.

为此,我们将使用Motion组件生命周期的新部分-出口。 为此,我们需要使用Motion的AnimatePresence组件,当从React树中删除组件时,该组件可以为它们设置动画。

So to start, let’s open up pages/_app.js and import that component at the top:

首先,让我们打开pages/_app.js并在顶部导入该组件:

import { motion, AnimatePresence } from 'framer-motion';

Next, we want to wrap our <motion.div> component with our new AnimatePresence component:

接下来,我们要用新的AnimatePresence组件包装<motion.div>组件:

<AnimatePresence>
      <motion.div key={router.route} initial="pageInitial" animate="pageAnimate" variants={{

With our component wrapped, we can now set our new lifecycle prop exit  along with its variant:

包装完组件后,我们现在可以设置新的生命周期道具exit及其变体:

<motion.div key={router.route} initial="pageInitial" animate="pageAnimate" exit="pageExit" variants={{
  pageInitial: {
    opacity: 0
  },
  pageAnimate: {
    opacity: 1
  },
  pageExit: {
    backgroundColor: 'white',
    filter: `invert()`,
    opacity: 0
  }
}}>

In the above, we’re:

在上面,我们是:

  • Configuring a pageExit variant

    配置pageExit变体

  • We set out exit lifecycle prop to pageExit

    我们向pageExit设置了exit生命周期道具

  • Inside of our pageExit variant, we set the background color to white and we add a filter to invert the colors

    pageExit变体内部,我们将背景色设置为白色,并添加了一个滤镜以反转颜色

Note: it’s important to set the background color to white, otherwise, the invert filter won’t apply to the background.

注意:将背景颜色设置为白色非常重要,否则,反转滤镜将不适用于背景。

And if we save and reload the page, when we navigate to another element, we get our effect!

而且,如果我们保存并重新加载页面,则导航到另一个元素时,我们将获得效果!

Follow along with the commit!

跟随提交!

我们还能做什么? (What else can we do?)

添加一些动画以错开搜索结果 (Add some animations to stagger the search results)

If you check out my original demo that I wrote this tutorial based on, I add a feature that makes the results float in by shifting up slightly.

如果您查看了我编写本教程所基于的原始演示,那么我将添加一项功能,使结果略微上移即可浮动结果。

We can do that with the staggerChildren transition property and the setting the x and y position properties on our list elements.

我们可以使用staggerChildren过渡属性以及在列表元素上设置x和y位置属性来做到这一点。

https://github.com/colbyfayock/rick-and-morty-wiki/blob/master/pages/index.js#L11

https://github.com/colbyfayock/rick-and-morty-wiki/blob/master/pages/index.js#L11

动画按钮 (Animate the buttons)

Currently the buttons are just static. Add some hover and click effects to the buttons like Load More at the bottom.

当前按钮是静态的。 将鼠标悬停并单击效果到底部的“加载更多”之类的按钮。

添加更多怪异效果 (Add more weird effects)

This is Rick and Morty after all, make it as weird as you can! But still make sure it’s usable.

毕竟,这是瑞克和莫蒂,让它尽可能古怪! 但是仍然要确保它是可用的。

翻译自: https://www.freecodecamp.org/news/how-to-add-interactive-animations-and-page-transitions-to-a-next-js-web-app-with-framer-motion/

framer x使用教程

把这段 C++ 代码转换成 C 代码并不是一件简单的事情,因为 C++ 和 C 有许多语法上的不同,C++ 有许多 C 中没有的特性,例如模板、类和命名空间等等。因此,我们需要对代码进行适当的修改和调整。以下是将 C++ 代码转换为 C 代码的一种可能的方式: ```c struct Rect { float x, y, width, height; }; struct FramerOptions { float max_zoom_ratio; float target_crop_to_roi_ratio; }; struct Framer { struct Rect region_of_interest_; struct FramerOptions options_; }; float clamp(float value, float min_value, float max_value) { if (value < min_value) { return min_value; } else if (value > max_value) { return max_value; } else { return value; } } struct Rect ComputeActiveCropRegion(struct Framer *framer, int frame_number) { const float min_crop_size = 1.0f / framer->options_.max_zoom_ratio; const float new_x_crop_size = clamp(framer->region_of_interest_.width * framer->options_.target_crop_to_roi_ratio, min_crop_size, 1.0f); struct Rect active_crop_region; active_crop_region.x = framer->region_of_interest_.x + (framer->region_of_interest_.width - new_x_crop_size) / 2.0f; active_crop_region.y = framer->region_of_interest_.y; active_crop_region.width = new_x_crop_size; active_crop_region.height = framer->region_of_interest_.height; return active_crop_region; } ``` 需要注意的是,C 中没有命名空间的概念,因此我们将结构体 `Rect`、`FramerOptions` 和 `Framer` 放在了全局命名空间中。另外,C 中没有 `std::clamp` 函数,我们需要手动实现一个 `clamp` 函数来实现相同的功能。最后,建议根据实际情况对代码进行适当的调整,以便更好地适应 C 语言的语法和特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值