在省略号路径上使用@keyframes对svg进行动画处理

如何解决在省略号路径上使用@keyframes对svg进行动画处理

正如标题所述,我正在尝试在看起来像省略号路径的svg上进行动画处理 第一个图标(无穷大符号)。我试过使用转换,但是动作很糟糕。我该如何以一种流畅的方式实现这一目标?

我找到了一些有关类似内容文章,但并没有使我得到平滑的省略号: https://www.useragentman.com/blog/2013/03/03/animating-circular-paths-using-css3-transitions/ http://thenewcode.com/860/Animating-Elements-In-Arcs-Circles-and-Ellipses-With-CSS https://usefulangle.com/post/32/moving-an-element-in-circular-path-with-css

这是笔https://codepen.io/acubaniti/pen/abNqzEV?editors=1100链接

这是代码

#gesture {
  width: 300px;
  height: 300px;
}

#phone {
  fill: white;
  animation: phone-orbits-cw 6s cubic-bezier(0.5,0.38,0.1) infinite;
  opacity: 0;
  transform: rotate3d(0,0) translate3d(0,0);
  will-change: transform,opacity;
  transform-style: preserve-3d;
  transform-origin: center top;
}

#left,#right {
  fill: none;
  stroke-width: 10;
  stroke-miterlimit: 10;
  stroke: white;
  transform-origin: 200px 150px;
  animation-fill-mode: forwards;
  stroke-dasharray: 314;
  stroke-dashoffset: 314;
  opacity: 0;
}

#right {
  animation: circle-fill 6s linear infinite;
  stroke: white;
  transform: rotate(-180deg);
}

#left {
  animation: circle-fill-left 6s linear infinite;
  stroke: white;
  transform: rotateX(180deg);
}

@keyframes circle-fill {
  0%,12.5% {
    stroke-dashoffset: 314;
    opacity: 1;
  }
  12.5%,100% {
    stroke-dashoffset: 0;
  }
  37.5% {
    opacity: 1;
  }
  49%,100% {
    opacity: 0;
  }
}
@keyframes circle-fill-left {
  12.5% {
    stroke-dashoffset: 314;
    opacity: 1;
  }
  25% {
    stroke-dashoffset: 0;
  }
  37.5% {
    opacity: 1;
  }
  49%,100% {
    opacity: 0;
    stroke-dashoffset: 0;
  }
}
@keyframes phone-orbits-cw {
  0% {
    opacity: 0;
    transform: rotate3d(0,0);
  }
  45% {
    opacity: 0;
    transform: rotate3d(0,1,-360deg) translate3d(2%,-5%,0) rotate3d(0,360deg);
  }
  58.75% {
    opacity: 1;
    transform: rotate3d(0,360deg);
  }
  72.5% {
    opacity: 1;
  }
  86.25% {
    opacity: 1;
    transform: rotate3d(0,360deg) translate3d(-2%,-360deg);
  }
  100% {
    opacity: 1;
    transform: rotate3d(0,-360deg) translate3d(0,360deg);
  }
}
@keyframes phone-orbits-ccw {
  0% {
    opacity: 0;
    transform: rotate3d(0,0);
  }
  40% {
    opacity: 0;
    transform: rotate3d(0,180deg) translate3d(0,-180deg);
  }
  45% {
    opacity: 1;
  }
  50% {
    opacity: 1;
    transform: rotate3d(0,-180deg) translate3d(2%,180deg);
  }
  75% {
    opacity: 1;
  }
  100% {
    opacity: 1;
    transform: rotate3d(0,-180deg);
  }
}
<html>
  <body style="background-color: black;"> 
    <svg id="gesture" viewBox="0 0 300 300" xml:space="preserve">
      <g id="phone">
        <path  d="M212.1 23.1H90.2c-4.8 0-8.8 3.9-8.8 8.8v236.4c0 4.8 3.9 8.8 8.8 8.8h121.9c4.8 0 8.8-3.9 8.8-8.8V31.8c0-4.8-4-8.7-8.8-8.7zm0 8.5c.1 0 .2.1.2.2v28.4H90.2V31.6h121.9zM90 268.2l.2-200.6h122.1l-.2 200.8-122.1-.2z"/>
        <circle cx="151.1" cy="248.2" r="8.8"/>
        <path d="M142 49.5h18.3c2.3 0 4.1-1.8 4.1-4.1s-1.8-4.1-4.1-4.1H142c-2.3 0-4.1 1.8-4.1 4.1s1.8 4.1 4.1 4.1z"/>
      </g>
      <circle id="right" cx="200" cy="150" r="50"/>
      <circle id="left" cx="100" cy="150" r="50"/>
    </svg> 
  </body>
</html>

谢谢。

解决方法

如果您可以牺牲浏览器的兼容性,则应该可以使用motion path以更加语义化的方式来做到这一点。它需要Chrome 64,Edge 79,Firefox 72,Opera 45,但不支持Safari。

以下示例以多种方式简化了代码。首先,我将两个圆重写为一条路径,并对其进行了另外的移动,以使路径的起点和终点(“无穷大”符号的中点)位于坐标系的原点。这是因为此路径将被重用为运动路径-不用引号,如果您使用CSS,这是不可能的,但是您只需复制并粘贴路径命令即可。

通过stroke-dashoffset动画使我的生活更轻松,该路径还获得了属性(不是CSS属性!)pathLength="100"。这基本上是一个任意值,这意味着:对于所有沿路径的距离计算,将视为 100作为路径长度。

第二,我使用相同的路径命令定义了一个offset-path。将offset-rotate设置为0deg以避免手机在移动时沿切线路径旋转。在动画过程中,offset-distance从0增加到100%。

#gesture {
  width: 300px;
  height: 300px;
}

#phone {
  fill: white;
  animation: phone-orbit 6s ease-in-out infinite;
  opacity: 0;
  offset-path: path("M0 0 A 30 30 0 0 1 60 0 A 30 30 0 0 1 0 0 A 30 30 0 0 0 -60 0 A 30 30 0 0 0 0 0");
  offset-rotate: 0deg;
  offset-distance: 0;
  will-change: transform,opacity;
}

#infinity {
  fill: none;
  stroke-width: 6.666;
  stroke: white;
  animation-fill-mode: forwards;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  opacity: 0;
  animation: infinity-fill 6s linear infinite;
}

@keyframes infinity-fill {
  0%,25% {
    stroke-dashoffset: 100;
    opacity: 1;
  }
  25%,100% {
    stroke-dashoffset: 0;
  }
  37.5% {
    opacity: 1;
  }
  49%,100% {
    opacity: 0;
  }
}
@keyframes phone-orbit {
  0% {
    opacity: 0;
  }
  40% {
    opacity: 0;
  }
  45% {
    opacity: 1;
  }
  50% {
    offset-distance: 0%;
  }
  100% {
    opacity: 1;
    offset-distance: 100%;
  }
}
<body style="background-color: black;"> 
    <svg id="gesture" viewBox="0 0 300 300" xml:space="preserve">
      <g id="phone">
        <path  d="M212.1 23.1H90.2c-4.8 0-8.8 3.9-8.8 8.8v236.4c0 4.8 3.9 8.8 8.8 8.8h121.9c4.8 0 8.8-3.9 8.8-8.8V31.8c0-4.8-4-8.7-8.8-8.7zm0 8.5c.1 0 .2.1.2.2v28.4H90.2V31.6h121.9zM90 268.2l.2-200.6h122.1l-.2 200.8-122.1-.2z"/>
        <circle cx="151.1" cy="248.2" r="8.8"/>
        <path d="M142 49.5h18.3c2.3 0 4.1-1.8 4.1-4.1s-1.8-4.1-4.1-4.1H142c-2.3 0-4.1 1.8-4.1 4.1s1.8 4.1 4.1 4.1z"/>
      </g>
      <path id="infinity" transform="translate(150 150) scale(1.666)" d="M0 0 A 30 30 0 0 1 60 0 A 30 30 0 0 1 0 0 A 30 30 0 0 0 -60 0 A 30 30 0 0 0 0 0"  pathLength="100"/>
    </svg> 
</body>

要获得更好的支持,您可以切换到标记内SMIL animation。只有旧版本的IE才能使您失望。

差异主要在于不同动画的启动方式:除了第一个infinityFill动画从0s开始之外,每个后续动画均根据其运行时开始。尤其是phoneOrbit动画从infinityFill动画的结尾开始,然后phoneOrbit的结尾再次从infinityFill开始,依此类推,直到无穷大。

另外,运动路径可以真正地重用。

#gesture {
  width: 300px;
  height: 300px;
}

#phone {
  fill: white;
  opacity: 0;
  will-change: transform,opacity;
}

#infinity {
  fill: none;
    stroke-width: 10;
    stroke: white;
    stroke-dasharray: 100;
  opacity: 0;
}
<body style="background-color: black;"> 
    <svg id="gesture" viewBox="0 0 300 300">
      <defs>
        <path id="motion" d="M0 0 A 30 30 0 0 1 60 0 A 30 30 0 0 1 0 0 A 30 30 0 0 0 -60 0 A 30 30 0 0 0 0 0"  pathLength="100"/>
      </defs>
      <g id="phone">
        <path  d="M212.1 23.1H90.2c-4.8 0-8.8 3.9-8.8 8.8v236.4c0 4.8 3.9 8.8 8.8 8.8h121.9c4.8 0 8.8-3.9 8.8-8.8V31.8c0-4.8-4-8.7-8.8-8.7zm0 8.5c.1 0 .2.1.2.2v28.4H90.2V31.6h121.9zM90 268.2l.2-200.6h122.1l-.2 200.8-122.1-.2z"/>
        <circle cx="151.1" cy="248.2" r="8.8"/>
        <path d="M142 49.5h18.3c2.3 0 4.1-1.8 4.1-4.1s-1.8-4.1-4.1-4.1H142c-2.3 0-4.1 1.8-4.1 4.1s1.8 4.1 4.1 4.1z"/>
        <animateMotion id="phoneOrbit" dur="3s"
                       begin="infinityFill.end" rotate="0">
          <mpath href="#motion" />
        </animateMotion>
        <animate attributeName="opacity" dur="6s"
                 begin="infinityFill.begin"
                 values="0;0;1;1" keyTimes="0;.45;.5;1" />
      </g>
      <use id="infinity" href="#motion" transform="translate(150 150) scale(1.666)">
        <animate id="infinityFill" attributeName="stroke-dashoffset"
                 dur="3s" begin="0s;phoneOrbit.end"
                 values="100;0;0" keyTimes="0;.5;1" />
        <animate attributeName="opacity" dur="3s"
                 begin="infinityFill.begin"
                 values="1;1;0" keyTimes="0;.75;1" />
      </use>
    </svg> 
</body>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?