【问题标题】:SVG CSS animation smooth transition and point of originSVG CSS 动画平滑过渡和原点
【发布时间】:2021-01-03 17:28:52
【问题描述】:

我有以下设置,其中多个对象以交错的延迟缩小。我面临以下问题:

  • 缩小动画设置为从 0% 加速到 15%,然后减慢其余关键帧的速度。但是当动画从 15% 过渡到 16% 时,动作明显不和谐。我怎样才能使这个过渡顺利?
  • 当圆圈开始时,它们从左侧出现,而不是以它们的原点为中心。我该如何解决这个问题?

HTML:

<div>
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <circle class="blk" cx="10" cy="10" r="5"/>
  
  <circle class="red" cx="20" cy="10" r="5" color="red" stroke="red" fill="red"/>
  
  <circle class="green" cx="30" cy="20" r="5" color="red" stroke="green" fill="green"/>
</svg>
</div>

CSS:

.blk{
  animation-name: zoom-out;
  animation-duration: 2s;
    animation-timing-function: ease-in-out;
    -webkit-animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
  animation-delay: 2.5s;
}


.red{
  animation-name: zoom-out;
  animation-duration: 2s;
    animation-timing-function: ease-in-out;
    -webkit-animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
  animation-delay: 1.5s;
}

.green{
  animation-name: zoom-out;
  animation-duration: 2s;
    animation-timing-function: ease-in-out;
    -webkit-animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
  animation-delay: 0.5s;
}

@keyframes zoom-out {
    0% {
        transform: scale(5,5);
    }
    15% {
        transform: scale(2,2);
    }
    100% {
        transform: scale(1,1);
    }
}  

【问题讨论】:

    标签: css animation svg


    【解决方案1】:

    一种可能的解决方案是使用 cx="0" 和 cy="0" 的圆圈,并使用具有 x 和 y 位置的圆圈,如下所示:

    circle {
      animation-name: zoom-out;
      animation-duration: 2s;
      /*animation-timing-function: ease-in-out;
        -webkit-animation-timing-function: ease-in-out;*/
      animation-iteration-count: infinite;
    }
    
    #blk {
      animation-delay: 2.5s;
    }
    
    #red {
      stroke: red;
      fill: red;
      animation-delay: 1.5s;
    }
    
    #green {
      stroke: green;
      fill: green;
      animation-delay: 0.5s;
    }
    
    @keyframes zoom-out {
      0% {
        transform: scale(5, 5);
      }
      15% {
        transform: scale(2, 2);
      }
      100% {
        transform: scale(1, 1);
      }
    }
    <div>
      <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
        <defs>
          <circle id="blk" r="5" />
          <circle id="red" r="5" />
          <circle id="green" r="5" />
        </defs>
    
        <use xlink:href="#blk" x="10" y="10" />
        <use xlink:href="#red" x="20" y="10" />
        <use xlink:href="#green" x="30" y="20" />
    
      </svg>
    </div>

    另外,为了使过渡顺利,您可以使用animation-timing-function: linear; 而不是ease-in-out

    更新

    OP 正在评论:

    至于原点,我使用的实际 SVG 是一个插画矢量,其中的每个对象都有多个路径和形状。因此,红色圆圈实际上是一个具有 50 条路径/形状的对象。如何将路径集合的坐标归零?

    接下来是我使用路径集合的示例:

    let wrap = document.querySelector("#red .wrap")
    let bb = wrap.getBBox();
    
    wrap.setAttribute("transform",`translate(${-(bb.x + bb.width/2)}, ${-(bb.y + bb.height/2)})`)
    g[id] {
      animation-name: zoom-out;
      animation-duration: 2s;
      animation-iteration-count: infinite;
    }
    
    #red {
      stroke: red;
      fill: red;
      animation-delay: 1.5s;
    }
    
    @keyframes zoom-out {
      0% {
        transform: scale(5, 5);
      }
      15% {
        transform: scale(2, 2);
      }
      100% {
        transform: scale(1, 1);
      }
    }
    
    svg{border:solid}
    <svg viewBox="0 0 1000 500">
      <defs>
      <g id="red">
        <g class="wrap">
    <path id="body" fill-rule="evenodd" clip-rule="evenodd" d="M121.506,108.953c3.145-2.115,5.896-3.967,8.624-5.802 c20.948,12.522,42.66,12.281,65.725,4.354c0.778,3.128,1.687,6.18,2.285,9.291c3.208,16.677,0.616,36.326-2.758,52.719
        c0,0-152.162,0.035-154.82,0.035c8.408,10.604,18.647,16.674,31.173,16.227c15.059-0.536,30.099-2.491,45.07-4.433
        c26.453-3.431,50.783,0.317,70.991,19.392c1.675,1.581,7.179,9.382,3.632,13.47c-3.524,4.062-12.062-1.289-13.795-3.036
        c-10.215-10.294-22.693-16.145-37.008-15.98c-14.568,0.166-29.103,2.376-43.679,3.216c-11.405,0.656-22.888,1.255-34.268,0.634
        c-9.862-0.538-18.646-5.258-25.691-12.131c-15.127-14.758-26.56-31.716-26.923-53.792c-0.396-24.125,17.008-44.198,40.835-48.153
        c23.477-3.897,43.372,4.666,62.051,17.569C115.82,104.515,118.537,106.717,121.506,108.953z"/>
    <path id="head" fill-rule="evenodd" clip-rule="evenodd" d="M129.747,18.651c3.646,6.147,7.048,11.646,10.189,17.291
        c1.404,2.523,2.761,3.481,5.888,2.718c14.09-3.439,28.227-3.932,42.396-0.046c1.308,0.358,3.815-0.733,4.608-1.923
        c4.043-6.072,7.705-12.398,11.814-19.149c8.693,15.648,15.012,31.447,13.169,49.204c-1.48,14.266-9.114,24.946-22.028,31.172
        c-17.641,8.503-35.969,9.511-54.067,1.823c-15.169-6.443-22.96-18.723-23.677-35.151C117.396,49.828,122.038,32.188,129.747,18.651z
         M189.467,81.017c7.232,0.084,15.334-6.867,14.292-13.652c-0.832-5.418-11.566-6.019-11.732-6.025
        c-7.238-0.308-13.768,6.133-14.144,13.949C177.731,78.444,182.773,80.938,189.467,81.017z M145.369,81.453
        c3.597,0.294,11.258-2.441,11.324-6.992c0.079-5.443-3.357-10.158-8.897-12.255c-5.807-2.197-16.523,1.484-17.065,5.19
        C129.692,74.494,138.107,81.089,145.369,81.453z"/>
        </g>
      </g>
      </defs>
     <use xlink:href="#red"  x="300" y="175" />
    </svg>

    为了将路径集合的坐标归零我正在使用 javaScript。

    • 首先我将路径包装在一个组中 class="wrap"
    • 我正在获取包装的边界框:let bb = wrap.getBBox();
    • 我正在使用边界框值来计算所需的平移并设置环绕的变换属性。

    【讨论】:

    • 谢谢!使用线性使动画更流畅。至于原点,我使用的实际 SVG 是一个插画矢量,其中的每个对象都有多个路径和形状。因此,红色圆圈实际上是一个具有 50 条路径/形状的对象。如何将路径集合的坐标归零?
    • 我已经更新了我的答案。请看一看。
    猜你喜欢
    • 2013-08-02
    • 1970-01-01
    • 2019-04-07
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-15
    • 1970-01-01
    相关资源
    最近更新 更多