Resizing SVG animation while keeping it centered in its container

1.4k views Asked by At

I'm trying to center the <path> animation horizontally and vertically (after having scaled it down with transform="scale(0.5)) while keeping the <svg> at 100% width and height of its container. I'm using Snap.svg.

As you can see below, the <svg> is fine but the <path> is all crammed up in the upper left corner.

var s = Snap("#me");


var myPath = s.select("#mypath");

function reset( el ) {
    el.stop();
    el.attr({ "stroke-dashoffset": 125 });
};

function startAnim( el ) {
    el.animate( { "stroke-dashoffset": 600 }, 1000 );
};

reset( myPath );

s.mouseover( function() {
  startAnim( myPath );
} );

s.mouseout( function() {
  reset( myPath );
} );
.test {
    border: 1px solid black;
    height: 500px;
    width: 500px;
}
#me { 
  border: 2px solid green;
}
#mypath { 
  border: 2px solid blue;
  display: flex;
  justify-content: center;
  align-content: center;
  flex-direction: column;
}
<script src="http://tedbeer.net/lib/snap.svg-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">
    <div class="pie">
        <svg id="me" viewBox="0 0 350 350">
        <!--<svg id="me" viewBox="0 0 350 350" width="100" height="100">-->
            <path id="mypath" d="M 175, 175 m 0, -75 a 75, 75 0 1, 0 0, 150 a 75, 75 0 1, 0 0, -150" fill="none" stroke="#ccc" stroke-width="150" stroke-dasharray="0 600 600 0" stroke-dashoffset="1000" transform="scale(0.5)">
            </path>
        </svg>
    </div>
</div>

2

There are 2 answers

0
Ian On BEST ANSWER

If you want to amend the transform via Snap you would do it very slightly different.

The end result is probably the same to the browser as mefs solution, as it will end up having a similar matrix on the element itself, its really down to whats the most convenient.

You can specify a center point for the scaling, just add it after the scale x & y parameters.

myPath.transform('s0.5,0.5,175,175');  

jsfiddle

Edit: Actually I'm an idiot, its even more simple. I just remembered that Snap automatically uses the center of an object on transform strings if not specified. So in fact you can reduce it to this..

myPath.transform('s0.5');

jsfiddle

4
Mehdi On

The position of your object is affected by the scaling transform. Add a translation in order to move the object to the correct position, right after scale:

transform="scale(0.5)translate(175,175)"

updated snippet:

var s = Snap("#me");


var myPath = s.select("#mypath");

function reset( el ) {
    el.stop();
    el.attr({ "stroke-dashoffset": 125 });
};

function startAnim( el ) {
    el.animate( { "stroke-dashoffset": 600 }, 1000 );
};

reset( myPath );

s.mouseover( function() {
  startAnim( myPath );
} );

s.mouseout( function() {
  reset( myPath );
} );
.test {
    border: 1px solid black;
    height: 500px;
    width: 500px;
}
#me { 
  border: 2px solid green;
}
#mypath { 
  border: 2px solid blue;
  display: flex;
  justify-content: center;
  align-content: center;
  flex-direction: column;
}
<script src="http://tedbeer.net/lib/snap.svg-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">
    <div class="pie">
        <svg id="me" viewBox="0 0 350 350">
        <!--<svg id="me" viewBox="0 0 350 350" width="100" height="100">-->
            <path id="mypath" d="M 175, 175 m 0, -75 a 75, 75 0 1, 0 0, 150 a 75, 75 0 1, 0 0, -150" fill="none" stroke="#ccc" stroke-width="150" stroke-dasharray="0 600 600 0" stroke-dashoffset="1000" transform="scale(0.5)translate(175,175)">
            </path>
        </svg>
    </div>
</div>

Edit: possible other options based on the question in your comment:

option 1 If you do not want to have the translate at all, You can change the viewBox coordinates, this way:

<svg id="me" viewBox="-75 -75 350 350" width="100%" height="100%">

Please note that I haven't taken the time to calculate the exact ones that would be relevant to you, but you get the idea. You should adapt the four values so that they match to the viewport you want to obtain.

option 2

do some math to replace your current path coordinates by the ones for an object twice smaller, so that you don't need the scale transform anymore.