admin管理员组

文章数量:1420606

Assuming I have an svg made with inkscape. In this SVG set with a viewbox, I want to animate each element inside the SVG. There is no problem for translate or opacity ... but when I need to rotate or scale a single element, it acting weird.

I try to correctly understand the concept of the viewbox but I need some help.

I understand that I have only one origin point when I have only one viewbox should I set multiple viewbox ?

<?xml version="1.0" encoding="UTF-8"?>
<svg id="SVGRoot" version="1.1" viewBox="0 0 700 500" xmlns="">
 
  // 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>

Assuming I have an svg made with inkscape. In this SVG set with a viewbox, I want to animate each element inside the SVG. There is no problem for translate or opacity ... but when I need to rotate or scale a single element, it acting weird.

I try to correctly understand the concept of the viewbox but I need some help.

I understand that I have only one origin point when I have only one viewbox should I set multiple viewbox ?

<?xml version="1.0" encoding="UTF-8"?>
<svg id="SVGRoot" version="1.1" viewBox="0 0 700 500" xmlns="http://www.w3/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>

I'm using anime.js 3.0 or CSS or I can try anything else

Share Improve this question asked Mar 29, 2019 at 20:43 user7637140user7637140 4
  • hmm maybe I can take a look to transform-box : fill-box... – user7637140 Commented Mar 29, 2019 at 22:05
  • Rotation and scale often need to be translated prior to performing the transformation then translated back so that the object being transformed is at the origin when it changes – mike510a Commented Mar 31, 2019 at 0:38
  • Specifically the object should have its center point set to the origin... there are many ways to do this but without providing the animation code, its impossible to tell you how you should go about it.. – mike510a Commented Mar 31, 2019 at 0:43
  • @Cedric Gourville If you want a detailed explanation about svg transformations and tricks, you can check out this link css-tricks./transforms-on-svg-elements – Syam Commented Jul 27, 2019 at 15:51
Add a ment  | 

3 Answers 3

Reset to default 6

In Svg, the coordinates of any figure always have an absolute value that is calculated from the upper left corner of the SVG canvas.
Therefore, when applying the scale (2) mand, the coordinates of the center of the figure will also be doubled and the figure will shift to the right and down.

<svg id="SVGRoot" version="1.1"  width="500" height="500" viewBox="0 0 500 500" xmlns="http://www.w3/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>

To return the enlarged figure to its original position, you must use the mand translate (X, Y)

There is a great post here by @Paul LeBeau where this is explained in detail.

CSS solution

In order not to calculate the position of the center of the figure, you can use the CSS rule transform-box: fill-box

When the value of the fill-box attribute is selected

The object bounding box is used as the reference box.

Below is an example of increasing and decreasing the size of figures:

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/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>

  • Rotation example

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/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>

  • Increase and rotation

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/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>

I guess you mean the transform-origin CSS propierty. It is related to the center point of the svg file. Then, you need to calculate the center point of the element to animate related to document's center point.
For the animations you can use CSS animations.

The basics of viewBox is that the 4 numbers are "x y width height”. Generally the x/y coordinates are 0 which keeps your origin in the top left corner. Something people often do is place the origin in the middle.

In order to do that you move your viewBox top left by half of the width and half the height. In your case "-350 -250 700 500".

本文标签: javascriptAnimate scale rotate svg elementStack Overflow