Expert Front-End Coding Services:info@plutonium.dev

How to Morph SVG Paths

How to Morph SVG Paths

The Plutonium Animator includes a normalizing SVG path morphing plugin that generates buttery smooth animations.

Normalization features include adding points as needed, rotation alignment, and point flow adjustment in a clockwise or counterclockwise direction. The plugin is extremely lightweight at just 3K, making the total required library size which includes the full API a scant 8K compressed.

The morph plugin and Animator library are free to use under an open source MIT license!

Download the Animator Library from GitHub

We will be using the Plutonium React-State-Animator in a generic HTML page environment. However you can also use the same principals and library to perform morphs in your React project.

Open the 'morph.html' Sample

You can optionally follow along by opening the ‘morph.html’ sample in the download.

Add the Animator Scripts

Add a link to the animator and plugin scripts in the head of your page. Choose the relative or CDN links below.


//relative link
<script src="lib/src/min/animator.js"></script>
<script src="lib/src/min/morph.js"></script>

//CDN link
<script src="https://cdn.jsdelivr.net/npm/react-state-animator@1/lib/min/animator.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-state-animator@1/lib/min/morph.js"></script>

Add the SVG

In our sample we will be animating from an inline SVG path. Add the SVG path to your page.


<svg class="svg" viewBox="0 0 100 100">
    <path 
        id="morphLogo"
        fill-rule="evenodd"
        fill="transparent"
        stroke="rgba(121,209,31,1)"
        stroke-width="3%"
        d="m 50.000001,36.358318 c -5.859836,0 -10.58963,5.005203 -10.58963,11.206232 0,6.200528 4.729794,11.206225 10.58963,11.206225 5.859827,0 10.589629,-5.005697 10.589629,-11.206225 0,-6.201029 -4.729802,-11.206232 -10.589629,-11.206232 z m 42.299921,17.323585 c -0.141433,0 -0.282627,-0.0075 -0.420529,-0.02567 L 70.755204,50.963995 C 68.997088,50.737876 67.67009,49.176476 67.645855,47.305287 67.563018,40.78301 64.340007,34.884305 59.028013,31.520939 57.514633,30.561441 56.901142,28.566231 57.593942,26.847942 L 65.949861,6.1463041 c 0.386168,-0.9520277 1.123677,-1.6926383 2.044275,-2.0465062 0.91682,-0.3538669 1.933899,-0.2881255 2.809306,0.1860283 15.470981,8.3578518 25.084952,24.9408268 25.084952,43.2787008 0,0.860881 -0.02066,1.721771 -0.06209,2.571701 -0.05176,1.035951 -0.503366,1.998944 -1.251226,2.666582 -0.64126,0.572764 -1.447724,0.879071 -2.275131,0.879071 z m -84.5998444,0 c -0.8274034,0 -1.6338626,-0.306307 -2.2751237,-0.87907 C 4.6768558,52.135195 4.225267,51.172202 4.1737307,50.13625 c -0.041414,-0.84993 -0.062125,-1.710819 -0.062125,-2.5717 0,-18.337875 9.6139703,-34.92085 25.0849433,-43.2782067 0.875647,-0.4669232 1.892485,-0.5326726 2.809313,-0.1860212 0.920356,0.3538679 1.658099,1.0944704 2.044267,2.0465052 l 8.355927,20.7016387 c 0.692801,1.718034 0.0793,3.713491 -1.43407,4.672997 -5.311996,3.363359 -8.535246,9.261824 -8.617843,15.78434 -0.02422,1.871443 -1.351233,3.432597 -3.109349,3.658716 L 8.1206027,53.656753 c -0.1378998,0.01796 -0.2790953,0.02515 -0.4205251,0.02515 z M 75.909062,82.901266 63.131138,64.896848 c -1.058727,-1.494169 -2.964856,-1.942418 -4.518237,-1.045914 -2.612115,1.569118 -5.647804,2.390657 -8.612668,2.390657 -2.964856,0 -6.000551,-0.821786 -8.612659,-2.390657 -1.553381,-0.896504 -3.459752,-0.448255 -4.518245,1.045914 L 24.091173,82.901266 c -0.565012,0.821797 -0.847169,1.867712 -0.635612,2.838912 0.141432,1.045915 0.706212,1.942408 1.553381,2.540328 7.412276,5.154871 16.095768,7.844361 24.991059,7.844361 8.89529,0 17.578782,-2.68949 24.991289,-7.844361 0.847171,-0.59792 1.411954,-1.494162 1.553387,-2.540328 0.211556,-0.9712 -0.0706,-2.017115 -0.635615,-2.838912 z"
    />
</svg>

Add the Animation

The sample animates both the path and stroke color as shown below. Instead of defining the initial path and stroke color on the start keys ‘pos_30’, we grab the values from the element to save the duplication.

The only added requirement for animating a path is that the Animator needs to be told it’s a path. We do this with the optional tween property. Also note that ‘applyAs’ is set as ‘attribute’ to override the default ‘style’ type apply.


document.addEventListener("DOMContentLoaded", e => {
    //create a new plutonium animator instance
    const animator = new PU_Animator({
        morph:true
    });
    //add the animation
    const morphElm = document.querySelector("#morphLogo");
    let animation = animator.add(morphElm, 3, {
        stroke:{
            keys:{
                pos_30:morphElm.getAttributeNS(null,'stroke'),
                pos_70:'rgba(98,219,252,1)'
            },
            tween:{
                applyAs:'attribute'
            }
        },
        d:{
            keys:{
                pos_30:morphElm.getAttributeNS(null,'d'),
                pos_70:'M 35.181142,59.459317 C 29.543909,48.726868 25.704496,37.866215 24.103356,28.852301 22.175339,17.991649 23.538247,9.6859054 27.421983,7.2103601 c 4.047173,-2.5823811 11.703837,0.412082 19.73724,8.2721659 6.074915,5.94314 12.3105,14.880743 17.662408,25.069854 5.487645,10.445519 9.601303,21.025344 11.199673,29.92937 2.024972,11.269683 0.385049,19.880668 -3.58456,22.411162 C 68.583481,95.350143 61.536247,92.749446 54.018088,85.621952 47.66893,79.599448 40.873778,70.29555 35.181142,59.459317 Z M 35.167288,40.579853 C 40.787904,29.838246 47.411306,20.748021 53.699523,14.719411 61.275853,7.4545569 68.486524,4.6096642 72.373031,7.0791043 76.422974,9.6523281 77.893917,18.458675 75.7249,30.054971 74.084976,38.821636 70.173541,49.239682 64.835482,59.43795 59.364457,69.892626 53.098403,79.101897 46.896061,85.078614 39.048256,92.639554 31.458075,95.374554 27.485696,92.850172 23.629662,90.399049 22.155947,82.371082 24.003631,71.63558 25.565988,62.557564 29.488507,51.425242 35.167291,40.579853 Z m 14.834094,-9.444312 c 11.252306,0 21.706811,1.779585 29.587858,4.767943 9.496036,3.601902 15.335494,9.062753 15.335494,14.007738 0,5.152553 -6.188496,10.95528 -16.385378,14.676228 -7.709296,2.814369 -17.856316,4.285654 -28.537974,4.285654 -10.953131,0 -21.321761,-1.379713 -29.119703,-4.316178 C 11.017214,60.842082 5.075265,54.966097 5.075265,49.911222 c 0,-4.905303 5.57629,-10.32342 14.939362,-13.919216 7.911517,-3.037198 18.623646,-4.856465 29.986755,-4.856465 z m 8.382442,18.778733 a 8.3824416,9.2367439 0 0 1 -8.382442,9.236745 8.3824416,9.2367439 0 0 1 -8.382441,-9.236745 8.3824416,9.2367439 0 0 1 8.382441,-9.236744 8.3824416,9.2367439 0 0 1 8.382442,9.236744 z',
            },
            tween:{
                applyAs:'attribute',
                isPath:true
            }
      }
    },{
        timing:'ease',
        delay:'0s',
        direction:'alternate',
        iterationCount:'infinite',
        fillMode:'both',
        playState:'running'
    });
});

The sample uses specific key positions of ‘pos_30’ and ‘pos_70’ instead of the shortcut ‘to’ and ‘from’ keys. This adds a nice delay between morphs.

The Animated Morph!

See the Pen SVG Normalizing Path Morph Animation by plutonium.dev (@plutonium-js) on CodePen.37461

Normalization

The morph plugin will automatically normalize paths by filling in points, and adjusting both rotation and flow (clockwise, counterclockwise).

The plugin does not normalize differences in SVG viewBox dimensions. The paths you provide should be designed for the same viewBox or you may get unwanted scaling with the morph transitions.

Leave a Reply

Close Menu