【问题标题】:Animate scale rotate svg element动画比例旋转 svg 元素
【发布时间】:2019-03-29 20:43:54
【问题描述】:

假设我有一个用 inkscape 制作的 svg。 在这个带有视图框的 SVG 集中,我想为 SVG 中的每个元素设置动画。 翻译或不透明度没有问题......但是当我需要旋转或缩放单个元素时,它表现得很奇怪。

我尝试正确理解视图框的概念,但我需要一些帮助。

我知道当我只有一个viewbox时我只有一个原点我应该设置多个viewbox吗?

<?xml version="1.0" encoding="UTF-8"?>
<svg id="SVGRoot" version="1.1" viewBox="0 0 700 500" xmlns="http://www.w3.org/2000/svg">
 
  // rotate or scale acting weird
  <ellipse id="path9238" cx="332.91" cy="143.85" rx="64.941" ry="67.676" style="fill-rule:evenodd;fill:#f00;stroke:#000"/>
  // rotate or scale acting weird
  <rect id="rect9240" x="400.59" y="270.31" width="173.63" height="177.73" style="fill-rule:evenodd;fill:#f00;paint-order:normal"/>
  // rotate or scale acting weird
  <path id="path9242" d="m233.79 453.52-153.64-138.25 196.55-63.937z" style="fill-rule:evenodd;fill:#f00;paint-order:normal"/>
 
</svg>

我正在使用anime.js 3.0 或CSS,或者我可以尝试其他任何东西

【问题讨论】:

  • 嗯,也许我可以看看 transform-b​​ox : fill-box...
  • 旋转和缩放通常需要在执行转换之前进行转换,然后再转换回来,以便被转换的对象在更改时位于原点
  • 具体来说,对象应该将其中心点设置为原点......有很多方法可以做到这一点,但如果不提供动画代码,就不可能告诉你应该如何去做。
  • @Cedric Gourville 如果您想了解有关 svg 转换和技巧的详细说明,可以查看此链接 css-tricks.com/transforms-on-svg-elements

标签: javascript css svg inkscape anime.js


【解决方案1】:

在 Svg 中,任何图形的坐标始终具有从 SVG 画布的左上角计算的绝对值。
因此,在应用 scale(2) 命令时,图形中心的坐标也会翻倍,图形会向右下方移动。

<svg id="SVGRoot" version="1.1"  width="500" height="500" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" style="border:1px solid grey;">
     <rect  id="rect9240" transform="scale(2)" x="100" y="100" width="100" height="100"   style="fill-rule:evenodd;fill:#f00;> stroke:#000; paint-order:normal">
 
	<animateTransform
    	xlink:href="#rect9240"
		attributeName="transform"
		type="scale"
		values="1;2;2;1;1"
		dur="8s"
		fill="freeze"
		repeatcount="indefinite"
		/>
 </rect>		
      <circle cx="150" cy="150" r="3" fill="black" />
		<circle cx="300" cy="300" r="3" fill="dodgerblue" />
	 <text x="150" y="140" font-size="16px" text-anchor="middle" > Center (150,150)	</text>
	  <text x="300" y="290" font-size="16px" text-anchor="middle" > Center (300,300)	</text>
</svg>

要将放大后的图形恢复到原来的位置,必须使用命令translate (X, Y)

@Paul LeBeau 有一篇很棒的帖子here 对此进行了详细解释。

CSS 解决方案

为了不计算图形中心的位置,可以使用CSS规则transform-box: fill-box

当fill-box属性的值被选中时

对象边界框用作参考框。

下面是一个增加和减少图形大小的例子:

svg {
width:50%;
}
.ellipse1, .rect1, .path1 {
transform-box: fill-box;
    animation: scale 3s linear infinite alternate;
	animation-direction: alternate;
transform-origin:50% 50%;
}


@keyframes scale {
    0% { transform: scale(0.5); }
    100% {  transform: scale(1); }
}
<svg id="SVGRoot"  version="1.1" viewBox="0 0 700 500" xmlns="http://www.w3.org/2000/svg">
   <ellipse class="ellipse1" id="path9238" cx="332.91" cy="143.85" rx="64.941" ry="67.676" style="fill-rule:evenodd;fill:#f00;stroke:#000"/>
  
  <rect class="rect1" id="rect9240" x="400.59" y="270.31" width="173.63" height="177.73" style="fill-rule:evenodd;fill:#f00; stroke:#000; paint-order:normal"/>
  
  <path  class="path1" id="path9242" d="m233.79 453.52-153.64-138.25 196.55-63.937z" style="fill-rule:evenodd;fill:#f00;stroke:#000; paint-order:normal"/>
 </svg>
  • 旋转示例

svg {
width:50%;
}
.ellipse1, .rect1, .path1 {
transform-box: fill-box;
    animation: spin 4s linear infinite alternate;
transform-origin:50% 50%;
}


@keyframes spin {
    0% { transform: rotate(0deg); }
    100% {  transform: rotate(359deg); }
}




  <path  class="path1" id="path9242" d="m233.79 453.52-153.64-138.25 196.55-63.937z" style="fill-rule:evenodd;fill:#f00;stroke:#000; paint-order:normal"/>
 
</svg>
<svg id="SVGRoot" version="1.1" viewBox="0 0 700 500" xmlns="http://www.w3.org/2000/svg">

  <ellipse class="ellipse1" id="path9238" cx="332.91" cy="143.85" rx="64.941" ry="67.676" style="fill-rule:evenodd;fill:#f00;stroke:#000"/>

  <rect class="rect1" id="rect9240" x="400.59" y="270.31" width="173.63" height="177.73" style="fill-rule:evenodd;fill:#f00; stroke:#000; paint-order:normal"/>

  <path  class="path1" id="path9242" d="m233.79 453.52-153.64-138.25 196.55-63.937z" style="fill-rule:evenodd;fill:#f00;stroke:#000; paint-order:normal"/>
 
</svg>
  • 增加和旋转

svg {
width:50%;
}
.ellipse1, .rect1, .path1 {
transform-box: fill-box;
    animation: scale1 4s linear, spin 4s linear 4s infinite alternate;
	transform-origin:50% 50%;
}


@keyframes spin {
    0% { transform: rotate(0deg);	}
    100% { transform: rotate(360deg); }
}

@keyframes scale1 {
    0% { transform: scale(0.5);}
    100% {  transform: scale(1);}
}
<svg id="SVGRoot" version="1.1" viewBox="0 0 700 500" xmlns="http://www.w3.org/2000/svg">
   
  <ellipse class="ellipse1" id="path9238" cx="332.91" cy="143.85" rx="64.941" ry="67.676" style="fill-rule:evenodd;fill:#f00;stroke:#000"/>
  
  <rect class="rect1" id="rect9240" x="400.59" y="270.31" width="173.63" height="177.73" style="fill-rule:evenodd;fill:#f00; stroke:#000; paint-order:normal"/>
 
  <path  class="path1" id="path9242" d="m233.79 453.52-153.64-138.25 196.55-63.937z" style="fill-rule:evenodd;fill:#f00;stroke:#000; paint-order:normal"/>
 
</svg>

【讨论】:

    【解决方案2】:

    我猜你的意思是transform-origin CSS 属性。它与svg文件的中心点有关。然后,您需要计算元素的中心点以与文档的中心点相关的动画。
    对于动画,您可以使用CSS animations。

    【讨论】:

      【解决方案3】:

      viewBox的基本原理是4个数字是“x y width height”。通常x/y坐标为0,保持你的原点在左上角。人们经常做的就是把原点放在中间。

      为了做到这一点,您将 viewBox 左上角移动一半宽度和一半高度。在你的情况下“-350 -250 700 500”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-03
        • 1970-01-01
        • 2011-03-01
        • 2023-03-31
        • 2011-07-24
        • 2014-07-23
        • 2019-04-15
        相关资源
        最近更新 更多