What you'll learn:
transform functionanimationControlsuseAnimationNow 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.
transformWe 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.
Now the question is how to get the scale value out from the handleDrag function and set it to Skinny's cheek Frame.
animationControlsWe 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
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 (
...
)
}
useAnimationWe 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.
If you test your slider now, everything should be working smoothly, and you should have a happy Skinny!
In the next post, we'll learn about a very important concept in JavaScript and almost every other programming language, variable scope.