3.6 Making Skinny Happy

Watch the video course

Overview

What you'll learn:

  • transform function
  • animationControls
  • useAnimation

Animating Skinny

Now that we have the position of the slider knob available as info.point.x, we can finally try to make Skinny happy. That is, we want to change the scale of Skinny’s cheek according to info.point.x.

Let's look closer at the info.point.x values that the console prints. We begin at 0 and end at 220.

We can’t directly use the value of x as the scale of Skinny’s cheek. Otherwise, he’d be very mad when his face is 220 times puffier! We need to convert x into a smaller range.

When x is 0, we set the scale to 0.4, when x is 220, we set the scale to 1.5, when x is somewhere in-between, the scale should be between 0.4 and 1.5.

transform

We could work out the math, but the Framer library provides a good utility for this. Back to our import statements, we want to import transform.

import "./styles.css"

transform is a function. Let's call it right before printing info.point.x. We first give it our current value, info.point.x, then the input range in an array form [0, 220], and then the output range in an array [0.4, 1.5].

We can now initialize a variable called scale to save the transform return value.

function App(){
  function handleDrag(event, info) {
    // change scale of Skinny's cheeks according to slider knob position
let newScale = transform(info.point.x, [0, 220],[0.4, 1.5])
console.log(info.point.x, newScale)
} return ( ... ) }

Printing both info.point.x and newScale, separated with a comma, gives us this.

console x position and scale

Now the question is how to get the scale value out from the handleDrag function and set it to Skinny's cheek Frame.

animationControls

We could directly set the scale attribute in that frame to some variable.

{/* Cheek */}
<Frame
  background="url(https://cdn.glitch.com/071e5391-90f7-476b-b96c-1f51f7106b0c%2Fcheek.png)"
  width={79}
  height={67}
  left={155}
  top={135}
  scale={someVariable}
/>

However, we want some animation when the scale value changes. Therefore, we’ll use the animate attribute.

Usually we do this:

{/* Cheek */}
<Frame
  background="url(https://cdn.glitch.com/071e5391-90f7-476b-b96c-1f51f7106b0c%2Fcheek.png)"
  width={79}
  height={67}
  left={155}
  top={135}
  animate={{ scale: 0.5}}
/>

But here we’ll use a new thing called animationControls.

{/* Cheek */}
<Frame
  background="url(https://cdn.glitch.com/071e5391-90f7-476b-b96c-1f51f7106b0c%2Fcheek.png)"
  width={79}
  height={67}
  left={155}
  top={135}
  animate={animationControls}
/>

Looking at the Framer animate documentation

animate documentation

the animate attribute can have three different controls, AnimationControls, TargetAndTransition which we used for our toggle, and VariantLabels which we also used.

We get an error since animationControls is not defined yet.

We’ll define it this way.

import "./styles.css"

function App(){
let animationControls = useAnimation() function handleDrag(event, info) { // change scale of Skinny's cheeks according to slider knob position
let newScale = transform(info.point.x, [0, 220],[0.4, 1.5])
console.log(info.point.x, newScale) } return ( ... ) }

useAnimation

We import useAnimation. Then since useAnimation is a function because of the parentheses, we get its return value, and assign it to animationControls. Now that there are no errors, we can begin our animation with animationControls.start({scale: newScale}).

function App(){
  let animationControls = useAnimation()
  function handleDrag(event, info) {
    let newScale = transform(info.point.x, [0, 220],[0.4, 1.5])
animationControls.start({scale: newScale})
} return ( ... ) }

What’s animationControls? And why can we use dot notation?

animationControls is an object with a property called start whose value is a function which is why we can call it like that. We are also passing an object into the parameter of the start function.

Conclusion

If you test your slider now, everything should be working smoothly, and you should have a happy Skinny!

happy skinny

In the next post, we'll learn about a very important concept in JavaScript and almost every other programming language, variable scope.