Creating an Animated Valentine’s Day Card with Snap.svg

Share this article

Last year I showed you how to create a resolution independant infographic with Snap.svg library. Snap is a JavaScript library designed to make it easy to work with SVG.

While we obtained a good result, our creation was mostly a static drawing without any real bells and whistles.

Today I’m going to show you how to achieve some cool effects and animations while we create an animated SVG Valentine’s Day love card. You’ll also learn how to incorporate Google’s web fonts as well your SVG drawings and some advanced text manipulations.

While it’s relatively simple to create static SVG in a host of graphics programs, Snap.svg is one of the best ways to create dynamic, interactive SVGs. We will cover some techniques that you should be able to apply to many different applications.

Let’s get started.

First, open up your favorite editor and create a new HTML document. Then we add references for two of the Google’s web fonts and for the Snap.svg library.

We’ll do this by putting the next 3 lines inside the head tag. This sets up Snap for us and includes a couple of Google Fonts.

<link href='http://fonts.googleapis.com/css?family=Niconne' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Oleo+Script' rel='stylesheet' type='text/css'>
<script src="http://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.3.0/snap.svg-min.js">
</script>

Now, inside the body tag, we create a script tag and put the following code in it:

window.onload = function () {

var card = Snap(600, 400);
}

The windows.onload function makes sure that the page is fully loaded before executing any JavaScript. The card variable represents our SVG canvas with width and height set to 600 and 400 pixels.

<!-- SVG Heart Shape -->
	 
	<svg version="1.1" id="heart" xmlns="https://www.w3.org/2000/svg" xmlns:xlink="https://www.w3.org/1999/xlink" x="0px" y="0px"
	     width="300px" height="200px" viewBox="0 0 300 200" enable-background="new 0 0 300 200" xml:space="preserve">
	<path fill-rule="evenodd" clip-rule="evenodd" fill="none" d="M149.95,43.749C111.115-25.583,0.729-9.406,0.002,71.063
	    c-0.402,44.195,52.563,60.716,87.829,78.384c34.196,17.135,58.534,40.574,62.347,50.553c3.266-9.777,30.373-33.88,62.028-51.032
	    c34.612-18.755,88.231-34.189,87.829-78.385C299.304-10.087,186.998-22.818,149.95,43.749z"/>
	</svg>

Next, we put the above raw SVG code below the script tag. This is a SVG path for the heart shape which we’ll use a bit later. I used Inkscape to create the path data. Then, we move back inside the script tag and place the following lines of code below the card variable.

// Utilities

    var dropShadow = card.paper.filter(Snap.filter.shadow(0, 2, 3))

    var bgGradient = card.paper.gradient("r(0.5, 0.5, 0.5)#EE2C34-#821D2D");
    var barGradient = card.paper.gradient("l(0, 0.5, 1, 0.5)#00ADEF-#EC008B:75");

These are some utilities: a drop shadow filter and two gradients (one radial and one linear). We’ll need them throughout the code below.

Now, we are ready to start building the actual card. We begin by adding a warm red sunburst background.

// Card's Background

    var background = card.paper.rect(0, 0, 600, 400).attr({fill: bgGradient, stroke: "none"})

    var rays = card.circle(300, 200, 300).attr({
      fill: "none",
      stroke: "red",
      strokeWidth: 580,
      strokeDasharray: "20 20",
      opacity: 0.2
    });

We create a rectangle and fill it with our already defined radial gradient. The next thing we want to make is a bunch of rays spreading out from the center of the card. This seems tricky, but thanks to a small stroke trick we’ll achieve that effect pretty easily.

First, we create a circle with red stroke and fill set to “none”, and then, to mimic the effect of rays, we set strokeWidth to be extremely tick (filling the whole canvas) and give the strokeDasharray attribute a value of “20 20” (resulting in a dashed line).

OK. The stage is now set! Let’s add the actors.

// Hearts Shapes

    Snap.select("#heart").appendTo(card);

    var heartLeft = Snap.select("path").attr({
        fill: "#00ADEF",  
        filter: dropShadow, 
        transform: "t50,80",
        opacity: 0.9
    }).insertAfter(rays);

    var heartRight = heartLeft.clone().attr({
        fill: "#EC008B", 
        filter: dropShadow,
        transform: "t250,80", 
        opacity: 0.9
    });

Now, we are need the SVG code which we place at the end of our body tag. First, we select it by its ID #heart and append it to the canvas. Then, we select the actual path, give it the desired attributes, and make sure that it is inserted after the rays (which means above them). Next, we create the second heart shape by cloning the first one and changing the fill and transform attributes.

We have two lovely hearts and now we want to position the text “I LOVE U” on them. Here we’ll call on the Google’s web font “Oleo Script”.

// Hearts Texts

    var iuText = card.paper.text(185,200, ['I','U']).attr({
        fill: "#B5DD25", 
        fontFamily: "Oleo Script", 
        fontSize: "72px", 
        filter: dropShadow,
        opacity: 0
    }).animate({opacity: 1}, 2000);

        iuText.select("tspan:nth-child(2)").attr({dx: "160px"});

    var loveText = card.paper.text(290,85, ["L", "O", "V", "E"]).attr({
        fill: "#B5DD25", 
        fontFamily: "Oleo Script", 
        fontSize: "24px", 
        filter: dropShadow,
        opacity: 0
    }).animate({opacity: 1}, 2000);

        loveText.selectAll("tspan").attr({x: 290, dy: "1.2em"});

The first chunk of text creates two strings “I” and “U”. By default they are positioned them together, but we want them separated. We do this by selecting the “U” string and moving it away 160 pixels (by using the dx attribute).

The second text creates four strings: one for each letter from the word “love”. The last line of code make the text to appear vertically by selecting each letter and giving it one and the same coordinates for x, and setting the dy attribute to “1.2em”.

Now, it’s time to move to the bottom of our card.

var ribbon = card.paper.rect(0, 300, 600, 70).attr({fill: "#6F2570", filter: dropShadow});

    var bar = card.paper.rect(0, 300, 600, 10).attr({fill: barGradient});

Here, we create a ribbon with a bar at the top. We apply the drop shadow effect to the ribbon and fill the bar with a linear gradient with colors matching those from the heart shapes. And the next thing we’re going to add is a cool rotating text above the ribbon. This time we’ll use the Google’s web font “Niconne”.

// Rotating Wish Text

    setTimeout(function(){

      var wishText = "Happy Valentine's Day \u2763";  // create the wish text

      var charsGroup = card.g();  // create a group for the individual characters

      var charsArray = wishText.split('');  // split the wish text to characters 
      var wishTextChars = charsGroup.text(110, 355, charsArray).attr({  // create a text element with an individual string for each character
          fill: "#D6DF23",
          fontFamily: "Niconne", 
          fontSize: "42px",
          filter: dropShadow,
          opacity : 1, 
      });
        
      var singleChars = charsGroup.selectAll("tspan").attr({opacity: 0});  // select all strings/characters and hide them initially

      function charsAnimation( element ) {  // a function for animating each character
        Snap.animate(0,1, function( value ) {
          element.attr({ opacity: value, rotate: (value * 360) });
        }, 2000 );
      }

      for( var i=0; i < singleChars.length; i++ ) {  // go through each character and animate it
        setTimeout( 
          charsAnimation.bind(null, singleChars[i]) , i * 300);
      }

    }, 2000);

To complete our creation we’re going to add a randomized raining hearts effect. This is something you’d find hard to produce in a standard SVG graphics program.

We’re going to randomize four characteristics of this rain. Two different heart characters will be rendered at randomized sizes, colors and timings.

// Hearts Rain Effect

    setTimeout(function(){

      function randomNums(min, max) {  // a function generating random numbers
        
        return Math.floor( Math.random() * ( 1 + max - min ) ) + min;
        
      }
          
      setInterval(function () {  // create new hearts set every 2 seconds

        for (var i = 1; i < 29; i++) {

          var hearts = ["\u2764", "\u2665"];  // unicode characters for hearts
          var colors = ["#D691BF","#D74498", "#A54A9C"];  // different colors for the hearts

          var heart = randomNums(0,1);
          var color = randomNums(0, 2);
          var size = randomNums(3, 6);
          var time = randomNums(5, 10);

          var mutableX = i * 20;

          var heartsRain = card.paper.text(mutableX, -50, hearts[heart]).attr({
              fill: colors[color],
              fontSize: size * 5, 
              opacity: 0.3
          }).animate({transform: "t0,500", opacity: 0.9}, time * 1500, mina.linear);

        };

      }, 2000);

    }, 7000);

And now we’re done. You can see the final outcome here:

See the Pen vEpQOr by (@Secret Sam ) on CodePen.

As you can see by combining our imagination with the capabilities of Snap.svg we can create many cool drawings and animations like the beautiful animated love card we’ve just created.

I hope you’ve enjoyed the tutorial and I wish Happy Valentine’s Day to all of you!

Frequently Asked Questions about Creating an Animated Valentine’s Day Card with Snap SVG

How can I add more animations to my Valentine’s Day card using Snap SVG?

Snap SVG is a powerful tool that allows you to create complex animations. To add more animations to your Valentine’s Day card, you can use the animate() function. This function allows you to animate different attributes of your SVG elements over a specified duration. You can animate attributes like position, size, rotation, color, and more. You can also chain animations together to create more complex animation sequences. Remember to experiment and play around with different animations to create a unique and personalized Valentine’s Day card.

Can I use Snap SVG to create interactive Valentine’s Day cards?

Yes, you can use Snap SVG to create interactive Valentine’s Day cards. Snap SVG provides functions like click(), hover(), and drag() that allow you to add interactivity to your SVG elements. For example, you can make a heart shape enlarge when it’s clicked, or make a text message appear when the mouse hovers over a certain area. This can make your Valentine’s Day card more engaging and fun for the recipient.

How can I add music to my animated Valentine’s Day card?

While Snap SVG doesn’t directly support adding music, you can use HTML5’s audio element to add music to your animated Valentine’s Day card. You can control the playback of the music using JavaScript, allowing you to synchronize the music with your animations. Remember to choose a romantic song that fits the theme of Valentine’s Day.

Can I use Snap SVG to create 3D animations?

Snap SVG is primarily designed for 2D vector graphics, and it doesn’t directly support 3D animations. However, you can simulate 3D effects by manipulating the size, position, and perspective of your SVG elements. For example, you can make a heart shape appear to move towards or away from the viewer by increasing or decreasing its size.

How can I share my animated Valentine’s Day card with others?

Once you’ve created your animated Valentine’s Day card, you can share it with others by hosting it on a web server. You can then send the URL of the card to the recipient. Alternatively, you can save the card as an HTML file and send it as an email attachment. Remember to test the card in different web browsers to ensure it works correctly.

Can I use Snap SVG to animate text?

Yes, you can use Snap SVG to animate text. You can animate the position, size, color, and other attributes of text elements. You can also create text effects like typing, fading, and scrolling. This can be useful for adding a personal message to your Valentine’s Day card.

How can I add a background image to my animated Valentine’s Day card?

While Snap SVG doesn’t directly support background images, you can use HTML and CSS to add a background image to your animated Valentine’s Day card. You can then use Snap SVG to create animations on top of the background image. Remember to choose a background image that complements your animations and fits the theme of Valentine’s Day.

Can I use Snap SVG to create animations with multiple scenes?

Yes, you can use Snap SVG to create animations with multiple scenes. You can create each scene as a separate SVG element, and then use the animate() function to transition between the scenes. This can be useful for telling a story or conveying a complex message in your Valentine’s Day card.

How can I optimize my animated Valentine’s Day card for mobile devices?

To optimize your animated Valentine’s Day card for mobile devices, you can use responsive design techniques. You can use CSS media queries to adjust the size and layout of your SVG elements based on the screen size. You can also use the viewBox attribute of the SVG element to control the aspect ratio and scaling of your animations.

Can I use Snap SVG to create animations with user input?

Yes, you can use Snap SVG to create animations with user input. You can use functions like click() and drag() to allow the user to interact with your SVG elements. You can also use the val() function to get the value of form elements, allowing you to create animations based on user input. This can make your Valentine’s Day card more interactive and personalized.

Ivaylo GerchevIvaylo Gerchev
View Author

I am a web developer/designer from Bulgaria. My favorite web technologies include SVG, HTML, CSS, Tailwind, JavaScript, Node, Vue, and React. When I'm not programming the Web, I love to program my own reality ;)

AlexWJavaScriptSVG
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week