Yummygum: Internship blog 3, Creating SVG animations and an electron app

October 29, 2018

This blog was originally published on school blog website this is a republish and translation of the original content

For the past two weeks I have been busy working on the Jollycons website and have continued to work on Tide.

Jollycons

Among other things, I continued working on the SVG animations for the homepage these two weeks.

Friendly style SVG animation

For the friendly style image, we wanted to animate the lines in separate from each other and insert text from the side.

For this I first had to export the image from sketch and place it as inline svg. However, here I ran into the problem that the horizontal lines in sketch were just visible but as svg they were invisible.

After much searching I found out that this is because you cannot do a stroke with a gradient if it is not wider than zero. This means that if there is only a stroke it is not visible. I solved this by making the end position of the line 0.0001 higher than the starting point. This gives the element a height of 0.0001 and thus it does become visible.

I made the x2* (end position) 0.0001 higher than the x1* (start position) because of this the line has a height of 0.0001 and is therefore displayed in the browser.

Now that I solved this problem I started animating the svg, for this I first animated the lines

With the code above, I pass to the masks the style they are supposed to have now. These are relevant to the scroll position in the browser. To avoid writing the same code multiple times I created a style object.

Here I use a setter* (way to execute a function in an object) this way I don't have to write the same code over and over again. This makes the code more DRY* (Don't repeat yourself), this makes the code more maintainable.

If all goes well, we now have the lines in the svg properly animated in the browser. Now let's open our browser and look at this.

Then I started animating the text, I soon found out that animating the text based on the scroll position did not look right. I then chose to have the text come in at a certain scroll position.

With this we animate the two texts, we want these to come in from the side. Now let's view the animation in the browser.

For performance, we want only the area that has changed to be re-rendered* (Calculating where the content belongs on the page). We can check this by opening element inspect and then going to the rendering tool.

In this I turn on paint flashing, this causes the browser to highlight parts that need to be re-rendered.

In addition to checking that no unnecessary extra work is being performed by the browser, this also allows us to see more clearly what exactly we are animating and how we are doing it.

Mistakes and solutions

When creating this animation I ran into only one problem and that was that the horizontal line was not visible in the browser. After much searching I found out the cause, I then compared the different solutions and then chose the one that worked best for my use case* (the purpose of the svg).

Flexible vector SVG animation

For the flexible vectors svg, we want the zoom lens to move across the image.

Before we begin, we need to replace the png for an svg and modify this svg so that it works with React.js. After we have done this we can start creating the animation.

To make an svg work in React.js we need to do a few things, first we need to place the svg code in the React file. Next, we need to replace the all values where there is a line in between* (-) for a capital letter. So for example if we have a value of line-height then we need to make it lineHeight. Once we have done that we just need to change xmlns:link to xmlnsLink. Now that we have done this the svg is ready to be used in React.

In doing this I figured that this animation would work best if we animate the position of the lens along a path and do the animation through breakpoints* (points in the animation that we animate to).

With this code we set the steps of the animation. We use a switch statement here this does the same thing as an if else statement. Which one we use does not make much difference but I chose a switch statement because this is the code default with Yummygum. Now let's view the animation in the browser and check that everything is working properly.

Here something goes wrong the animation feels slow and the rest of the page also becomes very slow. That's not good let's try to figure out what is causing this. Let's open the rendering panel in Chrome and see if we can find anything there.

Here I turn on the FPS* (frames per second) meter, for an animation to look good it should always be at sixty and at least at fifty-seven. If it gets below fifty-seven the animation starts to look slow to the user.

As I thought, the FPS is well below our goal of sixty. Let's turn on paint flashing and see if we can figure out the cause with that. If the animation is working properly only the lens should have a green square around it.

That's weird it seems that in addition to the lens, all content that is not visible is also reloaded. It looks like we've found the culprit, but before we start trying to fix this problem let's rule out that it's not something else.

Instead of testing all the components separately to find the cause I remove the entire contents of the lens. Then if the animation is still slow we know the cause is not there. If the animation is then fast we know the cause is in the lens.

After I removed the contents of the lens I easily achieved our goal of sixty FPS. So then the problem lies in the contents of the lens. Now that we have established that, we can start looking for a solution.

I immediately had an idea what the possible cause was when I saw that the entire content was being recalculated. Since the browser is not supposed to recalculate the elements when we use transform. Since it is an svg all the dots and lines are their own element. So because of this the browser has to recalculate a lot of things while nothing has changed in the elements.

I then initially tried adding the will-change: transform property to the elements. This tells the browser that of this element the transform property is going to change. This allows the browser to animate the animation using the GPU* (video card) instead of the CPU* (processor). This often makes the animation look better.

Unfortunately this did not work, so I started searching through google and then I found out that with SVG transform does not work the same as in HTML and so there as I thought all the elements are recalculated.

After trying many things that all did not work I came up with the idea what if I make the points a PNG and place it in the lens. Then the browser only has to show the PNG again and the bike.

To place the image in the SVG, I used the tag <image />. Let's see if the performance is improved now.

This already looks much better. Normally, I would not recommend this since this would cause the points to no longer be vector and thus may look less sharp on large screens. In this situation, this was just the best solution to the problem. Now let's open the FPS meter again and see if we can get the desired sixty FPS.

We now almost constantly reach sixty fps with the occasional small drop to fifty-nine FPS, but that is acceptable and not really visible to the user.

What did I learn

I have spent the past two weeks learning a lot about animating an SVG and working on an Electron app* (A native app for MacOS).

I have been working on the following points from my PAP

Core task 2 - Learning to work with frameworks such as Gatsby

At Jollycons we use Gatsby, so I have also been learning to work better with this over the past two weeks. Furthermore, at Jollycons I also worked with Contentful, this is a kind of CMS that allows us to retrieve content from an external location.

Personal development learning objective - Improve communication with my colleagues.

This has come back over the past two weeks as I often discuss different solutions to a problem with my colleagues and also discuss more things.

Learning objective in personal development - Giving feedback to teammates.

I have been working on this over the past two weeks by giving feedback on designs and code solutions.

Personal development goal - Better substantiate my choices

This has come back the last two weeks because when I suggest a solution and this solution differs from how we do it now I explain why I did it this way and why this way is a good way for the specific application.

Practice trainer learning objective - Structured workflow with each task you perform

This has come back in recent weeks as I follow the same workflow with each task, this consists of looking at the item in the backlog. Then reviewing what I need to resolve this item. And then accomplishing it and then creating a pull request.

Practitioner's learning objective - Being able to proudly share your work with your colleagues and the outside world.

This has definitely come back as I am very proud of the final result of Jollycons animations. So I would also proudly share these with the outside world.

What will I be doing the upcoming weeks?

Over the next few weeks, I will be connecting the dots at Jollycons and continuing to work on Tide.