What you'll learn:
transform
functionanimationControls
useAnimation
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.
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
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.
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.