Wednesday, 10 February 2021

Web Tutorial: CNY 2021 and Valentine's Day Animation (Part 2/2)

Now that we've created an ox head and made a simple animation, let's build on that. Add this to your styles. It will set font. I prefer a nice orange myself.
svg
{
    width: 800px;
    height: 550px;
    background-color: rgba(200, 200, 200, 0);
}

g.text
{
    stroke-width: 1px;
    font: 20px Georgia;
    fill: rgba(255, 100, 0, 0);
}


g.light
{
    fill: rgba(255, 100, 0, 0.5);
}


Now add a g tag at the end of the svg. The x and y attributes have been filled out for you; this will differ based on your choice of font.
        <path d="M340 355 q0 20 -20 30 Z"></path>
        <path d="M460 355 q0 20 20 30 Z"></path>
    </g>

    <g class="text">
        <text x="250" y="200">
            year of the
        </text>
        <text x="450" y="200">
            X
        </text>
        <text x="320" y="220">
            valentine's day 2021
        </text>
    </g>
</svg>


Now if you refresh, you won't see a damn thing because the alpha aspect of the fill attribute has been set to 0, which is zero opacity. We are going to animate this. In this case, we animate the g tag instead of the text itself. The effect is that all the text within that g tag gets animated. We animate the fill property, setting it to full opacity at the end of the transformation.
<g class="text">
    <text x="250" y="200">
        year of the
    </text>
    <text x="450" y="200">
        X
    </text>
    <text x="320" y="220">
        valentine's day 2021
    </text>

    <animate
        id="animateTextAppear"
        attributeName="fill"
        from="rgba(255, 0, 0, 0)"
        to="rgba(255, 100, 0, 1)"
        fill="freeze"
        begin="0s"
        dur="2.5s"
        repeatCount="1"
    />

</g>


And the text fades into view. Well done! Don't worry about the missing "o" in "ox". We will be filling that in.



Now, what would Valentine's Day be without a heart? We'll create one. Notice that the horns are kind of heart-shaped. That's deliberate. Our heart will originate from there. Add this styling. The heart will have a nice red fill.
    g.dark
    {
        fill: rgba(100, 0, 0, 1);
    }

    g.heart
    {
        fill: rgba(255, 0, 0, 1);
    }

</style>


Since we want the heart to appear behind the horns, we'll need to code the g tag right at the top of the SVG.
<svg>
    <g class="heart">
        <path d="M400 285 q-120 -60 0 35 q120 -100 0 -35 Z">
    </g>


    <g class="dark">
        <path d="M380 320 l-30 5 q-80 -110 40 -50 q-100 -40 0 45 Z"></path>
        <path d="M420 320 l30 5 q80 -110 -40 -50 q100 -40 0 45 Z"></path>
    </g>


Oooh. Nice.



Now hide the heart by doing this. We're going to make it fade into view like we did for the text.
g.heart
{
    fill: rgba(255, 0, 0, 0);
}


Now add an animate tag in there. Give it an id of animateHeartAppear, and pretty much do what we did for the text. Refresh. Does it fade into view like a good little heart? Excellent.
<g class="heart">
    <path d="M400 285 q-120 -60 0 35 q120 -100 0 -35 Z">
        <animate
            id="animateHeartAppear"
            attributeName="fill"
            from="rgba(255, 0, 0, 0)"
            to="rgba(255, 0, 0, 1)"
            fill="freeze"
            begin="2s"
            dur="1.5s"
            repeatCount="1"
        />
    </path>
</g>


We follow up with another animation with an id of animateHeartExpand. This begins when animateHeartAppear ends. We animate the d attribute, making the heart appear to stretch upwards.
<animate
    id="animateHeartAppear"
    attributeName="fill"
    from="rgba(255, 0, 0, 0)"
    to="rgba(255, 0, 0, 1)"
    fill="freeze"
    begin="2s"
    dur="1.5s"
    repeatCount="1"
/>

<animate
    id="animateHeartExpand"
    attributeName="d"
    from="M400 285 q-120 -60 0 35 q120 -100 0 -35 Z"
    to="M400 120 q-120 -60 0 120 q120 -180 0 -120 Z"
    fill="freeze"
    begin="animateHeartAppear.end"
    dur="2s"
    repeatCount="1"
/>


See what I mean?!



Next up is animateHeartContract, which begins as animateHeartExpand ends. This one brings the heart back to more normal proportions.
<animate
    id="animateHeartExpand"
    attributeName="d"
    from="M400 285 q-120 -60 0 35 q120 -100 0 -35 Z"
    to="M400 120 q-120 -60 0 120 q120 -180 0 -120 Z"
    fill="freeze"
    begin="animateHeartAppear.end"
    dur="2s"
    repeatCount="1"
/>

<animate
    id="animateHeartContract"
    attributeName="d"
    from="M400 120 q-120 -60 0 120 q120 -180 0 -120 Z"
    to="M400 150 q-120 -60 0 100 q120 -150 0 -100 Z"
    fill="freeze"
    begin="animateHeartExpand.end"
    dur="0.5s"
    repeatCount="1"
/>


Great...



Now for two more animate tags. The first one is animateHeart1 and it begins after animateHeartContract ends, and also after animateHeart2 ends. The second is animateHeart2, and it begins after animateHeart1 ends. Thus animateHeart1 and animateHeart2 have a bit of a circular thing going on. It's meant to make the heart pulsate, sort of. Try it!
<animate
    id="animateHeartContract"
    attributeName="d"
    from="M400 120 q-120 -60 0 120 q120 -180 0 -120 Z"
    to="M400 150 q-120 -60 0 100 q120 -150 0 -100 Z"
    fill="freeze"
    begin="animateHeartExpand.end"
    dur="0.5s"
    repeatCount="1"
/>

<animate
    id="animateHeart1"
    attributeName="d"
    from="M400 150 q-125 -60 0 100 q125 -150 0 -100 Z"
    to="M400 150 q-130 -60 0 90 q110 -150 0 -90 Z"
    fill="freeze"
    begin="animateHeartContract.end;animateHeart2.end"
    dur="1.5s"
    repeatCount="1"
/>


<animate
    id="animateHeart2"
    attributeName="d"
    from="M400 150 q-130 -60 0 90 q110 -150 0 -90 Z"
    to="M400 150 q-125 -60 0 100 q125 -150 0 -100 Z"
    fill="freeze"
    begin="animateHeart1.end"
    dur="1.5s"
    repeatCount="1"
/>


But the thing is, the heart still doesn't really resemble the "o" in "ox". So let's give it a little center. Add another path tag within the same g tag. Give it the same dimensions as the heart in animateHeart2, but smaller.
    <animate
        id="animateHeart2"
        attributeName="d"
        from="M400 150 q-130 -60 0 90 q110 -150 0 -90 Z"
        to="M400 150 q-125 -60 0 100 q125 -150 0 -100 Z"
        fill="freeze"
        begin="animateHeart1.end"
        dur="1.5s"
        repeatCount="1"
    />
</path>

<path d="M400 155 q-110 -60 0 90 q110 -155 0 -90 Z">

</path>


Then animate it, to make it fade in. I like to call this one animateHeartHoleAppear, though it doesn't really matter what we call it since we won't be referencing it at all. The animation will begin after animateHeartContract ends. Unlike the pulsating heart, however, this one will be white in color.
    <animate
        id="animateHeart2"
        attributeName="d"
        from="M400 150 q-130 -60 0 90 q110 -150 0 -90 Z"
        to="M400 150 q-125 -60 0 100 q125 -150 0 -100 Z"
        fill="freeze"
        begin="animateHeart1.end"
        dur="1.5s"
        repeatCount="1"
    />
</path>

<path d="M400 155 q-110 -60 0 90 q110 -155 0 -90 Z">
    <animate
        id="animateHeartHoleAppear"
        attributeName="fill"
        from="rgba(255, 0, 0, 0)"
        to="rgba(255, 255, 255, 1)"
        fill="freeze"
        begin="animateHeartContract.end"
        dur="0.5s"
        repeatCount="1"
    />

</path>


Now tell me this ain't the most stylish damn thing you've ever seen!



And that's it! Happy Chinese New Year and happy Valentines Day!
Enjoy the results of your SVG animation, tinker with it, have fun! And have a lovey-dovey festive season!

May you have an ox-spicious Chinese New Year,
T___T

No comments:

Post a Comment