您的位置:

提升网页动画体验的不一样选择:使用CSS cubic-bezier曲线

在网站和应用中,动画是让用户享受最佳体验的重要组成部分之一,而所选动画曲线对用户感知的影响是不可忽略的。然而,开发者通常没有对此问题足够的认识和理解,从而通常会选择默认的简单动画,浪费了一个机会,以获取更好的用户体验。

一、 何为cubic-bezier曲线?

在CSS中,提供了一种曲线函数cubic-bezier(),该曲线由四个值组成,这四个值控制曲线的弯曲程度。实际上,cubic-bezier()函数描述了一个三次贝塞尔曲线,通过两个锚点和两个控制点定义。锚点是曲线的起点和终点,而控制点会将曲线弯曲并确定它的形状,因此,定义了四个值(P0,P1,P2,P3)以及两个锚点之后即可确定cubic-bezier曲线。

  .box {
    animation: move 2s cubic-bezier(0.42,-0.25,0.99,0.67)
  }
  
  @keyframes move {
    from {
      transform: translateX(0);
    }
    to {
      transform: translateX(500px);
    }
  }

二、 如何使用cubic-bezier曲线提高用户体验?

1、弹性动画:要制作一种具有类似于弹簧的效果的动画,可以调整曲线的P1和P2的值,并控制它们之间的曲线峰度。

  .box {
    animation: move 1.8s cubic-bezier(0.2, 0.84, 0.75, 1.1);
  }
  
  @keyframes move {
    from {
      transform: translateY(0);
    }
    to {
      transform: translateY(200px);
    }
  }

2、自然过渡:当我们要制作视觉效果更自然的动画时,可以使用Safari和Chrome浏览器的默认值,即cubic-bezier(0.25,0.1,0.25,1.0)。

  .box1 {
    animation: move1 2s cubic-bezier(0.25,0.1,0.25,1.0);
  }
  
  @keyframes move1 {
    from {
      opacity: 0;
      transform: translateY(-100px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

3、趣味性动画:我们可以通过修改曲线的控制点,制作出具有趣味性的动画效果, 如下例所示。

  .box2 {
    animation: move2 3s cubic-bezier(.31,1.32,.72,.27)
  }
  
  @keyframes move2 {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }

三、cubic-bezier曲线的可视化工具

使用一些开源的在线工具,可轻松制作满足特定动画需要的cubic-bezier函数。

1、 Cubic-Bezier

2、 Ceaser

四、结论

cubic-bezier曲线是一个毫无疑问的有价值的工具,可以差异化选择动画曲线,从而增强用户体验。除了基础的应用,还可以考虑通过使用开源工具获得更高级别的优化。尽管如此,我们需要根据场景自行评估各种变体,以确保用户的体验和目标对话。

提升网页动画体验的不一样选择:使用CSS cubic-bez

2023-05-17
提高网站用户体验的CSS动画技巧

2023-05-12
使用CSS Animation来优化您的网站动效

2023-05-12
transition-timing-function:理解动

2023-05-18
CSS Bounce Expression in After

2023-05-12
when-present<#else>when-missing. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: ${item.id} [in template "article/detail/index.ftl" at line 48, column 106] ---- Java stack trace (for programmers): ---- freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...] at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134) at freemarker.core.EvalUtil.coerceModelToTextualCommon(EvalUtil.java:481) at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:401) at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:370) at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:104) at freemarker.core.DollarVariable.accept(DollarVariable.java:63) at freemarker.core.Environment.visit(Environment.java:371) at freemarker.core.IteratorBlock$IterationContext.executedNestedContentForCollOrSeqListing(IteratorBlock.java:321) at freemarker.core.IteratorBlock$IterationContext.executeNestedContent(IteratorBlock.java:271) at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:244) at freemarker.core.Environment.visitIteratorBlock(Environment.java:645) at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:108) at freemarker.core.IteratorBlock.accept(IteratorBlock.java:94) at freemarker.core.Environment.visit(Environment.java:335) at freemarker.core.Environment.visit(Environment.java:341) at freemarker.core.Environment.visit(Environment.java:341) at freemarker.core.Environment.process(Environment.java:314) at freemarker.template.Template.process(Template.java:383) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.processTemplate(FreeMarkerView.java:332) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.doRender(FreeMarkerView.java:266) at org.springframework.web.servlet.view.freemarker.FreeMarkerView.renderMergedTemplateModel(FreeMarkerView.java:220) at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:181) at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:314) at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1431) at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1167) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1106) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at com.software.filter.HttpSpiderIdentifyFilter.doFilter(HttpSpiderIdentifyFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:340) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) at java.base/java.lang.VirtualThread.run(VirtualThread.java:309)