Get Started
Get started with Framer by exploring the basics.
1. Layers
Layers can be images, text and more. They have a hierachy and properties defining their position, appearance and interactivity.
2. Animation
Animate states or layer properties like scale and color with various easing or spring curves, repeat and delay options and more.
3. States
States are stored sets of layer properties with values. You can animate states, switch instantly or cycle between them.
4. Events
Events are used to detect and respond to user interactions, animations that start or end, values that change and more.
Align
The Align functions help you quickly position an object on the screen relative to its parent. Use these to place a Layer to the top, bottom, left, right or center of its parent. They can be used as layer properties, in states and animations.
# Create a layer an position it in the center layerA = x: Aligncenter y: Aligncenter # Create a state in the bottom right corner layerA.states = stateA: x: Alignright y: Alignbottom stateB: x: Alignleft y: Aligntop layerAonTap -> layerAstateCycle
The Align functions calculate the correct value for x or y dynamically at the moment you actually want to position them. So if you have a state that puts a layer in the bottom right position, it will always do so, even if you resize the screen in between switching states.
You can also optionally use offsets:
layerA = x: Aligncenter-100 # 100 pixels left from the center y: Aligntop100 # 100 pixels from the top
Please note that left and right only work for the x property, and top and bottom only for the y property. Center works for both. Align is a more flexible alternative to layer.center() that works well with Auto-Code direct editing.
align.bottom(offset)
Position the layer to the bottom of its parent. If there is no parent, it will use the Screen. Bottom only works for the y layer property. It can be used as a property, in states and in animations.
Arguments
offset
— A number (optional).
layerA = y: Alignbottom layerB = y: Alignbottom-100 # 100 pixels from the bottom
align.center(offset)
Place the layer in the center, relative to its parent. If there is no parent, it will use the Screen. It can be used as a property, in states and in animations.
Arguments
offset
— A number (optional).
layerA = x: Aligncenter y: Aligncenter layerB = x: Aligncenter+100 y: Aligncenter-100
align.left(offset)
Position the layer to the left of its parent. If there is no parent, it will use the Screen. Left only works for the x layer property. It can be used as a property, in states and in animations.
Arguments
offset
— A number (optional).
layerA = x: Alignleft layerB = x: Alignleft100 # 100 pixels from the left
align.right(offset)
Place the layer to the right of its parent. If there is no parent, it will use the Screen. Right only works for the x layer property. It can be used as a property, in states and in animations.
Arguments
offset
— A number (optional).
layerA = x: Alignright layerB = x: Alignright-100 # 100 pixels from the right
align.top(offset)
Position the layer to the top of its parent. If there is no parent, it will use the Screen. Top only works for the y layer property. It can be used as a property, in states and in animations.
Arguments
offset
— A number (optional).
layerA = y: Aligntop layerB = y: Aligntop100 # 100 pixels from the top
Animation
Animation objects manage animations targeted on a layer. This is what is created by the layer’s animate function. The only difference is that animation objects don’t start immediately, you have to explicitly execute start()
.
The animation options allow you to define curves, timing, delays and more. Layers can run multiple animations at the same time. If animations affect the same layer properties, only the last one will run.
Properties
layer
— A layer object, the targeted layer.properties
orstate
— An object with target values for the animated properties or a State object.options
— An object with all the animation options like curve, time and more. (Optional)
Example: Layer and properties
Here, we create a new Animation for layerA. Once we start the animation, it will move horizontally from 0
to 100
. Note that we left out many optional arguments. By default, the animation will take 1 second, with an ease
curve.
layerA = # Animate the layer to the right animationA = layerA x: 100 animationAstart
Example: Layer and states
Animate a layer using a layer state by inserting the State object instead of layer properties.
layerA = layerA.states.stateA = x: 100 # Animate the layer to the right animationB = layerA layerAstatesstateA animationBstart
Example: Multiple properties and time
Multiple properties can be animated at once. Here, we animate the x
and opacity
properties, with a duration of 5 seconds.
layerA = # Animate multiple properties for 5 seconds animationC = layerA x: 100 opacity: 0.5 options: time: 5 animationCstart
Example: Repeat and delay
When using repeat, the end values of properties will be reset to their starting position instantly. In the example below, there is a 2 second delay between every repeat.
layerA = # Repeat an animation 5 times, delay for 2 seconds animationD = layerA x: 100 options: repeat: 5 delay: 2 animationDstart
Animation Curves
Bezier.linear
— Constant speed.Bezier.ease
— Ease curve.Bezier.easeIn
— Ease-in curve.Bezier.easeOut
— Ease-out curve.Bezier.easeInOut
— Ease-in-out curve.Spring
— A spring curve with damping.
Example: Bezier
layerA = # Animate with a bezier curve animationA = layerA x: 100 opacity: 0.5 options: curve: Bezier0.250.10.251
Example: Spring
The default spring can be used along with the time
property.
damping
— Bounciness of the spring.mass
— Mass of the animating layer. (Optional)velocity
— Velocity at the start. (Optional)
layerA = # Animate with a spring curve animationA = layerA x: 100 options: curve: Springdamping: 0.5 time: 0.5
Example: Classic Spring
The classic spring cannot be used with the time
property.
tension
— Strength of the spring.friction
— Weight of the spring.velocity
— Velocity at the start. (Optional)tolerance
— Minimal threshold before the animation ends. (Optional)
layerA = # Animate with a spring curve animationA = layerA x: 100 options: curve: Springtension: 250friction: 25
Animatable Properties
Only numeric layer properties and color can be animated:
- x, y, z
- minX, midX, maxX
- minY, midY, maxY
- width, height
- opacity
- rotation, rotationX, rotationY, rotationZ
- scale scaleX, scaleY, scaleZ
- originX, originY, perspective
- scrollX, scrollY
- borderRadius, borderWidth
- shadowX, shadowY, shadowBlur, shadowSpread
- blur, brightness, saturate
- hueRotate, contrast, invert, grayscale, sepia
Multiple Properties
You can start multiple animations targeting the same layer, as long as they don’t target the same properties. If you start two animations both targeting x
for the same layer, the first one will be cancelled.
Performance
Most properties benefit from GPU accelerated drawing. You can animate many of them smoothly. But some properties need to involve the CPU to animate, and are therefore more expensive to render:
- width
- height
- scrollX
- scrollY
- borderRadius
- borderWidth
animation.start()
Start the animation.
layerA = animationA = layerA x: 100 # Nothing will move until we start animationAstart
animation.stop()
Stop the animation.
layerA = animationA = layerA x: 100 animationAstart # Stop the animation animationAstop
animation.reverse()
Create a new animation with all reverse values.
layerA = animationA = layerA x: 100 animationB = animationAreverse # Alternate between the two animations animationAon EventsAnimationEndanimationBstartanimationBon EventsAnimationEndanimationAstart animationAstart
animation.reset()
Reset the layer to its default state.
layerA = animationA = layerA x: 100 animationAstart # On animation end reset the animation animationAon EventsAnimationEnd-> animationAreset
animation.restart()
Reset the layer to its default state and start the animation again.
layerA = animationA = layerA x: 100 animationAstart # On animation end restart the animation animationAon EventsAnimationEnd-> animationArestart
animation.finish()
Stop the currently active animation and jump to its end state.
layerA = animationA = layerA x: 100 time: 3 animationAstart # Finish the animation after a 1 second delay Utilsdelay 1-> animationAfinish
BackgroundLayer
A background layer is just a normal layer, but it scales with your window, so it always covers the entire canvas. If the background layer has a parent, the background will inherit the size of the parent.
layerA = backgroundColor: "white"
Colors can be defined by keywords, but also rgb and hex values.
# Hex value for white layerA = backgroundColor: "#ffffff" # RGB value for white layerA = backgroundColor: "rgb(255,255,255)" # RGBA value for white layerA = backgroundColor: "rgba(255,255,255,1)"
Canvas
The Canvas object contains the size for the current entire document in pixels. It will change if you resize your document by resizing the window it is in.
Canvas.backgroundColor <string>
Sets the background color of the canvas.
# Change the canvas background color Canvas.backgroundColor = "#28affa"
Canvas.image <string>
Sets the background image of the canvas. You can set it as a local path, or a link. The image will always fit to cover the canvas, and will never be stretched.
# Local images Canvas.image = "images/background.png" # Hosted images Canvas.image = "http://framerjs.com/background.png"
Canvas.width <number>
The width of the current entire document in pixels. (Read-only)
print Canvaswidth# Output: 640
Canvas.height <number>
The height of the current entire document in pixels. (Read-only)
print Canvasheight# Output: 480
Canvas.size <object>
The width and height of the current entire document in pixels. (Read-only)
print Canvassize# Output: { width:640, height: 480 }
Canvas.frame <object>
The x, y, width and height of the current entire document in pixels. (Read-only)
print Canvasframe# Output: { x:0, y:0, width:640, height: 480 }
Canvas.convertPointToScreen(point)
Converts a point from the Canvas to the Screen.
point = x: 20 y: 40pointInScreen = CanvasconvertPointToScreenpoint
Canvas.convertPointToLayer(point, layer)
Converts a point from the Canvas to a layer.
point = x: 20 y: 40 layer = pointInLayer = CanvasconvertPointToLayerpointlayer
Color
The Color object can be used to define, detect, modify and mix colors. Colors can be defined using either a string value or an object. All colors are converted to a Color object with r, g, b
, h, s, l
and an a
value.
bg = backgroundColor: "#28affa" print bgbackgroundColor# <Color "#28affa">
Supported color models: CSS Names, HEX, RGB, RGBA, HSL and HSLA.
# Multiple ways to define the same color: blue = "blue"blue = "#28AFFA"blue = "rgb(255, 0, 102)"blue = "rgba(255, 0, 102, 1)"blue = "hsl(201, 95, 57)"blue = "hsla(201, 95, 57, 1)"
You can also create new Color objects and pass in strings, or objects:
# Define a color with a HEX string bg = backgroundColor: "#fff" # Define a color with an RGB object layerA = backgroundColor: r: 255g: 255b: 255 # Define a color with an HSL object layerB = backgroundColor: h: 360s: 1l: 1a: 1
Color Models
You can animate the background color, text color and shadow color of a layer. By default, color transitions use HUSL. With the colorModel
property, you can specify in which model to animate. We support rgb
, hsl
and husl
.
bg = backgroundColor: "blue" # Animate in RGB bganimate backgroundColor: "red" options: colorModel: "rgb"
color.lighten(amount)
Add white and return a lightened color.
Arguments
amount
— A number, from 0 to 100. Set to 10 by default.
# Create a new color, lighten it blue = "#28affa"lighten20 layerA = backgroundColor: blue
color.darken(amount)
Add black and return a darkened color.
Arguments
amount
— A number, from 0 to 100. Set to 10 by default.
# Create a new color, darken it blue = "#28affa"darken20 layerA = backgroundColor: blue
color.saturate(amount)
Increase the saturation of a color.
Arguments
amount
— A number, from 0 to 100. Set to 10 by default.
# Create a new Color, saturate it blue = "#877DD7"saturate100 layerA = backgroundColor: blue
color.desaturate(amount)
Decrease the saturation of a color.
Arguments
amount
— A number, from 0 to 100. Set to 10 by default.
# Create a new Color, desaturate it blue = "#28affa"desaturate25 layerA = backgroundColor: blue
color.grayscale()
Return a fully desaturated color.
# Create a new Color yellow = "yellow" # Convert it to gray gray = yellowgrayscale layerA = backgroundColor: gray
color.gray(amount, alpha)
Generates a transparent white background.
Arguments
amount
— A number representing the amount of white.alpha
— A number representing the alpha. (Optional)
layer = layer.backgroundColor = Colorgray0.5
color.alpha(amount)
Increase the alpha value, also known as opacity, of the color.
Arguments
amount
— A number, from 0 to 1. Set to 1 by default.
# Create a new Color, increase the opacity blue = "#28affa"alpha5 layerA = backgroundColor: blue
Color.mix(colorA, colorB, fraction, limit, model)
Blend two colors together, optionally based on user input. The fraction defines the distribution between the two colors, and is set to 0.5 by default.
Arguments
colorA
— A color, the first onecolorB
— A color, the second onefraction
— A number, from 0 to 1. (Optional)limit
— A boolean, set to false by default. (Optional)model
— A string, the color model used to mix. (Optional)
# Mix red with yellow orange = Colormix"red""yellow"0.5
The limit
defines if the color can transition beyond its range. This is applicable when transitioning between colors, using Utils.modulate. Below, the limit is set to true
, so the transition cannot extend beyond the second color.
# Create new Layer layerA = backgroundColor: "red" # Enable dragging layerA.draggable.enabled = true # On move, transition its color to yellow layerAon EventsMove # Map the dragging distance to a number between 0 and 1 fraction = Utilsmodulateoffsetx0Screenwidth01true # Mix the colors, enable the limit, transition in HUSL layerA.backgroundColor = Colormix"red""yellow"fractiontrue"husl"
Color.random()
Returns a Color instance with a random color value set.
random = Colorrandom
Color.isColor(value)
Checks if the value is a valid color object or color string. Returns true or false.
Arguments
value
— An object or string, representing a color
print ColorisColor "red" # true print ColorisColor"red" # true
Color.isColorObject(value)
Checks if the value is a valid color object. Returns true or false.
Arguments
value
— An object, representing a color
print ColorisColorObject "red" # true print ColorisColorObject"red" # false
Color.isColorString(value)
Checks if the value is a color string. Returns true or false.
Arguments
value
— A string, representing a color
print ColorisColorString"red" # true print ColorisColorString"#28affa" # true
Color.toHexString()
Returns the hexadecimal string representation of a color.
Arguments
value
— An object or string, representing a color
blue = "blue"print bluetoHexString # "#0000ff"
Color.toRgbString()
Returns the RGB string representation of a color.
Arguments
value
— An object or string, representing a color
blue = "blue"print bluetoRgbString # "rgb(0, 0, 255)"
Color.toHslString()
Returns the HSL string representation of a color.
Arguments
value
— An object or string, representing a color
blue = "blue"print bluetoHslString # "hsl(240, 100%, 50%)"
Compatibility
Framer.js | ||
Browsers | Webkit (Chrome, Safari) | |
Platforms | Mac OS X, Windows, Linux | |
Mobile Platforms | iOS, Android, Windows Phone | |
Generator.app | ||
Imports from | Photoshop CC, Sketch 3.4.4 | |
Platforms | Mac OS X, Windows (coming soon) | |
Framer Studio.app | ||
Imports from | Photoshop CC, Sketch 3.4.4 | |
Platforms | Mac OS X 10.10+ |
Defaults
The Framer.Defaults allows you to override the default properties for Layers and Animations when they are created. For example, all new layers get a light blue background color so you can see them. You can override that color here.
# Override the default background color for layers Framer.Defaults.Layer.backgroundColor = "red" # Override the default corner radius for layers Framer.Defaults.Layer.borderRadius = 10 layerA = print layerAbackgroundColor# Output: "red" print layerAborderRadius# Output: 10
Here is an example to set the default animation curve. Note that those will also be used for layer.states switches unless you override them for a layer or state with the animationOptions
property.
# Override the default animation options for all Animations Framer.Defaults.Animation = curve: Springdamping: 0.75 # Override the default corner radius for layers Framer.Defaults.Layer.borderRadius = 10 layerA = layerAanimate x: 100 # The animation will now use the spring curve
Device
The DeviceComponent emulates a device like an iPhone, iPad or Android. It allows you to scale the device, scale the content and adjust the orientation. After the device is set up, everything will render within its screen. Device previews match mirrored previews, meaning that if you're previewing on iPhone and then view it on an iPhone it will appear in fullscreen.
Scaling and orientation properties are also prefixed with Framer.Device:
Framer.Device.contentScale = 0.5Framer.Device.orientation = 90
Underneath, the Device is just a collection of layers. That makes it easy to customize or add behaviour. You can find the entire source on Github. Here are some common examples:
# Set a blurred background image Framer.Device.background.image = "photo.jpg"Framer.Device.background.blur = 10 # Get the screen dimensions for the current device print FramerDevicescreenwidth # Output: 640 print FramerDevicescreenheight # Output: 480
Please note that the scale-to-fit view can render your content off-pixel to retain your screen ratio. Your content will always snap-to-pixel when viewed at 50%, 100% etc. If your browser supports it, device images are compressed with JPEG2000 to reduce image size.
To change the device position simply change the x
and y
values for the screen and device like you would for a normal Layer.
# Set the Device position Framer.Device.screen.x = 50Framer.Device.x = 50 # Change from the current Device position Framer.Device.screen.x += 50Framer.Device.x += 50
Device.customize(deviceType, screenWidth, screenHeight, deviceImage, deviceImageWidth, deviceImageHeight)
Customize the device with a custom device image and sizes. If the device is a phone or tablet you can specify its type which will make sure the device image isn't visible when previewing on the device itself.
# Define and set custom device FramerDevicecustomize deviceType: FramerDeviceTypeTablet screenWidth: 720 screenHeight: 1024 deviceImage: "http://f.cl.ly/items/001L0v3c1f120t0p2z24/custom.png" deviceImageWidth: 800 deviceImageHeight: 1214
Device.deviceType <string>
The type of device to render. Below is an overview of all available options.
Fullscreen
Renders in fullscreen.
Framer.Device.deviceType = "fullscreen"
Apple Watch 38mm
All available Apple Watch 38mm colors.
Framer.Device.deviceType = "apple-watch-38mm-black-steel-black-closed"Framer.Device.deviceType = "apple-watch-38mm-gold-midnight-blue-closed"Framer.Device.deviceType = "apple-watch-38mm-rose-gold-lavender-closed" Framer.Device.deviceType = "apple-watch-38mm-sport-aluminum-blue-closed"Framer.Device.deviceType = "apple-watch-38mm-sport-aluminum-fog-closed"Framer.Device.deviceType = "apple-watch-38mm-sport-aluminum-green-closed"Framer.Device.deviceType = "apple-watch-38mm-sport-aluminum-red-closed"Framer.Device.deviceType = "apple-watch-38mm-sport-aluminum-walnut-closed"Framer.Device.deviceType = "apple-watch-38mm-sport-aluminum-white-closed"Framer.Device.deviceType = "apple-watch-38mm-sport-space-gray-black-closed"
Apple Watch 42mm
All available Apple Watch 42mm colors.
Framer.Device.deviceType = "apple-watch-42mm-black-steel-black-closed"Framer.Device.deviceType = "apple-watch-42mm-gold-midnight-blue-closed"Framer.Device.deviceType = "apple-watch-42mm-rose-gold-lavender-closed" Framer.Device.deviceType = "apple-watch-42mm-sport-aluminum-blue-closed"Framer.Device.deviceType = "apple-watch-42mm-sport-aluminum-fog-closed"Framer.Device.deviceType = "apple-watch-42mm-sport-aluminum-green-closed"Framer.Device.deviceType = "apple-watch-42mm-sport-aluminum-red-closed"Framer.Device.deviceType = "apple-watch-42mm-sport-aluminum-walnut-closed"Framer.Device.deviceType = "apple-watch-42mm-sport-aluminum-white-closed"Framer.Device.deviceType = "apple-watch-42mm-sport-space-gray-black-closed"
iPhone 6s
All available iPhone 6s colors.
Framer.Device.deviceType = "apple-iphone-6s-gold"Framer.Device.deviceType = "apple-iphone-6s-rose-gold"Framer.Device.deviceType = "apple-iphone-6s-silver"Framer.Device.deviceType = "apple-iphone-6s-space-gray"
iPhone 6+
All available iPhone 6+ colors.
Framer.Device.deviceType = "apple-iphone-6s-plus-gold"Framer.Device.deviceType = "apple-iphone-6s-plus-rose-gold"Framer.Device.deviceType = "apple-iphone-6s-plus-silver"Framer.Device.deviceType = "apple-iphone-6s-plus-space-gray"
iPhone 5s
All available iPhone 5s colors.
Framer.Device.deviceType = "apple-iphone-5s-gold"Framer.Device.deviceType = "apple-iphone-5s-silver"Framer.Device.deviceType = "apple-iphone-5s-space-gray"
iPhone 5c
All available iPhone 5c colors.
Framer.Device.deviceType = "apple-iphone-5c-blue"Framer.Device.deviceType = "apple-iphone-5c-green"Framer.Device.deviceType = "apple-iphone-5c-red"Framer.Device.deviceType = "apple-iphone-5c-white"Framer.Device.deviceType = "apple-iphone-5c-yellow"
Nexus
All Google Nexus devices.
Framer.Device.deviceType = "google-nexus-4"Framer.Device.deviceType = "google-nexus-5x"Framer.Device.deviceType = "google-nexus-6p"Framer.Device.deviceType = "google-nexus-9"
HTC One A9
All Google Nexus devices.
Framer.Device.deviceType = "htc-one-a9-black"Framer.Device.deviceType = "htc-one-a9-white"
HTC One M8
All HTC One M8 devices.
Framer.Device.deviceType = "htc-one-m8-black"Framer.Device.deviceType = "htc-one-m8-gold"Framer.Device.deviceType = "htc-one-m8-silver"
Microsoft Lumia 950
All Microsoft Lumia 950 devices.
Framer.Device.deviceType = "microsoft-lumia-950-black"Framer.Device.deviceType = "microsoft-lumia-950-white"
Samsung Note 5
All Samsung Note 5 devices.
Framer.Device.deviceType = "samsung-galaxy-note-5-black"Framer.Device.deviceType = "samsung-galaxy-note-5-gold"Framer.Device.deviceType = "samsung-galaxy-note-5-pink"Framer.Device.deviceType = "samsung-galaxy-note-5-silver-titanium"Framer.Device.deviceType = "samsung-galaxy-note-5-white"
iPad Mini
All available iPad Mini colors.
Framer.Device.deviceType = "apple-ipad-mini-4-silver"Framer.Device.deviceType = "apple-ipad-mini-4-gold"Framer.Device.deviceType = "apple-ipad-mini-4-space-gray"
iPad Air
All available iPad Air colors.
Framer.Device.deviceType = "apple-ipad-air-2-silver"Framer.Device.deviceType = "apple-ipad-air-2-gold"Framer.Device.deviceType = "apple-ipad-air-2-space-gray"
iPad Pro
All available iPad Pro colors.
Framer.Device.deviceType = "apple-ipad-pro-silver"Framer.Device.deviceType = "apple-ipad-pro-gold"Framer.Device.deviceType = "apple-ipad-pro-space-gray"
Apple iMac
The iMac desktop device.
Framer.Device.deviceType = "apple-imac"
Apple MacBook
All available Apple MacBook laptop devices.
Framer.Device.deviceType = "apple-macbook"Framer.Device.deviceType = "apple-macbook-air"Framer.Device.deviceType = "apple-macbook-pro"
Dell XPS
The Dell XPS laptop device.
Framer.Device.deviceType = "dell-xps"
Sony TV
The Sony W850C TV device.
Framer.Device.deviceType = "sony-w85Oc"
Device.fullScreen <boolean>
Set the device to render fullscreen, independent of the deviceType. Set to true or false.
# Render the device in fullscreen Framer.Device.fullScreen = true
Device.deviceScale <number / string>
The scale of the device. Supported scale values range from 0.5 to 1.
Framer.Device.deviceScale = 0.5
Device.setDeviceScale(scale, animate)
The scale of the device and an optional animation (true or false). Supported scale values range from 0.5 to 1.
# Set device scale and animate FramerDevicesetDeviceScale0.5true
Device.contentScale <number>
The scale of the content, including the custom device. Supported scale values range from 0.5 to 1.
# Set content scale Framer.Device.contentScale = 0.5
Device.setContentScale(scale, animate)
Sets the scale of the content, and an optional animation (true or false). Supported scale values range from 0.5 to 1.
# Set content scale and animate FramerDevicesetContentScale0.5true
Device.orientation <number>
The orientation of the device. Supported orientation values are 0 and 90 (portrait and landscape orientations).
Framer.Device.orientation = 90
Device.setOrientation(orientation, animate)
Sets the orientation of the device, and an optional animation (true or false). Supported orientation values are 0 and 90 (portrait and landscape orientations).
# Set orientation and animate FramerDevicesetOrientation90true
Device.orientationName <string>
Set the device orientation by name. Valid options are "portrait" and "landscape". The portrait and landscape values are the same setting the device orientation to 0 and 90 respectively.
# Set orientation to either landscape or portrait Framer.Device.orientationName = "landscape"Framer.Device.orientationName = "portrait"
Device.rotateLeft()
Rotates the device to the left (clockwise).
FramerDevicerotateLeft
Device.rotateRight()
Rotates the device to the right (clockwise).
FramerDevicerotateRight
Draggable
Layers can be made horizontally and/or vertically draggable. They can be tossed around with momentum. To control where they end up, you can define a specific area that a layer can be dragged within. They can optionally be dragged beyond this area, but they will then bounce back by default.
layer.draggable.enabled <boolean>
Enable dragging for the layer.
layerA = layerA.draggable.enabled = true
layer.draggable.horizontal <boolean>
Enable or disable horizontal movement.
layerA = layerA.draggable.enabled = true # Disable horizontal dragging layerA.draggable.horizontal = false
layer.draggable.vertical <boolean>
Enable or disable vertical movement.
layerA = layerA.draggable.enabled = true # Disable vertical dragging layerA.draggable.vertical = false
layer.draggable.speedX <number>
Modify the horizontal dragging speed. The value is in pixels per mouse moved pixels. The default value is 1. When set lower then 1 dragging will be slower than mouse movement and vice versa. You can set the value to 0 to disable horizontal dragging.
layerA = layerA.draggable.enabled = true # Make horizontal dragging slow layerA.draggable.speedX = 0.1 # Make horizontal dragging fast layerA.draggable.speedX = 10
layer.draggable.speedY <number>
Modify the vertical dragging speed. The value is in pixels per mouse moved pixels. The default value is 1. When set lower then 1 dragging will be slower than mouse movement and vice versa. You can set the value to 0 to disable vertical dragging.
layerA = layerA.draggable.enabled = true # Make vertical dragging slow layerA.draggable.speedY = 0.1 # Make vertical dragging fast layerA.draggable.speedY = 10
layer.draggable.constraints <object>
Constraints for the area this layer can be dragged within. If you also set the x and y properties as constraints, the layer will snap to that position on DragStart. The layer will animate to the new point on click.
layerA = layerA.draggable.enabled = true # Set dragging constraints layerA.draggable.constraints = x: 0 y: 0 width: 200 height: 200
layer.draggable.constraintsOffset <object>
Get the offset position of a layer, compared to its dragging contraints. If you set the dragging constraints to { x: 100, y: 100 }, the layer will still be initially positioned at x: 0, y: 0. After dragging, the layer will be bound to its dragging contraints. This offset can be measured with constraintsOffset.
layerA = layerA.draggable.enabled = true # Set dragging constraints layerA.draggable.constraints = x: 100 y: 100 width: 200 height: 200 # Get the constraintsOffset print layerAdraggableconstraintsOffset # Returns { x:-100, y:-100 }
layer.draggable.isBeyondConstraints <boolean>
See if the draggable layer is currently beyond its dragging constraints. (Read-only)
layerA = layerA.draggable.enabled = true # Set dragging constraints layerA.draggable.constraints = x: 100 y: 100 width: 400 height: 400 # On move, see if the layer is beyond constraints or not layerAon EventsMove-> print layerAdraggableisBeyondConstraints
layer.draggable.overdrag <boolean>
Enable or disable dragging beyond the set constraints.
layerA = layerA.draggable.enabled = true layerA.draggable.constraints = x: 0 y: 0 width: 200 height: 200 # Disable dragging beyond constraints layerA.draggable.overdrag = false
layer.draggable.overdragScale <number>
Set the dragging resistance when dragging beyond constraints. The scale is defined with a number between 0 and 1. The default value is 0.5.
layerA = layerA.draggable.enabled = true layerA.draggable.constraints = x: 0 y: 0 width: 200 height: 200 # Increase resistance when dragging beyond constraints layerA.draggable.overdragScale = 0.25
layer.draggable.momentum <boolean>
Enable or disable momentum/inertia simulation. Enabled by default.
layerA = layerA.draggable.enabled = true # Disable momentum layerA.draggable.momentum = false
layer.draggable.momentumOptions <object>
Options for momentum simulation on DragEnd.
layerA = layerA.draggable.enabled = true # Define friction and tolerance of momentum layerA.draggable.momentumOptions = friction: 2.1 tolerance: 0.1
layer.draggable.bounce <boolean>
Spring animation when momentum runs beyond constraints.
layerA = layerA.draggable.enabled = true layerA.draggable.constraints = x: 0 y: 0 width: 200 height: 200 # Snap back after dragging beyond constraints layerA.draggable.bounce = false
layer.draggable.bounceOptions <object>
Options for the spring animations when momentum runs beyond constraints.
layerA = layerA.draggable.enabled = true layerA.draggable.constraints = x: 0 y: 0 width: 200 height: 200 # Define friction, tension and tolerance of bounce layerA.draggable.bounceOptions = friction: 40 tension: 200 tolerance: 0.0001
layer.draggable.velocity <object>
Current velocity for the draggable layer. The velocity is read-only.
layerA = layerA.draggable.enabled = true # On DragMove, print the x and y velocity layerAdraggableon EventsDragMove-> print layerAdraggablevelocity
layer.draggable.direction <string>
Current dragging direction. Returns "up", "down", "left" or "right". (Read-only)
layerA = layerA.draggable.enabled = true # Print the current direction layerAon EventsDragMove-> print layerAdraggabledirection
layer.draggable.angle <number>
Current angle (in degrees) for the draggable layer. (Read-only)
layerA = layerA.draggable.enabled = true # Print the current angle layerAon EventsDragMove-> print layerAdraggableangle
layer.draggable.updatePosition(point)
Function to override the final value before setting it. Allows you to add your own behaviour to a draggable. This allows you to create draggable layers that snap between certain distances.
Arguments
point
— An object with x and y properties.
layerA = layerA.draggable.enabled = true # Round numbers to a set amount = Mathroundnumber / nearest * nearest # Drag in increments of 20px = point.x = roundpointx20 point.y = roundpointy20 return point
layer.draggable.directionLock <boolean>
Snap to horizontal/vertical direction after a certain threshold.
layerA = layerA.draggable.enabled = true # Allow dragging only in one direction at a time layerA.draggable.directionLock = true
layer.draggable.directionLockThreshold <object>
The thresholds for lock directions. The x and y values represent the distance you can drag in a certain direction before it starts locking.
layerA = layerA.draggable.enabled = true # Snap horizontally after dragging 50px # Snap vertically instantly layerA.draggable.directionLock = true layerA.draggable.directionLockThreshold = x: 50 y: 0
layer.draggable.pixelAlign <boolean>
Snap to pixels while dragging to avoid subpixel-antialiasing.
layerA = layerA.draggable.enabled = true # Snap to pixel while dragging layerA.draggable.pixelAlign = true
layer.draggable.isDragging <boolean>
Whether the layer is currently being dragged (returns false when animating). (Read-only)
layerA = layerA.draggable.enabled = true # Check if the layer is being dragged layerAon EventsDragMove-> print layerAdraggableisDragging
layer.draggable.isAnimating <boolean>
Whether the layer is currently being animated by a momentum or bounce animation. (Read-only)
layerA = layerA.draggable.enabled = true # Check if the layer is animating layerAon EventsDragMove-> print layerAdraggableisAnimating
layer.draggable.isMoving <boolean>
Whether the layer is currently moving, either by dragging or by a momentum/bounce animation. (Read-only)
layerA = layerA.draggable.enabled = true # Check if the layer is moving layerAon EventsDragMove-> print layerAdraggableisMoving
layer.draggable.offset <object>
Get the x and y position of the draggable layer, relative to the Screen. (Read-only)
layerA = layerA.draggable.enabled = true # Get the x and y position of the layer layerAon EventsDragMove-> print layerAdraggableoffset
layer.draggable.layerStartPoint <object>
Get the x and y position of a draggable layer. (Read-only)
layerA = layerA.draggable.enabled = true # On DragStart, get the current x and y position layerAon EventsDragStart-> print layerAdraggablelayerStartPoint
layer.draggable.cursorStartPoint <object>
Get the x and y position of the cursor, relative to the Canvas. (Read-only)
layerA = layerA.draggable.enabled = true # On DragStart, get x and y position of the cursor layerAon EventsDragStart-> print layerAdraggablecursorStartPoint
layer.draggable.layerCursorOffset <object>
Get the x and y position of the cursor, relative to the draggable layer. If you click in the top left-corner, it returns { x: 0, y: 0 }. (Read-only)
layerA = layerA.draggable.enabled = true # Get the cursor position within the layer layerAon EventsDragStart-> print layerAdraggablelayerCursorOffset
layer.draggable.propagateEvents <boolean>
Set the propagateEvents property of a draggable layer. Set to true by default. This is useful when working with draggable layers within ScrollComponents or PageComponents, or nested Components.
Let's say you'd like to have a draggable layer within the scroll.content layer. By default, moving the layer will also move the scroll.content. This is because both layers will listen to the dragging events.
To prevent any draggable children from passing events to its parent, set propagateEvents to false. This applies to all nested draggable layers.
scroll = width: Screenwidth height: Screenheight scroll.content.backgroundColor = "#28affa" layerA = parent: scrollcontent backgroundColor: "#fff" layerA.draggable.enabled = true # Setting propagateEvents to false allows you to drag layerA # without also scrolling within the ScrollComponent layerA.draggable.propagateEvents = false
Events
Events are things that you can listen for. They can originate from the user, like a touch or click, or from an animation that ends. Most objects support event listening in Framer, but you will most often listen for events on layers.
When an event is called, the first argument is the event information. Depending on the event, this can contain mouse positions, mouse deltas etc. The second argument is always the layer that the event occurred to.
To listen for an event, you can use the on function:
layerA = layerA.name = "Layer A" layerAon EventsClick print "Clicked"layername # Output: "Clicked", "Layer A"
To stop listening for an event, you can use the off
function:
layerA = layerA.name = "Layer A" = print "Clicked"layername layerAonEventsClickclickHandlerlayerAoffEventsClickclickHandler
Tap Events
Tap events receive the gesture event properties.
Events.Tap
— Tap a layer.Events.SingleTap
— Same as Tap.Events.DoubleTap
— Quickly tap a layer twice.
layerA = layerAon EventsTap print "Tap"
layerA = layerAon EventsDoubleTap print "Double tap"
Tap Event Shortcuts
# For Events.Tap layerAonTap -> print "Tap" # For Events.SingleTap layerAonSingleTap -> print "Single tap" # For Events.DoubleTap layerAonDoubleTap -> print "Double tap"
ForceTap Events
ForceTap events receive the gesture event properties.
Events.ForceTap
— Tap with high pressure.Events.ForceTapChange
— Tap pressure sensitivity change.Events.ForceTapStart
— Start tap with high pressure.Events.ForceTapEnd
— End tap with high pressure.
layerA = layerAon EventsForceTap print "Force tap"
ForceTap Event Shortcuts
# For Events.ForceTap layerAonForceTap -> print "Force tap" # For Events.ForceTapChange layerAonForceTapChange -> print "Change of force tap pressure" # For Events.ForceTapStart layerAonForceTapStart -> print "Start force tap" # For Events.ForceTapEnd layerAonForceTapEnd -> print "End force tap"
LongPress Events
LongPress events receive the gesture event properties.
Events.LongPress
— A long press.Events.LongPressStart
— Start of long press.Events.LongPressEnd
— End of long press.
# Detect a long press layeron EventsLongPress print "Long press"
LongPress Event Shortcuts
# For Events.LongPress layerAonLongPress -> print "Long press" # For Events.LongPressStart layerAonLongPressStart -> print "Start long press" # For Events.LongPressEnd layerAonLongPressEnd -> print "End long press"
Swipe Events
Swipe events receive the gesture event properties.
Basic
Events.Swipe
— Swipe a layer.Events.SwipeStart
— Start swiping a layer.Events.SwipeEnd
— End swiping a layer.
layerA = layerAon EventsSwipe print eventdistance
Swipe Event Shortcuts
# For Events.Swipe layerAonSwipe -> print "Currently swiping" # For Events.SwipeStart layerAonSwipeStart -> print "Start swiping" # For Events.SwipeEnd layerAonSwipeEnd -> print "End swiping"
Up
Events.SwipeUp
— Upwards swiping.Events.SwipeUpStart
— Start swiping up.Events.SwipeUpEnd
— End swiping up.
layerA = layerAon EventsSwipeUp print eventdistance
SwipeUp Event Shortcuts
# For Events.SwipeUp layerAonSwipeUp -> print "Currently swiping up" # For Events.SwipeUpStart layerAonSwipeUpStart -> print "Start swiping up" # For Events.SwipeUpEnd layerAonSwipeUpEnd -> print "End swiping up"
Right
Events.SwipeRight
— Right swiping.Events.SwipeRightStart
— Start swiping right.Events.SwipeRightEnd
— End swiping right.
layerA = layerAon EventsSwipeRight print eventdistance
SwipeRight Event Shortcuts
# For Events.SwipeRight layerAonSwipeRight -> print "Currently swiping right" # For Events.SwipeRightStart layerAonSwipeRightStart -> print "Start swiping right" # For Events.SwipeRightEnd layerAonSwipeRightEnd -> print "End swiping right"
Down
Events.SwipeDown
— Downwards swiping.Events.SwipeDownStart
— Start swiping down.Events.SwipeDownend
— End swiping down.
layerA = layerAon EventsSwipeDown print eventdistance
SwipeDown Event Shortcuts
# For Events.SwipeDown layerAonSwipeDown -> print "Currently swiping down" # For Events.SwipeDownStart layerAonSwipeDownStart -> print "Start swiping down" # For Events.SwipeDownEnd layerAonSwipeDownEnd -> print "End swiping down"
Left
Events.SwipeLeft
— Left swiping.Events.SwipeLeftStart
— Start swiping left.Events.SwipeLeftEnd
— End swiping left.
layerA = layerAon EventsSwipeLeft print eventdistance
SwipeLeft Event Shortcuts
# For Events.SwipeLeft layerAonSwipeLeft -> print "Currently swiping left" # For Events.SwipeLeftStart layerAonSwipeLeftStart -> print "Start swiping left" # For Events.SwipeLeftEnd layerAonSwipeLeftEnd -> print "End swiping left"
Pan Events
Pan events receive the gesture event properties.
Events.Pan
— Pan in any directionEvents.PanStart
— Start panning.Events.PanMove
— While panning.Events.PanEnd
— End of panning.Events.PanLeft
— Left panning.Events.PanRight
— Right panning.Events.PanUp
— Upwards panning.Events.PanDown
— Downwards panning.
layerA = # Detect a panning gesture layerAon EventsPan print eventdistance
Pan Event Shortcuts
# For Events.Pan layerAonPan -> print "Currently panning" # For Events.PanStart layerAonPanStart -> print "Start panning" # For Events.PanMove layerAonPanMove -> print "Currently panning" # For Events.PanEnd layerAonPanEnd -> print "End panning" # For Events.PanLeft layerAonPanLeft -> print "Panning left" # For Events.PanRight layerAonPanRight -> print "Panning right" # For Events.PanUp layerAonPanUp -> print "Panning up" # For Events.PanDown layerAonPanDown -> print "Panning down"
Pinch Events
Pinch events receive the gesture event properties.
Events.Pinch
— Two pointers moving inwards or outwards.Events.PinchStart
— Start pinching.Events.PinchEnd
— End of pinching.
layerA = layerA.pinchable.enabled = true layerAon EventsPinch-> print layerAscalelayerArotation
Pinch Event Shortcuts
# For Events.Pinch layerAonPinch -> print "Currently pinching" # For Events.PinchStart layerAonPinchStart -> print "Start pinching" # For Events.PinchEnd layerAonPinchEnd -> print "End pinching"
Scale Events
Scale events receive the gesture event properties.
Events.Scale
— Scale a layer with two pointers.Events.ScaleStart
— Start scaling.Events.ScaleEnd
— End scaling.
layerA = layerA.pinchable.enabled = true layerAon EventsScale-> print layerAscale
Scale Event Shortcuts
# For Events.Scale layerAonScale -> print "Currently scaling" # For Events.ScaleStart layerAonScaleStart -> print "Start scaling" # For Events.ScaleEnd layerAonScaleEnd -> print "End scaling"
Rotate Events
Rotate events receive the gesture event properties.
Events.Rotate
— Rotate a layer with two pointers.Events.RotateStart
— Start rotating.Events.RotateEnd
— End of rotating.
layerA = layerA.pinchable.enabled = true layerAon EventsRotate-> print layerArotation
Rotate Event Shortcuts
# For Events.Rotate layerAonRotate -> print "Currently rotating" # For Events.RotateStart layerAonRotateStart -> print "Start rotating" # For Events.RotateEnd layerAonRotateEnd -> print "End rotating"
Touch Events
Events.TouchStart
— Start a touch/click.Events.TouchMove
— Touch move or mouse drag.Events.TouchEnd
— End touch or click.
layerA = # Returns the event and the layer layerAon EventsTouchStart print eventlayer
Touch Event Shortcuts
# For Events.TouchStart layerAonTouchStart -> print "Start touch" # For Events.TouchMove layerAonTouchMove -> print "Touch move" # For Events.TouchEnd layerAonTouchEnd -> print "End touch"
Click Events
Events.Click
— Click or touch (no delay on mobile).
layerA = # Returns the event and the layer layerAon EventsClick print eventlayer
Click Event Shortcuts
# For Events.Click layerAonClick -> print "Click"
Mouse Events
Events.MouseUp
— Releasing the mouse click.Events.MouseDown
— Pressing the mouse click.Events.MouseOver
— Hover with mouse cursor.Events.MouseOut
— Unhover with mouse cursor.Events.MouseMove
— While the mouse cursor moves.Events.MouseWheel
— Scrolling the mouse.
layerA = # Returns the event and the layer layerAon EventsMouseOver print eventlayer
Mouse Event Shortcuts
# For Events.mouseup layerAonMouseUp -> print "mouseup" # For Events.MouseDown layerAonMouseDown -> print "mousedown" # For Events.MouseOver layerAonMouseOver -> print "mouseover" # For Events.MouseOut layerAonMouseOut -> print "mouseout" # For Events.MouseMove layerAonMouseMove -> print "mousemove" # For Events.MouseWheel layerAonMouseWheel -> print "mousewheel"
Animation Events
Events.AnimationStart
— Animation start event, gets called when the animation starts.Events.AnimationStop
— Animation stop event, when an animation is finished or gets stopped half way.Events.AnimationEnd
— Animation end event, only gets called when the animation is completely finished.
layerA = layerAanimate x: 100 # Returns the animation and the layer layerAon EventsAnimationEnd print animationlayer
Animation Event Shortcuts
# For Events.AnimationStart layerAonAnimationStart -> print "Animation started" # For Events.AnimationStop layerAonAnimationStop -> print "Animation stopped" # For Events.AnimationEnd layerAonAnimationEnd -> print "Animation ended"
State Events
Events.StateSwitchStart
— Switch start event, gets called when the state starts switching.Events.StateSwitchStop
— Switch stop event, when a switch fully finishes or gets stopped half way.Events.StateSwitchEnd
— Switch end event, only gets called when the switch completely finishes.
(StateSwitch
deprecated the StateWillSwitch
and StateDidSwitch
events)
layerA = layerA.states.rotate = rotation: 90 layerAstateSwitch"rotate" # Returns the old and new state layerAon EventsStateSwitchEnd print fromto
State Event Shortcuts
# For Events.StateSwitchStart layerAonStateSwitchStart -> print "Will switch state" # For Events.StateSwitchStop layerAonStateSwitchStop -> print "Did switch state" # For Events.StateSwitchEnd layerAonStateSwitchEnd -> print "Did switch state"
Drag Events
Events.Move
— The layer is moving.Events.DragStart
— Start of drag.Events.Drag
— While dragging.Events.DragEnd
— End of drag.Events.DragAnimationStart
— Did start momentum/bounce animation.Events.DragAnimationEnd
— Did end momentum/bounce animation.Events.DirectionLockStart
— Did start lock direction.
layerA = layerA.draggable.enabled = true # Returns the offset (x, y) and the layer layerAon EventsMove print offsetlayer
layerA = layerA.draggable.enabled = true # Returns the event and the layer layerAon EventsDragStart print eventlayer
Drag Event Shortcuts
# For Events.Move layerAonMove -> print "Moving" # For Events.DragStart layerAonDragStart -> print "Start of drag" # For Events.Drag layerAonDrag -> print "Dragging" # For Events.DragEnd layerAonDragEnd -> print "End of drag" # For Events.DragAnimationStart layerAonDragAnimationStart -> print "Start of drag animation" # For Events.DragAnimationEnd layerAonDragAnimationEnd -> print "End of drag animation" # For Events.DirectionLockStart layerAonDirectionLockStart -> print "Start of direction lock"
Scroll Events
Events.Move
— The layer is moving.Events.ScrollStart
— Start scrolling.Events.Scroll
— While scrolling.Events.ScrollEnd
— End of scroll.Events.ScrollAnimationDidStart
— Did start momentum/bounce animation.Events.ScrollAnimationDidEnd
— Did end momentum/bounce animation.
scroll = layerA = parent: scrollcontent # Returns the event and the layer scrollon EventsScrollStart print eventlayer
Scroll Event Shortcuts
# For Events.Move scrollonMove -> print "Moving" # For Events.ScrollStart scrollonScrollStart -> print "Start of scroll" # For Events.Scroll scrollonScroll -> print "Scrolling" # For Events.ScrollEnd scrollonScrollEnd -> print "End of scroll" # For Events.ScrollAnimationDidStart scrollonScrollAnimationDidStart -> print "Start of scroll animation" # For Events.ScrollAnimationDidEnd scrollonScrollAnimationDidEnd -> print "End of scroll animation"
EdgeSwipe Events
EdgeSwipe events receive the gesture event properties.
Basic
Events.EdgeSwipe
— Swipe from any edge of the screen.Events.EdgeSwipeStart
— Start edge swipe.Events.EdgeSwipeEnd
— End edge swipe.
# Swipe from any edge of the screen Screenon EventsEdgeSwipe print eventdistance
EdgeSwipe Event Shortcuts
# For Events.EdgeSwipe ScreenonEdgeSwipe -> print "Swiping from edge" # For Events.EdgeSwipeStart ScreenonEdgeSwipeStart -> print "Start swiping from edge" # For Events.EdgeSwipeEnd ScreenonEdgeSwipeEnd -> print "End swiping from edge"
Top
Events.EdgeSwipeTop
— Edge swipe from top.Events.EdgeSwipeTopStart
— Start edge swipe from top.Events.EdgeSwipeTopEnd
— End edge swipe from top.
# Swipe from the top edge of the screen Screenon EventsEdgeSwipeTop print eventdistance
EdgeSwipeTop Event Shortcuts
# For Events.EdgeSwipeTop ScreenonEdgeSwipeTop -> print "Swiping from top edge" # For Events.EdgeSwipeTopStart ScreenonEdgeSwipeTopStart -> print "Start swiping from top edge" # For Events.EdgeSwipeTopEnd ScreenonEdgeSwipeTopEnd -> print "End swiping from top edge"
Right
Events.EdgeSwipeRight
— Edge swipe from right.Events.EdgeSwipeRightStart
— Start edge swipe from right.Events.EdgeSwipeRightEnd
— End edge swipe from right.
# Swipe from the right edge of the screen Screenon EventsEdgeSwipeRight print eventdistance
EdgeSwipeRight Event Shortcuts
# For Events.EdgeSwipeRight ScreenonEdgeSwipeRight -> print "Swiping from right edge" # For Events.EdgeSwipeRightStart ScreenonEdgeSwipeRightStart -> print "Start swiping from right edge" # For Events.EdgeSwipeRightEnd ScreenonEdgeSwipeRightEnd -> print "Start swiping from right edge"
Bottom
Events.EdgeSwipeBottom
— Edge swipe from bottom.Events.EdgeSwipeBottomStart
— Start edge swipe from bottom.Events.EdgeSwipeBottomEnd
— End edge swipe from bottom.
# Swipe from the bottom edge of the screen Screenon EventsEdgeSwipeBottom print eventdistance
EdgeSwipeBottom Event Shortcuts
# For Events.EdgeSwipeBottom ScreenonEdgeSwipeBottom -> print "Swiping from bottom edge" # For Events.EdgeSwipeBottomStart ScreenonEdgeSwipeBottomStart -> print "Start swiping from bottom edge" # For Events.EdgeSwipeBottomEnd ScreenonEdgeSwipeBottomEnd -> print "End swiping from bottom edge"
Left
Events.EdgeSwipeLeft
— Edge swipe from left.Events.EdgeSwipeLeftStart
— Start edge swipe from left.Events.EdgeSwipeLeftEnd
— End edge swipe from left.
# Swipe from the left edge of the screen Screenon EventsEdgeSwipeLeft print eventdistance
EdgeSwipeLeft Event Shortcuts
# For Events.EdgeSwipeLeft ScreenonEdgeSwipeLeft -> print "Swiping from left edge" # For Events.EdgeSwipeLeftStart ScreenonEdgeSwipeLeftStart -> print "Start swiping from left edge" # For Events.EdgeSwipeLeftEnd ScreenonEdgeSwipeLeftEnd -> print "End swiping from left edge"
Transition Events
Events.TransitionStart
— Transition start event, when the transition begins.Events.TransitionHalt
— Transition halt event, when a transition gets interrupted.Events.TransitionStop
— Transition stop event, when a transition completely finishes.Events.TransitionEnd
— Transition end event, when a transition completely finishes.
layerA = flow = flowshowOverlayRightlayerA flowon EventsTransitionStart-> print "Transition started"
Transition Event Shortcuts
# For Events.TransitionStart flowonTransitionStart -> print "Transition started" # For Events.TransitionHalt flowonTransitionHalt -> print "Transition halted" # For Events.TransitionStop flowonTransitionStop -> print "Transition stopped" # For Events.TransitionEnd flowonTransitionEnd -> print "Transition ended"
Value Events
The Value Change events can be used for the SliderComponent or the RangeSliderComponent. The min and max-value events can only be used with Range Sliders.
Events.SliderValueChange
— Slider value change.Events.SliderMinValueChange
— Minimum value change. (range sliders only)Events.SliderMaxValueChange
— Maximum value change. (range sliders only)
slider = x: Aligncenter y: Aligncenter slideron EventsSliderValueChange-> print slidervalue
Slider Event Shortcuts
# For Events.SliderValueChange slideronValueChange -> print slidervalue # For Events.SliderMinValueChange rangeonMinValueChange -> print rangeminValue # For Events.SliderMaxValueChange rangeonMaxValueChange -> print rangemaxValue
Change Events
The "change"
event allows you to listen to properties as they're changing. Below is a full overview of properties you can listen for:
"change:x"
— New x position."change:y"
— New y position."change:point"
— New x or y position."change:width"
— New width value."change:height"
— New height value."change:size"
— New width or height values."change:frame"
— New x, y, width or height values."change:scale"
— New scale value."change:rotation"
— New rotation value."change:borderRadius"
— New borderRadius value."change:currentPage"
— New currentPage layer."change:style"
— New style declaration."change:html"
— New html declaration."change:children"
— Added or removed children."change:parent"
— Added or removed parent.
For example, you can get the x
position of a layer while it's animating. Note that it'll return the exact, sub-pixel values.
layerA = layerAanimate x: 100 layerAon "change:x"-> print layerAx
The "change"
events can be used to link property changes to one another, with modulate. In the example below, we'll rotate the layer. The returned values are used to move the second layer horizontally.
layerA = layerB = x: 100 # We rotate layerA from 0 to 180 degrees. layerAanimate rotation: 180 # When the rotation value from layerA changes layerAon "change:rotation"-> # Use the values to move layerB from 100 to 300 x = UtilsmodulatelayerArotation0180100300true layerB.x = x
Gesture Event Properties
Every gesture receives an event object with the following set of properties. The touchCenter
, touchDistance
, touchOffset
, scale
and rotation
properties only return values when using multi-touch Events.
Positioning
event.point
— Current x and y positionevent.start
— Start x and y position.event.previous
— Previous x and y position.
layerA = layerA.pinchable.enabled = true layerAon EventsPinch print eventpoint
Offset
event.offset
— Current x and y offset.event.offsetTime
— Current duration since start.event.offsetAngle
— Current angle since start.event.offsetDirection
— Current direction since start.
layerA = layerAon EventsPan print eventoffset
Deltas
event.delta
— Offset since last event.event.deltaTime
— Time since last event.event.deltaAngle
— Angle change since last event.event.deltaDirection
— Direction change since last event.
layerA = layerAon EventsSwipe print eventdelta
Velocity & Force
event.velocity
— Current speed in x and y values.event.force
— Current pressure sensitivity of a tap.
layerA = layerAon EventsSwipe print eventvelocity
Input
event.fingers
— Amount of fingers on screen.event.touchCenter
— Center point between two fingers.event.touchDistance
— Distance between two fingers.event.touchOffset
— Offset between two fingers.
layerA = layerAon EventsRotate print eventfingers
Scale & Rotation
event.scale
— Scale value from two fingers.event.scaleDirection
— Current scaling direction (up or down).event.rotation
— Rotation value from two fingers.
layerA = layerA.pinchable.enabled = true layerAon EventsPinch print eventscaleDirection
Events.touchEvent(event)
Extract the touch event from a given event on mobile.
layerA = layerAon EventsClick myTouchEvent = EventstouchEventevent
Events.wrap(event)
Wrap a given DOM Element so we can keep track of the events and destroy them when needed. If you want to bind events to arbitrary dom element you should use this.
EventswrapwindowaddEventListener "resize" print "Page is resizing"
Extras
Extras are optional parts of Framer that have specific tasks like preloading, touch emulation and hints. In general, they are enabled automatically based on where your prototype is shown. But extras are often overridable explicitly by you, if you require specific behaviour.
Hints
Hints are used to highlight layers that a user can interact with, such as taps, swipes, etc. They are mainly to help users discover what a project can do when they see it for the first time.
By default, hints are enabled both in Framer for Mac and when you share your prototypes with others. If you click anywhere outside of an interactive layer or outside of the device, purple rectangles will indicate the tappable or scrollable areas.
You can enable or disable hints for your entire projects like this:
FramerExtrasHintsdisable
Or enable them like this:
FramerExtrasHintsenable
If you would like to show hints directly after a page loads, without any clicks you can do this:
FramerExtrasHintsenableFramerExtrasHintsshowHints
Some notes:
- Draggable or scrollable areas will highlight if you tap them, but did not scroll.
- Draggable or scrollable areas will only highlight if they can either scroll horizontal or vertically.
- Layers with rounded corners will get a hint with rounded corners.
- Rotated layers are currently unsupported.
- Invisible layers will not show hints, unless they are set to invisible or their opacity is 0. They will show a hint if they are covered by another layer but still respond to taps.
Customization
You can override layers (or components based on layers) to customize the hint indicator (by default a purple rectangle). This is great when you want to disable the highlight on a specific layer, or have a specific visiual hint.
This is how you disable a hint on a specific layer:
layerA = layerAonTap -> print "layerA" layerB = x: 220layerBonTap -> print "layerB" # Set an empty function on showHint = -> print "nope"
And you can customize the hint the same way:
layerA = layerAonTap -> print "layerA" layerB = x: 220layerBonTap -> print "layerB" = # Create a hint layer, this will automatically be # placed in the hints context on top of everything. hint = frame: hintFrame backgroundColor: "red" opacity: 0.5 # Add a cool animation hintanimate scale: 1.3 opacity: 0 options: time: 0.5 # Remove the layer when done hintonAnimationEnd -> hintdestroy
Preloader
When you open a project, our preloader makes sure your media is loaded before fully displaying. It analyzes the images and video you use and downloads them in the background, all while showing a circular progress indicator. When everything is fully loaded, it displays your project simultaneously.
A preloader vastly improves the user's experience because it avoids displaying your project in an incomplete state. When users interact with a prototype that is still loading, performance can suffer due to images being decompressed on the same thread that handles user interaction.
By default the preloader is only enabled outside of Framer, such as when you share a project online or via mirroring.
You can force enable the preloader like this:
FramerExtrasPreloaderenable
Or disable it like this:
FramerExtrasPreloaderdisable
Customization
You can customize the preloader image with any image, such as your logo. To do so, use the setLogo()
function:
FramerExtrasPreloaderenableFramerExtrasPreloadersetLogo"https://twitter.com/framerjs/profile_image?size=bigger"
Manually adding images
While the preloader often does a great job of discovering the main images used in your project, it may fail to locate specific images that were used at arbitrary points. The preloader also allows you to add these images manually using Framer.Extras.Preloader.addImage()
.
In the example below, the preloader cannot discover the image that layerB
uses because it only gets created after a tap, and theoretically could be any url. So in this scenarios, we add the image manually at the top of the prototype.
FramerExtrasPreloaderenableFramerExtrasPreloaderaddImage"https://twitter.com/framerjs/profile_image?size=bigger" layerA = point: Aligncenter layerAonTap -> layerB = image: "https://twitter.com/framerjs/profile_image?size=bigger"
Some notes:
- Device images are not counted against the preloader and are shown instantly because they are likely cached.
- There is a 30 second hard timeout on the preloader, after which your project gets shown even if not all images are loaded.
- Cached images load faster the second time you visit a project.
- Video preloading is based on the canplay event when enough buffer is available to play them.
- Loading errors are counted as loaded, so that the project appears even if some images are missing.
- The progress is based on image count and not loaded bytes, so if you have many small images and one big one, the last step may be significantly longer. Unfortunately, there is no great way to get progress based on size today.
FlowComponent
The FlowComponent helps you transition and navigate between multiple screens.
It’s built on two basic functions: showNext
to transition to a new layer, and showPrevious
to cycle back through previous layers. You can also use it to design overlays like modals, and fixed elements like a tab bar. The FlowComponent fires Transition
events. Learn more about them here.
Properties
layer
— A layer object, the targeted layer.options
— An object with all the animation options like curve, time and more. (Optional)
# Create layer layerA = size: Screensize # Create FlowComponent flow = # Show the layer flowshowNextlayerAanimate: true
flow.showNext(layer, options)
Transition to a new layer. By default, it will animate to the layer, except if it’s the first layer added to the FlowComponent. If the width or height of the layer exceeds that of its parent, it will become scrollable. It also automatically detects whether to become vertically or horizontally scrollable.
Arguments
layer
— A layer object.options.animate
— A boolean, sets whether the layer animates. (Optional)options.scroll
— A boolean, sets whether the layer becomes scrollable. (Optional)
# Create layer layerA = size: Screensize # Create FlowComponent flow = # Show the layer flowshowNextlayerA
Set animate to false
to switch between layers without a transition.
# Create layers layerA = size: Screensize backgroundColor: "#00AAFF" layerB = size: Screensize backgroundColor: "#FFCC33" # Create FlowComponent and show layer flow = flowshowNextlayerA # Instantly show layerB on click layerAonClick -> flowshowNextlayerBanimate: false
flow.showPrevious(options)
Transition to the previous layer. By default, it will animate to the layer.
Arguments
options.animate
— A boolean, sets whether the layer animates. (Optional)options.scroll
— A boolean, sets whether the layer becomes scrollable. (Optional)
# Create layer layerA = layerB = # Create FlowComponent flow = flowshowNextlayerA # Switch to layerA on click layerAonClick -> flowshowNextlayerB # Return to the previous on click layerBonClick -> flowshowPrevious
flow.showOverlayCenter(layer, options)
Overlay a layer from the center, like a modal dialog.
Arguments
layer
— A layer object.options.animate
— A boolean, sets whether the layer animates. (Optional)options.scroll
— A boolean, sets whether the layer becomes scrollable. (Optional)options.modal
— A boolean, sets whether the overlay becomes clickable. (Optional)
# Create layer layerA = size: Screensize # Create FlowComponent flow = # Overlay the modal layer flowshowOverlayCenterlayerA
The modal
argument is set to false
by default. If you would like the overlay to be clickable and return to the previous screen, you can enable this boolean.
# Create layer layerA = backgroundColor: "#00AAFF" size: Screensize layerB = borderRadius: 40 backgroundColor: "#FFF" size: 500 # Create FlowComponent flow = flowshowNextlayerA # Show modal, overlay is not clickable layerAonClick -> flowshowOverlayCenterlayerBmodal: true
flow.showOverlayTop(layer, options)
Overlay a layer from the top, like a notification screen.
Arguments
layer
— A layer object.options.animate
— A boolean, sets whether the layer animates. (Optional)options.scroll
— A boolean, sets whether the layer becomes scrollable. (Optional)options.modal
— A boolean, sets whether the overlay becomes clickable. (Optional)
# Create layer layerA = size: Screensize # Create FlowComponent flow = # Overlay the layer flowshowOverlayToplayerA
flow.showOverlayRight(layer, options)
Overlay a layer from the right.
Arguments
layer
— A layer object.options.animate
— A boolean, sets whether the layer animates. (Optional)options.scroll
— A boolean, sets whether the layer becomes scrollable. (Optional)options.modal
— A boolean, sets whether the overlay becomes clickable. (Optional)
# Create layer layerA = size: Screensize # Create FlowComponent flow = # Overlay the layer flowshowOverlayRightlayerA
flow.showOverlayBottom(layer, options)
Overlay a layer from the bottom.
Arguments
layer
— A layer object.options.animate
— A boolean, whether the layer animates. (Optional)options.scroll
— A boolean, whether the layer becomes scrollable. (Optional)options.modal
— A boolean, sets whether the overlay becomes clickable. (Optional)
# Create layer layerA = size: Screensize # Create FlowComponent flow = # Overlay the layer flowshowOverlayBottomlayerA
flow.showOverlayLeft(layer, options)
Overlay a layer from the left.
Arguments
layer
— A layer object.options.animate
— A boolean, sets whether the layer animates. (Optional)options.scroll
— A boolean, sets whether the layer becomes scrollable. (Optional)options.modal
— A boolean, sets whether the overlay becomes clickable. (Optional)
# Create layer layerA = size: Screensize # Create FlowComponent flow = # Overlay the layer flowshowOverlayLeftlayerA
flow.transition(layer, transition, options)
Create a custom transition. The transitions use states internally to cycle back and forward. There are three layers (current, next and background) with two states each (back and forward). If you don’t define a specific state, the FlowComponent assumes you don’t want to animate that layer.
Arguments
layer
— A layer object.transition
— A function with the animation states.options.animate
— A boolean, sets whether the layer animates. (Optional)options.scroll
— A boolean, sets whether the layer becomes scrollable. (Optional)
# Custom transition = transition = layerA: show: scale: 1.0 opacity: 1 hide: scale: 0.5 opacity: 0 layerB: show: scale: 1.0 opacity: 1 hide: scale: 0.5 opacity: 0 # Create layers layerA = backgroundColor: "#00AAFF" size: Screensize layerB = backgroundColor: "#FFCC33" size: Screensize # Create FlowComponent flow = flowshowNextlayerA # Switch to layerB with custom transition layerAonClick -> flowtransitionlayerBscaleTransition
The custom transition is a function that returns an object with states. Inside the function you have access to the arguments current FlowComponent, layerA, layerB and the overlay. If you don’t pass states for layerA, layerB or the overlay, it will leave the layer as is on a transition.
flow.header <layer>
Add a sticky header to a scrollable screen, like a a fixed navigation bar.
# Create navigation layer navBar = # Create FlowComponent flow = # Anchor layer to the top flow.header = navBar
flow.footer <layer>
Add a sticky footer to a scrollable screen, like a a fixed tab bar.
# Create tab bar layer tabBar = # Create FlowComponent flow = # Anchor layer to the bottom flow.footer = tabBar
Layer
Layers are the basic containers of Framer, which can contain images, videos, or text. You can position layers with numeric values and dynamic values. Layers contain many properties that define their appearance, such as opacity, rotation and scale. Layers can also be nested to adjust their hierarchy.
To create a layer, use the new
keyword. Every layer has a set of default properties: a blue background, and a default width and height of 100.
layerA =
You can set layer properties when creating them:
layerA = x: 100 y: 100 width: 250 height: 250 opacity: 0.5 backgroundColor: "white"
And you can also override them later:
layerA = x: 100 y: 100 layerA.x = 200
layer.id <number>
A unique identification number for this layer. No other layer will have this number. The layer id is read only and cannot be changed.
layerA = print layerAid# Output: 1
layer.name <string>
The name of a layer. Layers aren't named by default. Imported layers will inherit the name you've defined within Sketch or Photoshop.
layerA = layerA.name = "Button" print layerAname# Output: "Button"
layer.x <number>
The x property of a layer defines its x position relative to the top left corner.
layerA = layerA.x = 500
layer.y <number>
The y property of a layer defines its y position relative to the top left corner.
layerA = layerA.y = 500
layer.z <number>
The z property of a layer defines its position in space, also known as depth. The larger this value, the further away the object is from the point of view.
Remember that you will have to enable perspective on a parent layer before you can see this effect. Also note the z property is different from layer.index (z-index) which defines the order for layers when they all have the same z value.
layerA = layerA.z = 500
layer.width <number>
The width of the layer in pixels.
layerA = layerA.width = 500
layer.height <number>
The height of the layer in pixels.
layerA = layerA.height = 500
layer.minX <number>
The left edge location of the layer. Same as layer.x.
layerA = x: 100 y: 100 width: 100 height: 100 print layerAminX# Output: 100
layer.midX <number>
The horizontal center for the layer.
layerA = x: 100 y: 100 width: 100 height: 100 print layerAmidX# Output: 150 layerA.midX = 500print layerAx# Output: 450
layer.maxX <number>
The right edge location of the layer.
layerA = x: 100 y: 100 width: 100 height: 100 print layerAmaxX# Output: 200 layerA.maxX = 500print layerAx# Output: 400
layer.minY <number>
The top edge location of the layer. Same as layer.y.
layerA = x: 100 y: 100 width: 100 height: 100 print layerAminY# Output: 100
layer.midY <number>
The vertical center for the layer.
layerA = x: 100 y: 100 width: 100 height: 100 print layerAmidY# Output: 150 layerA.midY = 500print layerAy# Output: 450
layer.maxY <number>
The bottom edge location of the layer.
layerA = x: 100 y: 100 width: 100 height: 100 print layerAmaxY# Output: 200 layerA.maxY = 500print layerAy# Output: 400
layer.point <object>
Allows you to set or capture the x, and y values of a layer.
layerA = print layerApoint# Output: { x: 100, y: 100 } layerA.point = x: 10 y: 200 print layerApoint# Output: { x: 10, y: 200 } print layerAx# Output: 10
layer.size <object>
Allows you to set or capture the width and height values of a layer.
layerA = print layerAsize# Output: { width: 100, height: 100 } layerA.size = width: 10 height: 10 print layerAsize# Output: { width: 10, height: 10 } print layerAwidth# Output: 10
layer.frame <object>
Allows you to set or capture the x, y, width and height values of a layer.
layerA = print layerAframe# Output: { x: 100, y: 100, width: 100, height: 100 } layerA.frame = x: 10 y: 200 width: 10 height: 10 print layerAframe# Output: { x: 10, y: 200, width: 10, height: 10 } print layerAx# Output: 10
layer.props <object>
Gets or sets all properties for this layer.
layerA = # Get current layer properties print layerAprops# Output: { x: 100, y: 100, ...} # Set properties layerA.props = rotation: 90 opacity: 0.5
layer.center()
Center this layer in its parent. If there is no parent, it will be centered relative to the screen.
layerA = width: 500 height: 500 layerB = parent: layerA width: 100 height: 100 layerBcenter print layerBxlayerBy# Output: 200, 200
layer.centerX(offset)
Center this layer horizontally in its parent. If there is no parent it will be centered relative to the screen. The offset is a pixel offset from the center and optional.
Arguments
offset
— A number that offsets the position.
layerA = width: 500 height: 500 layerB = parent: layerA width: 100 height: 100 layerBcenterXprint layerBxlayerBy# Output: 200, 0 layerBcenterX20print layerBxlayerBy# Output: 220, 0
layer.centerY(offset)
Center this layer vertically in its parent. If there is no parent it will be centered relative to the screen. The offset is a pixel offset from the center and optional.
Arguments
offset
— A number that offsets the position.
layerA = width: 500 height: 500 layerB = parent: layerA width: 100 height: 100 layerBcenterYprint layerBxlayerBy# Output: 0, 200 layerBcenterY20print layerBxlayerBy# Output: 0, 220
layer.pixelAlign()
Round the x and y values of this layer to whole numbers. Allows you to snap layers on the pixel. This is useful when dynamically centering layers.
layerA = x: 100.18293 y: 10.12873 layerApixelAlign print layerAxlayerAy# Output: 100, 10
layer.screenFrame <object>
Allows you to set or capture the absolute position of this layer on the screen, ignoring the inherited position from its parents.
layerA = x: 100 layerB = parent: layerA x: 100 print layerBscreenFrame# Output: { x: 200, y: 0, width: 100, height: 100 } layerB.screenFrame = x: 400 y: 0 width: 100 height: 100 print layerBx# Output: 300
layer.contentFrame()
The calculated frame for the total size of all the children combined.
layerA = layerB = parent: layerA x: 0 width: 100 layerC = parent: layerA x: 100 width: 300 print layerAcontentFrame# Output: { x: 0, y: 0, width: 400, height: 100 }
layer.centerFrame()
The calculated frame, centered within its parent. If there is no parent, it will be centered relative to the screen.
layerA = width: 500 height: 500 layerB = parent: layerA width: 100 height: 100 print layerBcenterFrame# Output: { x: 200, y: 200, width: 100, height: 100 }
layer.backgroundColor <string>
Sets the background color for this layer. The color is expressed as a string in the CSS color format. Layers have a light blue background color by default.
layerA = layerA.backgroundColor = "red"layerA.backgroundColor = "#00ff00"layerA.backgroundColor = "rgba(134, 12, 64, 0.3)"layerA.backgroundColor = "transparent" # Remove the background color layerA.backgroundColor = ""
layer.color <string>
Sets the text color for this layer. The color is expressed as a string in the CSS color format. Layers have a white text color by default.
layerA = layerA.color = "red"layerA.color = "#00ff00"layerA.color = "rgba(134, 12, 64, 0.3)"layerA.color = "transparent" # Remove the color layerA.color = ""
layer.image <string>
Sets the background-image url or path for this layer. You can set it as a local path or a full url. The image will always fit to cover the layer, and will never be stretched. You can remove an image by setting it to null or an empty string.
# Local images layerA = image: "images/logo.png" # Hosted images layerA.image = "http://framerjs.com/logo.png"
Setting an image will remove the default background color of a layer. Set the background color to another color than the default to show it behind the image.
# Show a color where the image is transparent layerA = image: "images/logo.png" backgroundColor: "blue"
You can be notified of when an image is loaded and ready to display with the Events.ImageLoaded event. If there is an error loading an image (like not found) it will throw an Events.ImageLoadError event.
layerA = # Listen to the loading event layerAon EventsImageLoaded-> print "The image loaded" layerAon EventsImageLoadError-> print "The image couldn't be loaded" layerA.image = "images/logo.png"
layer.visible <boolean>
Sets whether the layer should be visible or not.
layerA = layerA.visible = false
layer.opacity <number>
Sets the opacity for this layer. Opacity is defined with a number between 0 and 1 where 0 is invisible and 1 fully opaque.
layerA = layerA.opacity = 0.5
layer.clip <boolean>
Sets whether the layer should clip its children. Clipping is disabled by default.
layerA = width: 100 height: 100 layerB = width: 200 height: 200 parent: layerA layerA.clip = true
layer.ignoreEvents <boolean>
Enable or disable any user events added to layers. When disabled, no user events on the layer will be emitted. The default value for this is true
. Framer automatically disables it when you add an event listener.
layerA = layerAon EventsClick-> print "Click!" # Now it won't respond to a click layerA.ignoreEvents = true # Now it will layerA.ignoreEvents = false
layer.originX <number>
Sets the x origin for scale, rotate and skew transformations. The origin is defined as a number, where 0 is the left edge of the layer and 1 the right edge. The default value is 0.5, the center of the layer.
layerA = layerA.rotation = 45layerA.originX = 0layerA.originX = 1
layer.originY <number>
Sets the y origin for scale, rotate and skew transformations. The origin is defined as a number, where 0 is the top edge of the layer and 1 the bottom edge. The default value is 0.5, the center of the layer.
layerA = layerA.rotation = 45layerA.originY = 0layerA.originY = 1
layer.originZ <number>
Sets the z origin for 3D transformations. The origin is defined in pixels. Positive values bring 3D layers closer to you, and negative values further way.
layerA = originZ: -45 rotationY: 90
layer.perspective <number>
Sets the perspective for child layers. Perspective gives depth to 3d properties like rotationX, rotationY. The rotation is set from 1 to Infinity where 1 is a huge perspective. Setting perspective to 0 gives you an isometric effect. Perspective is disabled by default.
layerA = # Set the perspective for all sub layers layerA.perspective = 100 layerB = parent: layerA rotationX: 30 rotationY: 30
layer.flat <boolean>
Enable or disable 3D properties for all children of the layer.
# Enable flat on its children layerA = width: 200 height: 200 x: 100 y: 100 clip: false flat: true # Rotate horizontally layerA.rotationX = 45 # With flat enabled, adjusting z has no effect layerB = parent: layerA z: 25
layer.backfaceVisible <boolean>
Defines whether a layer should be visible when not facing the screen. This is useful when an element is rotated, and you don't want to see its backside.
layerA = layerA.backfaceVisible = false
layer.rotation <number>
Sets the rotation, relative to its transform origin. The rotation is defined in degrees between 0 and 360. The default value is 0.
layerA = layerA.rotation = 45
layer.rotationX <number>
Sets the x rotation, relative to its transform origin. The rotation is defined in degrees between 0 and 360. The default value is 0.
layerA = layerA.rotationX = 45
layer.rotationY <number>
Sets the y rotation, relative to its transform origin. The rotation is defined in degrees between 0 and 360. The default value is 0.
layerA = layerA.rotationY = 45
layer.rotationZ <number>
Sets the z rotation, relative to its transform origin. The rotation is defined in degrees between 0 and 360. Same as layer.rotation.
layerA = layerA.rotationZ = 45
layer.scale <number>
Sets the scale, relative to its transform origin. The default scale is 1. Any number smaller then one will decrease the size and vice versa.
layerA = layerA.scale = 2
layer.scaleX <number>
Sets the horizontal scale, relative to its transform origin. The default scale is 1. Any number smaller then one will decrease the size and vice versa.
layerA = layerA.scaleX = 2
layer.scaleY <number>
Sets the vertical scale, relative to its transform origin. The default scale is 1. Any number smaller then one will decrease the size and vice versa.
layerA = layerA.scaleY = 2
layer.parent <Layer object>
Sets the parent for this layer. You can set the parent to null if you want the layer to live at the root of your document. (Alias: superLayer)
layerA = layerB = layerB.parent = layerA print layerBparent# Output: <Object:Layer layerA>
layer.children <Array>
All the child layers of this layer. (Alias: subLayers)
layerA = layerB = parent: layerA layerC = parent: layerA print layerAchildren# Output: [<Object:Layer layerB>, <Object:Layer layerC>]
layer.childrenWithName(name)
All child layers of this layer, filtered by name. (Alias: subLayersByName)
Arguments
name
— A string of the layer name.
layerA = layerB = name: "navigation" parent: layerA layerC = name: "button" parent: layerA print layerAchildrenWithName"button"# Output: [<Object:Layer layerC>]
layer.siblings <Array>
All sibling layers of this layer. (Alias: siblingLayers)
layerA = layerB = parent: layerA layerC = parent: layerA print layerBsiblings# Output: [<Layer layerC id:3 (0,0) 200x200>]
layer.siblingsWithName(name)
All sibling layers of this layer, filtered by name.
Arguments
name
— A string of the layer name.
layerA = layerB = name: "navigation" parent: layerA layerC = name: "button" parent: layerA print layerBsiblingsWithName"button"# Output: [<Object:Layer name:button layerC>]
layer.descendants <Array>
All descendant layers of this layer. These include layers that are nested multiple levels deep, so also the child layers of its own child layers.
layerA = layerB = parent: layerA layerC = parent: layerB print layerAdescendants# Output: [<Layer id:2 name:layerB (0,0) 200x200>, <Layer id:3 name:layerC (0,0) 200x200>]
layer.ancestors(context)
All ancestor layers of this layer. These include layers that are nested multiple levels deep, so also the parent layers of its own parent layer.
Arguments
context
— A boolean that specifies if the context should be included, set to false by default. (Optional)
layerA = layerB = parent: layerA layerC = parent: layerB print layerCancestors# Output: [<Layer id:2 name:layerB (0,0) 200x200>, <Layer id:1 name:layerA (0,0) 200x200>]
layer.addChild(layer)
Add a layer as a child to this layer. This will set the parent of the added layer. (Alias: addSubLayer)
Arguments
layer
— A layer object.
layerA = layerB = layerAaddChildlayerB print layerBparent# Output: <Object:Layer layerA>
layer.removeChild(layer)
Remove a layer from the children of this layer. (Alias: removeSubLayer)
Arguments
layer
— A layer object.
layerA = layerB = parent: layerA layerAremoveChildlayerB print layerBparent# Output: null
layer.index <number>
The order index for this layer. Sibling layers with a higher index (and the same z value) will drawn on top of this layer, and those with a lower index below.
The layer index increases by order of insertion. So if you add a layer as a child and the highest sibling index value is 5, the index of the inserted layer will be 6 (5 + 1). Or, the last inserted layer will always be on top.
layerA = layerB = # Draw layerB on top layerA.index = 2layerB.index = 1
layer.placeBefore(layer)
Places this layer before another layer. This changes the layer.index property for at least one of the layers. This method only works on layers that have the same parent, or no parent at all.
Arguments
layer
— A layer object.
layerA = layerB = # Draw layerB on top layerBplaceBeforelayerA
layer.placeBehind(layer)
Places this layer behind another layer. This changes the layer.index property for at least one of the layers. This method only works on layers that have the same parent, or no parent at all.
Arguments
layer
— A layer object.
layerA = layerB = # Draw layerB on top layerAplaceBehindlayerB
layer.bringToFront()
Places this layer in front of all other layers with the same parent.
layerA = layerB = layerC = # Draw layerA on top layerAbringToFront
layer.sendToBack()
Places this layer behind all other layers with the same parent.
layerA = layerB = layerC = # Draw layerC last layerCsendToBack
layer.html <string>
Insert HTML content into this layer. The html can be anything, from text, to input and form elements to canvas or SVG content.
If you need to target any of the created elements, remember that they are only available after Framer rendered them. To reliably get a reference to a DOM element, use layer.querySelector
or layer.querySelectorAll
.
If the content that gets inserted needs user interaction, it's best to set layer.ignoreEvents to false. To retain the layer structure, the content is placed within an element that gets created when you set HTML for the first time.
layerA = # Add simple text content layerA.html = "Hello" # Add inline styled text content layerA.html = "I'm <span style='color:red'>Koen</span>" # Add an input field layerA.html = "<input type='text' value='Hello'>" # Add a div with a canvas element and get a reference layerA.html = "<div><canvas id='canvas'></canvas></div>"canvasElement = layerAquerySelectorAll"#canvas"
layer.style <object>
Set or get CC style properties for the layer.
Next to the standard CSS property names you can also camelCase naming. For example, layer.style["border-color"]
is the same as layer.style.borderColor
. For a full list see this overview.
layerA = # Modify a single style property layerAstyle"outline"= "1px solid red" # Modify set of style properties layerA.style = "outline": "1px solid red" "padding": "10px" # Get a specific style property print layerAstyle"outline"# Output: "1px solid red"
layer.computedStyle()
Get all the current applied CSS style properties for the layer. Note that this is an expensive operation for the browser. For a full reference on computed style, see this overview.
layerA = layerA.backgroundColor = "red" print layercomputedStyle"background-color"# Output: "red"
layer.classList <ClassList object>
A list of class attributed for the layer. Also contains methods to add, remove, toggle and check for classes. For a full reference, see this overview.
layerA = # Add the class .red layerAclassListadd"red" # Remove the class .red layerAclassListremove"red" # Toggle the class .red layerAclassListtoggle"red" # See if the layer has class .red print layerAclassListcontains"red"# Output: true
layer.destroy()
This will remove a layer from the hierarchy and remove all its listeners. If the layer has children they will be destroyed too.
layerA = layerAdestroy
layer.copy()
This will copy a layer and all its children. The layers will have all the same properties as their copied counterparts (same position and looks). The event listeners will not be copied.
layerA = layerB = parent: layerA layerC = layerAcopy
layer.copySingle()
This will copy a layer without its children. Event listeners aren't copied.
layerA = layerB = parent: layerA layerC = layerAcopySingle
layer.blur <number>
Adds a gaussian blur to the layer. Gaussian blur is defined in pixels. The default value is 0.
layerA = layerA.blur = 10
layer.brightness <number>
Brightens or darkens a layer. Brightness is defined with a number. Setting brightness to 0 produces a completely black layer, while the value that produces a completely white layer depends on the color of your layer or image.
layerA = layerA.brightness = 10
layer.saturate <number>
Saturates a layer. Saturation is defined with a number between 0 and 100 where 0 removes all saturation and 100 is default.
layerA = layerA.saturate = 50
layer.hueRotate <number>
Sets the hue of a layer. The hue rotation is defined in degrees between 0 and 360. The default value is 0.
layerA = layerA.hueRotate = 180
layer.contrast <number>
Sets the contrast of a layer. Contrast is defined with a number between 0 and 100 where 0 is removes all contrast. The default value is 100.
layerA = layerA.contrast = 50
layer.invert <number>
Inverts the color of a layer. Invert is defined with a number between 0 and 100. The invert property inverts all colors and brightness values of a layer. Setting invert to 100 on a colored layer replaces all hues with their complementary colors. The default value is 0.
layerA = layerA.invert = 100
layer.grayscale <number>
Grayscale converts all colors to gray. Grayscale is defined with a number between 0 and 100 where 100 turns all colors to a shade of gray. The default value is 0.
layerA = layerA.grayscale = 100
layer.sepia <number>
Adds a sepia tone to your layer. Sepia is defined with a number between 0 to 100. The default value is 0.
layerA = layerA.sepia = 100
layer.shadowX <number>
Defines the shadow direction on the x-axis. A positive value will produce a shadow from the right edge of a layer, whereas a negative value will produce a shadow from the left edge. A visible shadow will only appear if the shadowColor property is also defined.
layerA = layerA.shadowX = 10
layer.shadowY <number>
Defines the shadow direction on the y-axis. A positive value will produce a shadow from the bottom edge of a layer, whereas a negative value will produce a shadow from the top edge. A visible shadow will only appear if the shadowColor property is also defined.
layerA = layerA.shadowY = 10
layer.shadowBlur <number>
Adds a Gaussian blur to the shadowX or shadowY property. shadowBlur is defined with a number. The default value is 0.
layerA = layerA.shadowY = 1layerA.shadowBlur = 4
layer.shadowSpread <number>
Makes shadows larger in all directions. The shadow is expanded by the given value. Negative values cause the shadow to contract. If shadowX, shadowY and shadowBlur are all set to 0, this will appear as a border. A visible shadow will only appear if the shadowColor property is also defined.
layerA = layerA.shadowY = 1layerA.shadowBlur = 4layerA.shadowSpread = 2
layer.shadowColor <string>
Sets the color of a layers shadow. The color is expressed as a string in the CSS color format.
layerA = layerA.shadowY = 1layerA.shadowBlur = 4layerA.shadowColor = "rgba(0,0,0,0.2)"
layer.borderRadius <number>
Rounds the corners of a layer in pixels. To create circles, set the property to a high value (50-100) or divide the layers width/height by two.
layerA = layerA.borderRadius = 3 # To create a circle: layerA.borderRadius = layerAwidth/2
layer.borderColor <string>
Set the border color of this layer. The color is expressed as a string in the css color format.
layerA = layerA.borderColor = "red"layerA.borderWidth = 2
layer.borderWidth <number>
Set the width of the layer border in pixels.
layerA = layerA.borderWidth = 2layerA.borderColor = "red"
layer.animate(properties or state, options)
Animate a layer by creating a new animation object with a set of layer properties or a state name. The optional animation options allow you to define how the layer animates using curves, timing and more. You can run multiple animations at a time as long as they don’t alter the same layer properties.
Arguments
properties
orstate
— The layer properties or name of the state.options
— An object with all the animation options like curve, time and more. (Optional)
Example: Animate with properties
layerA = # Animate the x position layerAanimate x: 200
Example: Animate with properties and options
layerA = # Animate the x position with options layerAanimate x: 200 options: curve: Springdamping: 0.5 time: 0.5
Example: Animate with states
layerA = # Create a new state layerA.states.stateA = x: 200 # State animation layerAanimate "stateA"
Example: Animate with states and options
layerA = # Create a new state layerA.states.stateA = x: 200 # State animation with options layerAanimate "stateA" curve: Springdamping: 0.5 time: 0.5
layer.animationOptions <object>
The animation options manage how and when the layer will be animated. Edit things like the curve and timing to change the appearance of an animation.
Once set, the animation options are set for every animation performed on the layer, unless they’re overruled. You can also set the animation options for individual layer states.
Properties
curve
— A string, set to ease by default. (Optional)curveOptions
— An object with the options of the set curve. (Optional)time
— A number, the duration in seconds. (Optional)delay
— A number, the delay of the animation. (Optional)repeat
— A number, the amount of times it repeats. (Optional)colorModel
— A string, the model to animate colors in. (Optional)instant
— A boolean, instantly jump to the end of an animation. (Optional)
layerA = layerA.animationOptions = curve: Bezierease time: 0.25
layer.animations()
Returns all the current running animations for this layer.
layerA = layerAanimate x: 100 layerAanimate y: 100 print layerAanimations# Output: [<Object Animation>, <Object Animation>]
layer.isAnimating <boolean>
A read-only property that checks if a layer is animating.
layerA = layerAanimate x: 100 print layerAisAnimating# Result: True
layer.animateStop()
Immediately stop all animations running on this layer.
layerA = # Stop an animation immediately layerAanimate x: 100 layerAanimateStop
layer.stateSwitch(name)
Instantly switch to a state without animating. (layer.stateSwitch()
deprecated layer.states.switchInstant()
)
Arguments
name
— A string, the name of the state.
layerA = layerA.states.stateA = x: 100 layerAstateSwitch"stateA"
layer.stateCycle(states, options)
Cycle through all the layer states. Once we reach the end of the cycle we start at the beginning again. You can provide an array of state names for the ordering, if you don’t it will order based on when a state was added.
You can also add an animation options parameter to change the animation for a cycle.
(layer.stateCycle()
deprecated layer.states.next()
)
Arguments
states
— An array of state names. (Optional)options
— An object with all the animation options like curve, time and more. (Optional)
layerA = layerA.states = stateA: x: 100 stateB: x: 200 # Every time we call this we cycle to the next state layerAstateCycle"stateA""stateB"
layer.stateNames <Array>
A read-only property that returns an array with names of all states assigned to a layer.
layerA = layerA.states = stateA: x: 100 stateB: y: 100 print layerAstateNames# Result: ["stateA", "stateB"]
layer.convertPointToCanvas(point)
Converts a point from a layer to the Canvas.
point = x: 20 y: 40 layer = pointInCanvas = layerconvertPointToCanvaspoint
layer.convertPointToScreen(point)
Converts a point from a layer to the Screen.
point = x: 20 y: 40 layer = pointInScreen = layerconvertPointToCanvaspoint
layer.convertPointToLayer(point, layer)
Converts a point from a layer to another layer.
point = x: 20 y: 40 layerA = layerB = pointInLayerB = layerAconvertPointToLayerpointlayerB
layer.on(eventName, handler)
Start listening to an event on this layer.
When an event is called the first argument is the event information. Depending on the specific event this can contain mouse positions, mouse deltas etc. The second argument is always the layer that the event occurred to.
layerA = layerA.name = "layerA" layerAon EventsClick print "Clicked"layername # Output: "Clicked", "layerA"
layer.off(eventName, handler)
Stop listening to an event on this layer.
layerA = layerA.name = "layerA" = print "This layer was clicked"layername layerAonEventsClickclickHandlerlayerAoffEventsClickclickHandler
MIDIComponent
A MIDI controller sends signals to your computer, similar to a keyboard or a mouse. Most commonly MIDI controllers have buttons, sliders and knobs that you can hook up to software. There is a wide variety of hardware MIDI controllers available on the market, many of them connect over USB. There are also MIDI controller apps, that connect over Bluetooth.
The MIDIComponent gives you the ability to work with MIDI controllers directly in Framer and in browsers that support the Web MIDI API.
Get Started
- Connect a MIDI device
- Open Framer and paste the following code
midi = midionValueChange print valueinfo
Now, when you change a button on the MIDI device you will see the values being printed, for example if you move a control from the start to end position:
» 0, {source:"111955983", channel:1, control:2}» 1, {source:"111955983", channel:1, control:2}» 2, {source:"111955983", channel:1, control:2}…» 125, {source:"111955983", channel:1, control:2}» 126, {source:"111955983", channel:1, control:2}» 127, {source:"111955983", channel:1, control:2}
By default, MIDIComponent
will listen to MIDI signals from all controls and note buttons on all devices coming over any channel. You can use the properties you see printed above to filter the signal events. That way you can hook up control number 2 to a slider, for example:
midi = control: 2 slider = point: Aligncenter max: 127 midionValueChange slider.value = value
The output values from MIDI are always between 0
and 127
, but if you want to use the value to set a property that has a different range, you can use min
and max
to modulate the value for you. For example, the RGB components in a color range from 0
to 255
, so you can use:
midi = min: 0 max: 255 midionValueChange Screen.backgroundColor = r: valueg: 0b: 0
MIDIComponent.min <number>
The value that will be send as the minimum value to the onValueChange
handler. The default value is 0
.
MIDIComponent.max <number>
The value that will be send as the maximum value to the onValueChange
handler. The default value is 127
.
MIDIComponent.control <number>
The number of the control, between 0
and 127
. Filters out events not coming from this control.
To find the correct control number, you can use the extra information send to the handler of onValueChange
.
MIDIComponent.channel <number>
A number between 1
and 16
representing the channel. Filters out all events not coming from this channel.
To find the current channel of a control, you can use the extra information send to the handler of onValueChange
.
MIDIComponent.source <string>
The source to listen to. Filters out all events not coming from this source.
Each MIDI device has a unique source ID that is managed by the system. In general, the source ID should be stable, so that if you reconnect a device to the same computer, you should get the same ID. Note that the source ID will not be the same between different browsers and Framer.
To find the source ID, you can use the extra information send to the handler of onValueChange
.
MIDIComponent.onValueChange(handler)
Handle MIDI signal events.
The handler gets two parameters, first the value of the signal and second an object with more information about the origin.
midi = # Print the identifier of the control sending the change midionValueChange print infocontrol
See the Get Started section for more examples.
Properties
The info parameter is an object with the following properties:
control
— the identifier of the control (knob, slider, etc.) sending the signal.channel
— the channel the signal is send over.source
— the identifier of the device sending the signal.type
(optional) —"note"
if the signal is coming from a note, the value represents the velocity,0
means the note is off.
Modules
Modules allow you to separate and organize parts of your prototype across different files. They're JavaScript or CoffeeScript files, which you can include (require) within your prototype. They help you organize your code, and choose what parts to focus on.
You can find them in the /modules folder of your prototype. Modules are based on JavaScript and Node.js standards. Everything that you've prefixed with exports
in your module will be available in your prototype.
The require
keyword imports your module.
If you want to add modules to an older project, we advice to create a new project in the latest Framer Studio, and copy over your files.
Get Started
- Create a new project in Framer Studio
- Navigate to the /modules folder and open the myModule.coffee file in a text-editor.
- To include the module within your project, add the following:
# To include myModule.coffee in our prototype module = require "myModule"
Make sure to save your file and refresh your prototype to see changes. Modules can contain anything. For example, you can create Layers within your modules, or define specific interactions within functions.
# Store variables exports.myVar = "myVariable" # Create functions = -> print "I'm running!" # Create Arrays exports.myArray = 123 # Create Layers exports.mylayerA = backgroundColor: "#fff"
In the example above, a new layer is automatically created and included within our prototype. To also run the function, you can write:
# To include myModule.coffee module = require "myModule" # Run the function, printing "I'm running!" modulemyFunction
Example: Interactions
Let's create a simple draggable interaction within a module. In our myModule.coffee file, we include the following function. It takes a layer, makes it draggable, and snaps it back to its original position on DragEnd.
# A draggable function without our module = layer.draggable.enabled = true # Store current x and y position startX = layerx startY = layery # Animate back on DragEnd layeron EventsDragEnd-> thisanimate x: startX y: startY options: curve: Springdamping: 0.5 time: 0.5
Now, within our prototype, we can call the makeDraggable function from our module to include the dragging interaction.
# Include module module = require "myModule" # Set background bg = backgroundColor: "#28AFFA" # Create a new layer layerA = backgroundColor: "#fff" borderRadius: 4 layerAcenter # Add the dragging interaction to layerA modulemakeDraggablelayerA
Example: npm
Framer modules work with npm, a package manager where thousands of JavaScript packages are published. Let’s import the Moment.js library. Make sure you already have npm installed.
# In your terminal cd ~/my-projectframernpm install moment
Create a new module in /modules
, and name it npm.coffee
. Beware that if you name the file the same as the npm module (like moment.coffee
), you could run into a recursive import problem.
# File: modules/npm.coffee exports.moment = require "moment"
After a refresh, you can import moment into your project.
# Import the moment module from your npm index moment = require"npm"moment # Or use this nice shortcut, which is the exact same require "npm"
And now you can use it in your project:
dayStarted = html: momentstartOf"day"fromNow
PageComponent
The PageComponent is based on the ScrollComponent, but designed for displaying paginated instead of continuous content. It supports content layers of different sizes, and can snap to layers based on location and scroll velocity.
# Create a new PageComponent and only allow horizontal scrolling. page = width: Screenwidth height: Screenheight scrollVertical: false # Define the first page pageOne = width: pagewidth height: pageheight parent: pagecontent backgroundColor: "#28affa"
Let's add a second page now. Read more about the addPage method.
# Define second page pageTwo = width: pagewidth height: pageheight backgroundColor: "#90D7FF" # Add the second page to the right pageaddPagepageTwo"right"
Another way to go about adding content is by using a for-loop.
# Create a new PageComponent and only allow horizontal scrolling. page = width: Screenwidth height: Screenheight scrollVertical: false backgroundColor: "#fff" # Create 5 new layers and add them to the page.content for number in 0...5 pageContent = width: pagewidth height: pageheight x: pagewidth * number backgroundColor: UtilsrandomColor0.5 parent: pagecontent # Visualize the current page number pageContent.html = pageContent.html = number + 1 # Center the current page number pageContent.style = "font-size" : "100px" "font-weight" : "100" "text-align" : "center" "line-height" : "px"
page.originX <number>
Defines how pages will be horizontally snapped to. The origin is defined as a number between 0
and 1
, where 0
is the left-edge and 1
the right-edge. The default value is 0.5
, the center.
page = page.originX = 0
page.originY <number>
Defines how pages will be vertically snapped to. The origin is defined as a number between 0
and 1
, where 0
is the top-edge and 1
the bottom-edge. The default value is 0.5
, the center.
page = page.originY = 0
page.velocityThreshold <number>
The velocityThreshold influences the role velocity plays in snapping to a different page. Besides the scrolling distance, the PageComponent also takes your scrolling speed (velocity) into account.
page = page.velocityThreshold = 0.2
To better understand the effects of adjusting the velocityThreshold, you can print out your velocity after scrolling. If you want switching between pages to be based mostly on distance, increase the velocityThreshold.
# Increase the velocityThreshold page.velocityThreshold = 5 # After switching between pages, print the velocity pageon EventsScrollEnd-> print Mathabspagevelocityx
page.animationOptions <object>
Set the animation options for the PageComponent. This defines the animation that occurs on ScrollEnd, when snapping to a page.
page = page.animationOptions = curve: Bezierease time: 0.25
page.currentPage <Layer object>
Get the current page layer. (Read-only)
page = # Get the current page layer print pagecurrentPage
Note that you have to have pages within the page.content layer. You can also listen to the "change:currentPage"
event to get the new currentPage, after it has been changed.
page = # When the current page changes, print the new one pageon "change:currentPage"-> print pagecurrentPage
page.closestPage <Layer object>
Get the closest page layer. (Read-only)
page = # Get the current page layer print pageclosestPage
Note that you have to have pages within the page.content layer. You can also listen to the Scroll
event to get the page closest page while scrolling.
# Create a new PageComponent and only allow horizontal scrolling. page = # Print the closest page while scrolling pageon EventsScroll-> print pageclosestPage
page.nextPage(direction, currentPage)
Get the next page. Takes two arguments: direction and the currentPage. By default, the direction is set to "right"
and the currentPage will be the first page.
page = width: Screenwidth height: Screenheight pageOne = width: pagewidth height: pageheight parent: pagecontent backgroundColor: "#28affa" pageTwo = width: pagewidth height: pageheight backgroundColor: "#90D7FF" pageaddPagepageTwo"right"print pagenextPage
We can also set the currentPage to any other page. For instance, we can look which layer is at the left of the second page.
# Get the page to the left of pageTwo print pagenextPage"left"pageTwo # Returns pageOne
page.previousPage <Layer object>
Get the previous page. Effectively the same as getting the page on the left using page.nextPage("left")
. (Read-only)
page = # Get the previous page print pagepreviousPage
page.snapToPage(page, animate, animationOptions)
Snap to a specific page. Takes three arguments: a page.content layer, animate (true or false) and animation options. By default, animate is set to true and the animationCurve use a spring curve.
page = width: Screenwidth height: Screenheight pageOne = width: pagewidth height: pageheight parent: pagecontent backgroundColor: "#28affa" pageTwo = width: pagewidth height: pageheight backgroundColor: "#90D7FF" pageaddPagepageTwo"right" # Automatically scroll to pageTwo pagesnapToPagepageTwo
In the example above, we can customize the scrolling animation by defining custom animationOptions as well.
# Define a slower easing curve pagesnapToPage pageTwo true animationOptions = time: 2
page.snapToNextPage(direction, animate, animationOptions)
Snap to a specific the next page. Takes three arguments: direction, animate (true
or false
) and animation options. By default, the direction is set to "right"
and animate is true
.
page = width: Screenwidth height: Screenheight pageOne = width: pagewidth height: pageheight parent: pagecontent backgroundColor: "#28affa" pageTwo = width: pagewidth height: pageheight backgroundColor: "#90D7FF" pageaddPagepageTwo"right" # Automatically scroll to pageTwo pagesnapToNextPage
This allows you to snap to pages in any direction. For example, we can start on the first page by snapping to it without animating, and then animate back to the first page.
# Start at page two by default pagesnapToPagepageTwofalse # Scroll back to the page at its left, which is pageOne pagesnapToNextPage"left"true
page.snapToPreviousPage()
Snaps to the previous page. It keeps track of all previously visited pages, included the direction.
page = # Snap to the previous page pagesnapToPreviousPage
page.addPage(direction)
Add a new page to the page.content layer of the PageComponent. It takes two arguments: a layer (page) and a direction ("right"
or "bottom"
).
page = width: Screenwidth height: Screenheight # The first page, placed directly within the page.content pageOne = width: pagewidth height: pageheight parent: pagecontent backgroundColor: "#28affa" # Second page pageTwo = width: pagewidth height: pageheight backgroundColor: "#90D7FF" # Third page pageThree = width: pagewidth height: pageheight backgroundColor: "#CAECFF" # Add the second and third page to the right pageaddPagepageTwo"right"pageaddPagepageThree"right"
If you're looking to add pages to the left, you can initially add them to the right, and instantly switch to a different page, using snapToPage().
page = width: Screenwidth height: Screenheight pageOne = width: pagewidth height: pageheight parent: pagecontent backgroundColor: "#28affa" pageTwo = width: pagewidth height: pageheight backgroundColor: "#90D7FF" # Add a page to the right pageaddPagepageTwo"right" # Start at the second page by default pagesnapToPagepageTwofalse
page.horizontalPageIndex(page)
Get the index for a page component with horizontal pages. This is a number between 0 and the number of pages minus 1.
page = width: Screenwidth height: Screenheight pageA = size: pagesize pageB = size: pagesize pageaddPagepageA"right"pageaddPagepageB"right" print pagehorizontalPageIndexpageA# Prints: 0 print pagehorizontalPageIndexpageB# Prints: 1
page.verticalPageIndex(page)
Get the index for a page component with vertical pages. This is a number between 0 and the number of pages minus 1.
page = width: Screenwidth height: Screenheight pageA = size: pagesize pageB = size: pagesize pageaddPagepageA"bottom"pageaddPagepageB"bottom" print pageverticalPageIndexpageA# Prints: 0 print pageverticalPageIndexpageB# Prints: 1
Pinchable
Pinchable layers can be scaled and rotated with two fingers. By default, both of these properties are enabled. You can also define custom scale ranges, by defining minimum and maximum values. To pinch layers within Framer Studio, hold the alt key while moving your cursor.
layer.pinchable.enabled <boolean>
Enable pinching for the layer.
layerA = layerA.pinchable.enabled = true
layer.pinchable.threshold <number>
The minimal distance between two pointers before the gesture is recognized. Set to 0 by default.
layerA = layerA.pinchable.enabled = true # Set the minimal distance to 10 layerA.pinchable.threshold = 10
layer.pinchable.centerOrigin <boolean>
Sets the transform origin of your pinchable layer to the center point between your fingers. Set to true by default.
layerA = layerA.pinchable.enabled = true # Always scale from the center of the layer layerA.pinchable.centerOrigin = false
layer.pinchable.scale <boolean>
Enable or disable scaling on pinch. Set to true by default.
layerA = layerA.pinchable.enabled = true # Disable scale on pinch layerA.pinchable.scale = false
layer.pinchable.scaleIncrements <number>
Scale the pinchable layer incrementally.
layerA = layerA.pinchable.enabled = true # Scale in increments of 0.5 (0.5, 1, 1.5, 2) layerA.pinchable.scaleIncrements = 0.5
layer.pinchable.minScale <number>
Set the minimal scale value of the pinchable layer.
layerA = layerA.pinchable.enabled = true # Set the minimal scale to 0.5 layerA.pinchable.minScale = 0.5
layer.pinchable.maxScale <number>
Set the maximal scale value of the pinchable layer.
layerA = layerA.pinchable.enabled = true # Set the maximal scale to 2 layerA.pinchable.maxScale = 2
layer.pinchable.scaleFactor <number>
Set the scaling factor of the pinchable layer. Set to 1 by default.
layerA = layerA.pinchable.enabled = true # Increase scaling speed by 2 layerA.pinchable.scaleFactor = 2
layer.pinchable.rotate <boolean>
Enable or disable rotation on pinch. Set to true by default.
layerA = layerA.pinchable.enabled = true # Disable scale on pinch layerA.pinchable.rotate = false
layer.pinchable.rotateIncrements <number>
Rotate the pinchable layer incrementally.
layerA = layerA.pinchable.enabled = true # Rotate in increments of 15 degrees layerA.pinchable.rotateIncrements = 15
layer.pinchable.rotateFactor <number>
Set the rotation factor of the pinchable layer. Set to 1 by default.
layerA = layerA.pinchable.enabled = true # Increase the rotation speed by 2 layerA.pinchable.rotateFactor = 2
Printing allows you to inspect variables on runtime. It works similarly to console.log, only when using print, the output is shown directly within your prototype. Note that you need to use print() in Javascript (but not in CoffeeScript). We will omit these in the rest of the docs.
print "Hello"# Output: "Hello"
You can inspect any type of value, and even multiple at the same time.
layerA = x: 10 y: 20 # A single property value print layerAx# Output: 10 # Multiple values print layerAxprint layerAy# Output: 10, 20
RangeSliderComponent
The RangeSliderComponent creates a range slider with two knobs. You can use it to define and edit a numeric range, like a price filter. It consists of four layers: the slider itself, the fill, the minKnob and the maxKnob.
# Create a range slider range = x: Aligncenter y: Aligncenter
By default, the slider has a dark fill color, a light-gray backgroundColor
and rounded corners with borderRadius
. The radius of the fill automatically matches with that of the slider, so you only need to set it once.
# Customize the appearance range.backgroundColor = "#ddd"range.borderRadius = 4
rangeSlider.min <number>
The mininum range of the slider. Set to 0
by default.
# Create a range slider range = x: Aligncenter y: Aligncenter min: 0 max: 10
rangeSlider.max <number>
The maximum range of the slider. Set to 1
by default.
# Create a range slider range = x: Aligncenter y: Aligncenter min: 0 max: 10
rangeSlider.minValue <number>
The minimum value of the slider. Set to 0
by default.
# Create a range slider range = x: Aligncenter y: Aligncenter minValue: 0
You can exclusively listen to minimum value changes.
rangeonMinValueChange -> print rangeminValue
You can also listen to any value changes using the Value Change event.
rangeonValueChange -> print rangeminValuerangemaxValue
rangeSlider.maxValue <number>
The maximum value of the slider. Set to 0.5
by default.
# Create a range slider range = x: Aligncenter y: Aligncenter maxValue: 0.5
You can exclusively listen to maximum value changes.
rangeonMaxValueChange -> print rangemaxValue
You can also listen to any value changes using the Value Change event.
rangeonValueChange -> print rangeminValuerangemaxValue
rangeSlider.knobSize <number>
The size of both knobs. This automatically sets the width and height of the minKnob
and the maxKnob
. The default value is 30
.
# Create a range slider range = x: Aligncenter y: Aligncenter # Change the size of the knobs range.knobSize = 40
rangeSlider.fill <layer>
The fill of the slider. The width and height are automatically updated, based on the size of the slider. By default, its backgroundColor
is set to #333
.
# Create a range slider range = x: Aligncenter y: Aligncenter # Set the fill color to blue range.fill.backgroundColor = "#00AAFF"
rangeSlider.minKnob <layer>
The knob that influences the minimum value of the slider.
# Create a range slider range = x: Aligncenter y: Aligncenter
The minKnob is a draggable layer, with momentum
enabled.
# Disable momentum range.minKnob.draggable.momentum = false
rangeSlider.maxKnob <layer>
The knob that influences the maximum value of the slider.
# Create a range slider range = x: Aligncenter y: Aligncenter
The maxKnob is a draggable layer, with momentum
enabled.
# Disable momentum range.maxKnob.draggable.momentum = false
rangeSlider.animateToMinValue(minValue, animationOptions)
Automatically animate to a specific minimum value.
Arguments
minValue
— A number, representing the minimum value.animationOptions
— An object with curve, time, delay and repeat properties. (Optional)
# Create a range slider range = x: Aligncenter y: Aligncenter # Animate to 1 rangeanimateToMinValue0.3 # Animate with a custom curve rangeanimateToMinValue0.3 curve: Spring
rangeSlider.animateToMaxValue(maxValue, animationOptions)
Automatically animate to a specific maximum value.
Arguments
maxValue
— A number, representing the maximum value.animationOptions
— An object with curve, time, delay and repeat properties. (Optional)
# Create a range slider range = x: Aligncenter y: Aligncenter # Animate to 1 rangeanimateToMaxValue1 # Animate with a custom curve rangeanimateToMaxValue1 curve: Spring
Screen
The Screen object contains the size of the current device screen. The size changes when switching to a different device. You can also change the background color and the perspective of the device screen.
Screen.backgroundColor <string>
Sets the background color of the device screen.
# Change the device screen background color Screen.backgroundColor = "#28affa"
Screen.width <number>
The width of the current device screen in pixels. (Read-only)
print Screenwidth# Output: 640
Screen.height <number>
The height of the current device screen in pixels. (Read-only)
print Screenheight# Output: 1080
Screen.size <object>
The width and height of the current device screen in pixels. (Read-only)
print Screensize# Output: { width:640, height: 1080 }
Screen.frame <object>
The x, y, width and height of the current device screen in pixels. (Read-only)
print Screenframe# Output: { x:0, y:0, width:640, height: 1080 }
Screen.perspective <number>
The perspective of the current device screen. Set to 1200 by default.
# Rotate layer in 3D layerA = rotationX: 30 # Adjust perspective Screen.perspective = 1000
Screen.perspectiveOriginX <number>
Sets the x origin for 3D transformations. The origin is defined as a number, where 0 is the left edge of the screen and 1 the right edge. The default value is 0.5, the center of the screen.
# Rotate layer in 3D layerA = rotationX: 30 # Set horizontal perspective origin Screen.perspectiveOriginX = 1
Screen.perspectiveOriginY <number>
Sets the y origin for 3D transformations. The origin is defined as a number, where 0 is the top edge of the screen and 1 the bottom edge. The default value is 0.5, the center of the screen.
# Rotate layer in 3D layerA = rotationX: 30 # Set vertical perspective origin Screen.perspectiveOriginY = 1
Screen.convertPointToCanvas(point)
Converts a point from the Screen to the Canvas.
point = x: 20 y: 40 pointInCanvas = ScreenconvertPointToCanvaspoint
Screen.convertPointToLayer(point, layer)
Converts a point from the Screen to a layer.
point = x: 20 y: 40 layer = pointInLayer = ScreenconvertPointToLayerpointlayer
ScrollComponent
A ScrollComponent is used to scroll content. It implements momentum and spring physics, allows for customization, and emits different events.
The ScrollComponent is built with two layers. The ScrollComponent itself is a layer that masks its content. It has a content layer that has draggable enabled and constraints configured. It automatically manages the size of the content layer based on the total size of the sub layers of the content layer.
# Create a new ScrollComponent scroll = width: 100 height: 100 # Include a Layer layerA = parent: scrollcontent
You can also wrap an existing layer within a ScrollComponent, using ScrollComponent.wrap(). The ScrollComponent will insert itself in-between the content and its super layer. This is useful when you've imported designs from Sketch or Photoshop and want to make a layer scrollable. You can learn more about wrapping in the learn section.
layerA = width: 300 height: 300 scroll = ScrollComponentwraplayerA
scroll.content <layer>
The layer to add content to. To add content, create a new Layer and set its parent
to the scroll.content
layer. When the content doesn't fit the ScrollComponent it will be clipped.
scroll = width: 100 height: 100 layerA = parent: scrollcontent image: "images/bg.png" width: 100 height: 200
scroll.contentInset <object>
Inset for the content. This will give your content extra padding between the constraints and the actual content layers.
scroll = width: 100 height: 100 layerA = parent: scrollcontent image: "images/bg.png" width: 100 height: 200 scroll.contentInset = top: 20 right: 0 bottom: 20 left: 0
scroll.speedX <number>
Horizontal scrolling speed, number between 0 and 1. Default value is 1.
scroll = layerA = parent: scrollcontent scroll.speedX = 0.5
scroll.speedY <number>
Vertical scrolling speed, number between 0 and 1. Default value is 1.
scroll = layerA = parent: scrollcontent scroll.speedY = 0.5
scroll.scroll <boolean>
Enable or disable scrolling. Enabled by default. If you set this to false
, it will set both scrollVertical
and scrollHorizontal
to false.
scroll = layerA = parent: scrollcontent scroll.scroll = false
scroll.scrollHorizontal <boolean>
Enable or disable horizontal scrolling.
scroll = layerA = parent: scrollcontent scroll.scrollHorizontal = false
scroll.scrollVertical <boolean>
Enable or disable vertical scrolling.
scroll = layerA = parent: scrollcontent scroll.scrollVertical = false
scroll.scrollX <number>
Horizontal scroll location.
scroll = layerA = parent: scrollcontent scroll.scrollX = 250
scroll.scrollY <number>
Vertical scroll location.
scroll = layerA = parent: scrollcontent scroll.scrollY = 250
scroll.scrollPoint <object>
Define the scroll location with x and y properties.
scroll = layerA = parent: scrollcontent scroll.scrollPoint = x: 0 y: 50
scroll.scrollFrame <object>
Visible scroll frame.
scroll = layerA = parent: scrollcontent scroll.scrollFrame = x: 0 y: 250 width: 250 height: 250
scroll.velocity <number>
Current scroll speed and direction in pixels per second at this current time.
scroll = # On scroll, print the velocity scrollon EventsScroll-> print scrollvelocity
scroll.direction <string>
Current scrolling direction. Returns "up"
, "down"
, "left"
, or "right"
. The scrolling direction is the inverse of the direction of the drag action: when dragging downwards, you're effectively scrolling upwards. (Read-only)
scroll = # On scroll, print the direction scrollon EventsScroll-> print scrolldirection
scroll.directionLock <boolean>
Snap to horizontal/vertical direction after a certain threshold.
scroll = # Allow dragging only in one direction at a time scroll.directionLock = true
scroll.directionLockThreshold <object>
The thresholds for lock directions. The x and y values represent the distance you can drag in a certain direction before it starts locking.
scroll = # Snap horizontally after dragging 50px # Snap vertically instantly scroll.directionLock = true scroll.directionLockThreshold = x: 50 y: 0
scroll.angle <number>
Current scrolling angle (in degrees). The scrolling angle is the inverse of the direction of the drag action: when dragging downwards, you're effectively scrolling upwards. (Read-only)
scroll = # On scroll, print the angle scrollon EventsScroll-> print scrollangle
scroll.isDragging <boolean>
Whether the layer is currently being dragged (returns false when animating). (Read-only)
scroll = # Check if the layer is being dragged scrollonMove -> print scrollisDragging
scroll.isMoving <boolean>
Whether the content is currently moving, either by dragging or by a momentum/bounce animation. (Read-only)
scroll = # Check if the layer is moving scrollonMove -> print scrollisMoving
scroll.closestContentLayer(originX, originY)
Get the layer closest to the ScrollComponent, depending on the defined origin. The origin is defined as numbers between 0
and 1
, where (0,0)
is the top-left corner, (0.5, 0.5)
the center, and (1,1)
the bottom-right corner.
The default values are (0,0)
. This means that it calculates the distance from the top-left of the ScrollComponent to the top-left of the content layers.
scroll = # Create content layers layerA = parent: scrollcontent name: "layerA" x: 0 y: 0 layerB = parent: scrollcontent name: "layerB" x: 50 y: 50 # Get the Layer of which the center point is closest # to the center point of the ScrollComponent print scrollclosestContentLayer0.50.5
scroll.closestContentLayerForScrollPoint(originX, originY)
Get the content layer closest to a specific point.
scroll = # Create content layers layerA = parent: scrollcontent name: "layerA" x: 0 y: 0 layerB = parent: scrollcontent name: "layerB" x: 50 y: 50 # Get the layer of which the top-left # corner is closest to x: 50, y: 25 print scrollclosestContentLayerForScrollPoint x: 50 y: 25 # Returns layerB
You can adjust the origin values to define how the distance is calculated. The default values are (0,0)
. This means that it calculates the distance from the top-left of the ScrollComponent to the top-left of the content layers.
scroll = # Create content layers layerA = parent: scrollcontent name: "layerA" x: 0 y: 0 layerB = parent: scrollcontent name: "layerB" x: 50 y: 50 # With the origins set to the center, # layerA becomes the closest print scrollclosestContentLayerForScrollPoint x: 50y: 25 0.50.5 # Returns layerA
scroll.scrollToPoint(point, animate, animationOptions)
Scroll to a specific point, optionally animating.
Arguments
point
— An object with x and y properties.animate
— A boolean, set to true by default. (Optional)animationOptions
— An object with curve, time, delay and repeat properties. (Optional)
scroll = # Scroll content to x: 200, y: 100 scrollscrollToPoint x: 200y: 100 true curve: Bezierease # Scroll very slowly scrollscrollToPoint x: 200y: 100 true curve: Beziereasetime: 10
scroll.scrollToLayer(layer, originX, originY, animate, animationOptions)
Scroll to a specific layer. You can only scroll to layers that are children of the scroll.content layer.
Arguments
layer
— A layer object.originX
— A number between 0 and 1. (Optional)originY
— A number between 0 and 1. (Optional)animate
— A boolean, set to true by default. (Optional)animationOptions
— An object with curve, time, delay and repeat properties. (Optional)
# Create ScrollComponent scroll = width: 500 height: 500 # Define Background layerA = x: 500 y: 1000 image: "bg.png" parent: scrollcontent # Scroll to this layer scrollerA = parent: scrollcontent scrollscrollToLayerscrollerA
The originX and originY arguments define the point within the layer that will be scrolled to. The default values are 0,0 - which is the top-left corner.
scrollscrollToLayer layerA 0.50 true time: 2
scroll.scrollToClosestLayer(originX, originY)
Scroll to the closest content layer, using the given origin. The default values are (0,0)
which is the top-left corner, (0.5, 0.5)
the center, and (1,1)
the bottom-right corner.
Arguments
originX
— A number between 0 and 1.originY
— A number between 0 and 1.
scroll = layerA = parent: scrollcontent x: 75 y: 75 # Scroll to the center of layerA scrollscrollToClosestLayer0.50.5
scroll.mouseWheelEnabled <boolean>
Enable or disable scrolling with mousewheel. Disabled by default. When set to true
, layers can be scrolled both by dragging and with the mouse.
scroll = width: 100 height: 100 # Allow scrolling with mouse scroll.mouseWheelEnabled = true layerA = parent: scrollcontent image: "images/bg.png" width: 100 height: 200
scroll.wrap(layer)
Wraps a layer within a new ScrollComponent. This is useful to create scrollable layers out of imported layers.
# Import files from Sketch sketch = FramerImporterload "imported/Scrollable" # Wrap the "content" layer group scroll = ScrollComponentwrapsketchcontent
Now, scroll
is the variable name of the ScrollComponent. This also automatically wraps your layer within a ScrollContent layer, which you can select to adjust certain properties like momentum, overdrag or bounce.
# Import files from Sketch sketch = FramerImporterload "imported/Scrollable" # Wrap the "content" layer group scroll = ScrollComponentwrapsketchcontent # Change scroll properties scroll.scrollHorizontal = falsescroll.speedY = 0.5 # Change scroll.content properties scroll.content.draggable.momentum = truescroll.content.draggable.overdrag = falsescroll.content.draggable.bounce = false
scroll.updateContent()
Re-calculates and updates the size of the content and the dragging constraints. It also accounts for the contentInset.
If you're looking to change the size of your content layers, you can call it to update the size of your ScrollComponent accordingly.
scroll = # Update the contents of the ScrollComponent scrollupdateContent
scroll.copy()
Copies a ScrollComponent, including its content and properties.
scroll = layerA = parent: scrollcontent # Copy the ScrollComponent scrollB = scrollcopy
scroll.propagateEvents <boolean>
Set the propagateEvents property of the draggable content layer. Set to true by default. This is useful when working with nested ScrollComponents or PageComponents.
Let's say you'd like to have a draggable layer within the scroll.content layer. By default, moving the layer will also move the scroll.content. This is because both layers will listen to the dragging events.
To prevent any draggable children from passing events to its parent, set propagateEvents to false. This applies to all nested draggable layers.
scroll = width: Screenwidth height: Screenheight scroll.content.backgroundColor = "#28affa" layerA = parent: scrollcontent backgroundColor: "#fff" layerA.draggable.enabled = true # Setting propagateEvents to false allows you to drag layerA # without also scrolling within the ScrollComponent layerA.draggable.propagateEvents = false
SliderComponent
The SliderComponent creates a fully customisable slider for you. With it, you can adjust any numeric value or layer property. It consists of three layers: the slider itself, the fill and the knob.
# Create a SliderComponent slider = slidercenter
By default, the slider has a dark fill color, a light-gray backgroundColor
and rounded corners with borderRadius
. The radius of the fill automatically matches with that of the slider, so you only need to set it once.
# Customize the appearance slider.backgroundColor = "#ddd"slider.borderRadius = 4
slider.knob <layer>
The knob of the slider. By default, it's made circular using borderRadius
and has a little bit of a drop shadow applied to it.
# Create a SliderComponent slider = slidercenter # Customize the appearance slider.knob.shadowY = 2slider.knob.shadowBlur = 4slider.knob.borderRadius = 6
The knob is a draggable layer, with momentum
enabled.
# Disable momentum slider.knob.draggable.momentum = false
slider.knobSize <number>
The size of the knob. This automatically sets the width and height of the knob. The default value is 30
.
# Create a SliderComponent slider = slidercenter # Change the size of the knob slider.knobSize = 40
slider.fill <layer>
The fill of the slider. The width and height are automatically updated, based on the size of the slider. By default, its backgroundColor
is set to #333
.
# Create a SliderComponent slider = slidercenter # Set the fill color to blue slider.fill.backgroundColor = "#28affa"
slider.min <number>
The mininum value of the slider. Set to 0
by default.
# Create a SliderComponent slider = slidercenter # Set the minimum value slider.min = -1
slider.max <number>
The maximum value of the slider. Set to 1
by default.
# Create a SliderComponent slider = slidercenter # Set the maximum value slider.max = 2
slider.value <number>
The value of the slider. Set to 0.5
by default.
# Create a SliderComponent slider = slidercenter # Print the current value print slidervalue
You can listen to any value changes with the "change:value"
event. This is useful for retreiving the value or mapping it to another layer property, like changing the opacity of a layer with the slider.
slideron "change:value"-> print thisvalue
slider.pointForValue(value)
Takes a value and returns the corresponding point (x) within the slider. With a slider ranging from 0
to 1
, the pointForValue(0.5)
will be the center of the slider. With a width of 200
, this will return 100
.
# Create a SliderComponent slider = width: 200 slidercenter # Print the point for a value of 0.5 print sliderpointForValue0.5# Returns 100
slider.valueForPoint(value)
Takes a point and returns the corresponding value of the slider. With a width of 200
, the valueForPoint(100)
will be the center of the slider. With a slider ranging from 0
to 1
, this will return 0.5
.
# Create a SliderComponent slider = width: 200 slidercenter # Print the value for the point 100 print slidervalueForPoint100# Returns 0.5
slider.animateToValue(value, animationOptions)
Automatically animate to a specific value.
Arguments
value
— A number, ranging from the min to the max value.animationOptions
— An object with curve, time, delay and repeat properties. (Optional)
# Create a SliderComponent slider = slidercenter # Animate to 1 slideranimateToValue1 # Animate with a custom curve slideranimateToValue1 curve: Spring
States
Layer states manage and organize different combinations of layer properties. Animations can use them as a target. Switch lets you jump to another state instantly and cycle allows you to sequentially move from state to state.
You can add any layer property to a state, like x
and y
. Non-animatable layer properties like html
will be set at the end of the state animation.
States can have an animation options property. Which will be used whenever layers get animated to the defined state.
There are three pre-defined states that can't be overridden because they are already assigned to serve a purpose. You can get the state names for current and previous using their name property.
default
— The initially active state.current
— The currently active state.previous
— The previously active state.
Example: Create and delete a state
# Create a state layerA.states.stateA = x: 100 # Delete a state delete layerAstatesstateA
Example: A state with animation options
# Create a state with animationOptions layerA.states.stateA = x: 100 animationOptions: curve: Springdamping: 0.5 time: 0.5
Example: Animate to a state
# Create a state layerA.states.stateA = x: 100 # Animate to the state layerAanimate"stateA"
Example: Switch to a state
# Create a state layerA.states.stateA = x: 100 # Switch to the state without an animation layerAstateSwitch"stateA"
Example: Cycle through states
# Set multiple states at once layerA.states = stateA: x: 100 stateB: x: 200 # On a click, go back and forth between states. layerAonTap -> layerAstateCycle"stateA""stateB"
layer.states.current <object>
Returns an object of the currently active state.
Properties
name
— A read-only property that returns the name of the state object.
layerA = layerA.states.stateA = x: 500 opacity: 0.5 layerAstateSwitch"stateA" print layerAstatescurrent# Output: <Object State> print layerAstatescurrentname# Output: stateA
layer.states.previous <object>
Returns an object of the previously active state.
Properties
name
— A read-only property that returns the name of the state object.
layerA = layerA.states.stateA = x: 500 opacity: 0.5 layerAstateSwitch"stateA" print layerAstatesprevious# Output: <Object State>
TextLayer
A TextLayer allows you to work with type in Framer. Define text within a string, and use its unique properties to style it. Almost all property names match the CSS text styles. You can change the typeface, change the style, adjust the line height, add padding, shadows and much more.
text.text <string>
The text content. By default, the color
is set to #888
.
# Create a TextLayer title = text: "Title"
text.fontSize <number>
The size of the text. By default, it's set to 40
.
# Set fontSize to 64px title = fontSize: 64
text.fontFamily <string>
The current typeface of the text. By default, it's set to use the system typeface of the device you're currently previewing on.
- Apple Device: SF UI.
- Google Device: Roboto.
- Microsoft Device: Segoe UI.
# Create a TextLayer title = fontFamily: "-apple-system"
text.fontWeight <number>
The weight of the text. By default, it's set to 400
.
# Create a TextLayer title = fontWeight: 400
text.fontStyle <string>
The style of the text.
# Set font style to italic title = fontStyle: "italic"
You can choose between italic
, bold
and oblique
.
# Set font style to bold title = fontStyle: "bold"
text.font <string>
A shorthand to define all font styles using a single line.
These properties can be set (in order): "fontStyle fontWeight fontSize/lineHeight fontFamily"
.
# Set font styles in one line title = font: "300 64px/1 -apple-system, Helvetica Neue"
Note that the fontSize and fontFamily properties are required.
# Set font size and font family title = font: "64px -apple-system"
text.padding <object>
The padding of the text. By default, it's set to 0
.
# Set padding title = padding: 40
You can also define padding of each side individually.
# Set padding of each side title = padding: top: 40 left: 20 bottom: 40 right: 20
Left and right padding can be defined by using the horizontal
shorthand. Top and bottom padding can also be defined using the vertical
shorthand.
# Set horizontal and vertical padding title = padding: horizontal: 40 vertical: 80
text.lineHeight <number>
The line height of the text. By default, it's set to 1.25
. This means that if you've set the fontSize
to 40, the line-height will effectively be 50px.
# Set line-height title = lineHeight: 1.5
text.letterSpacing <number>
The letter spacing of the text in pixels. Set to 0
by default.
# Set letter spacing title = letterSpacing: 2
text.wordSpacing <number>
The letter spacing of the words in pixels. Set to 0
by default.
# Set word spacing title = wordSpacing: 10
text.textAlign <string>
The alignment of the text.
# Center-align the text title = textAlign: "center"
You can choose between left
, right
and center
.
# Multiple ways to align text title.textAlign = "left"title.textAlign = "right"title.textAlign = "center"
Alternatively, you can also use the Align class.
# Center-align the text title = textAlign: Aligncenter
text.textTransform <string>
The capitalization of the text.
# Uppercase all characters title = textTransform: "uppercase"
You can choose between uppercase
, lowercase
and capitalize
.
# Multiple ways to capitalize text title.textTransform = "uppercase"title.textTransform = "lowercase"title.textTransform = "capitalize"
text.textDecoration <string>
The decoration of the text.
# Add an underline to the text title = textDecoration: "underline"
You can choose between underline
, overline
and line-through
.
# Add an overline to the text title = textDecoration: "overline"
text.textIndent <number>
The indentation of the first paragraph of text in pixels.
# Indent the text by 20 pixels title = textIndent: 20
text.textOverflow <string>
Add an ellipsis to overflowing text content.
# Single line clipping paragraph = textOverflow: "ellipsis" text: """ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. """
If you set the height
, you’ll be able to add an ellipsis to multiple lines.
# Multi line clipping paragraph = textOverflow: "ellipsis" height: 100 text: """ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. """
text.direction <string>
The direction of the text. The direction of the text. Set to left-to-right
by default.
# Set the text direction title = direction: "right-to-left"
You can choose between right-to-left
(rtl
) and left-to-right
(ltr
).
# Set the text direction title = direction: "rtl"
text.truncate <boolean>
A shorthand of setting textOverflow to "ellipsis"
.
# Single line clipping paragraph = truncate: true text: """ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. """
If you set the height
, you’ll be able to add an ellipsis to multiple lines.
# Multi line clipping paragraph = truncate: true height: 100 text: """ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. """
text.shadowX <number>
Defines the shadow direction on the x-axis. A positive value will produce a shadow from the right edge of a layer, whereas a negative value will produce a shadow from the left edge.
# Set horizontal text shadow title = shadowX: 10
text.shadowY <number>
Defines the shadow direction on the y-axis. A positive value will produce a shadow from the bottom edge of a layer, whereas a negative value will produce a shadow from the top edge.
# Set vertical text shadow title = shadowY: 10
text.shadowBlur <number>
Adds a gaussian blur to the shadowX or shadowY property. shadowBlur is defined with a number. The default value is 0.
# Set text shadow title = shadowY: 1 shadowBlur: 4
text.shadowColor <string>
Sets the color of a layers shadow. The color is expressed as a string in the CSS color format.
# Set text shadow and color title = shadowY: 10 shadowColor: "rgba(0,0,0,0.2)"
Utilities
Utilities are custom functions in Framer, designed to make things easier to do. For example, they allow you to map values, set delays and intervals, detect devices and more. See below for a complete overview.
Utils.modulate(value, [a, a], [b, b], limit)
Translates a number between two ranges. When you enable limit, it will never return a value outside of the b
range. The default value for limit is false
.
Arguments
value
— A variable, representing the input.[a, a]
— The first range of two numbers.[b, b]
— The second range of two numbers.limit
— A boolean, set to false by default. (Optional)
print Utilsmodulate0.5010100# Output: 50 print Utilsmodulate1010100# Output: 100
You can think of modulate as a way to convert numbers between different scales. Like going from Celcius to Farenheit, or Kilometers to Miles.
# Convert to Celsius/Farenheit Utilsmodulatecelcius010032212
It's also useful for creating parallax effects on scroll. For example, you can move a layer from 0-10
, when scrolling from 0-100
.
scroll = scrollHorizontal: false layerA = x: 100 # Modulate the scrolling distance scrollon EventsMove-> y = UtilsmodulatescrollscrollY0100010 layerA.y = y
Utils.cycle(values)
Creates a function that returns the next value of an array every time it's called.
Arguments
values
— An array of values.
cycler = Utilscycle"a""b""c" print cycler # Output: "a" print cycler # Output: "b" print cycler # Output: "c" print cycler # Output: "a", returns to start
Utils.loadWebFont(fontFamily, fontWeight)
Load and set a typeface from Google Web Fonts.
Arguments
fontFamily
— A string with the name of the typeface.fontWeight
— A number defining the font weight.
# Load Raleway from Google Web Fonts raleway = UtilsloadWebFont"Raleway" # Set fontFamily title = fontFamily: raleway
You can optionally pass along a number as a second argument, which represents a specific fontWeight
of the typeface to load.
# Load a bold weight of Raleway raleway = UtilsloadWebFont"Raleway"600 # Set font title = font: raleway
Utils.labelLayer(layer, text)
Quickly add a label to a layer. By default, the text will be set in Menlo, and positioned in the center of the layer.
Arguments
layer
— A layer object.text
— A string.
layerA = # Add a label to layerA UtilslabelLayerlayerA"Hello"
Utils.round(value, decimals, increments, min, max)
Rounds a number.
Arguments
value
— A floating point number.decimals
— The amount to appear after the decimal point. (Optional)increments
— The increment to round to. (Optional)min
— The minimum value to return. (Optional)max
— The maximum value to return. (Optional)
print Utilsround100.123450 # Output 100 print Utilsround100.123452 # Output 100.12 print Utilsround100.123454 # Output 100.1234
Utils.randomChoice(values)
Select a random item in an array of values.
Arguments
values
— An array of values.
print UtilsrandomChoice"a""b""c" # Output: "c" print UtilsrandomChoice"a""b""c" # Output: "b" print UtilsrandomChoice"a""b""c" # Output: "b" print UtilsrandomChoice"a""b""c" # Output: "b" print UtilsrandomChoice"a""b""c" # Output: "a"
Utils.randomColor(opacity)
Creates a random color with a given opacity. The opacity is optional.
Arguments
opacity
— A number between 0 and 1. (Optional)
layerA = layerA.backgroundColor = UtilsrandomColor0.5 print layerAbackgroundColor# Output: "rgba(124, 12, 33, 0.5)"
Utils.randomImage(layer or size)
Generate a random unsplash image url. If you optionally pass a layer or size, it will keep using the same image for that layer and optimize for the size.
Arguments
layer
— Layer
layer = layer.image = UtilsrandomImage # Unoptimized layer.image = UtilsrandomImagelayer # Preferred
Utils.randomNumber(a, b)
Generate a random number between a and b.
Arguments
a
— A number, the first value of the range.b
— A number, the final value of the range.
print UtilsrandomNumber01 # Output: 0.2 print UtilsrandomNumber0100 # Output: 22
Utils.delay(delay, handler)
Calls a function after a delay. Delay is defined in seconds.
Arguments
delay
— A number, representing seconds.handler
— A function.
Utilsdelay 0.5-> print "hello" # Output: "hello", after 0.5 seconds
Utils.frameInset(frame, inset)
Arguments
frame
— An object with x, y, width, height.inset
— A number or object with top, right, bottom, left
Inset a frame by a certain amount of pixels.
print UtilsframeInsetx:0y:0width:100height:10010 # Output {x:10, y:10, width:80, height:80} print UtilsframeInsetx:0y:0width:100height:100top: 20 # Output {x:0, y:20, width:100, height:80}
Utils.interval(interval , handler)
Calls a function every x seconds.
Utilsinterval 2-> print "hello" # Output: "hello" # Output: "hello" # Output: "hello" # Output: "hello" etc...
Utils.debounce(interval, handler)
Creates a function that will delay the calling of handler until after x seconds have elapsed since the last time it was invoked. Alias to _.debounce.
Arguments
interval
— A number, representing seconds.handler
— A function.
handler = Utilsdebounce 0.1-> print "hello" for i in 1..100 handler # Output: "hello" only once
Utils.insertCSS(css)
Add css to a layer by wrapping it in a string and passing it as a parameter.
layerA = layerAclassListadd"testClass" css = """.testClass { border: 1px solid #000;}""" print UtilsinsertCSScss
Utils.throttle(interval, handler)
Creates a function that will call the wrapped function at most once per x seconds. Alias to _.throttle.
Arguments
interval
— A number, representing seconds.handler
— A function.
handler = Utilsthrottle 0.1-> print "hello" for i in 1..100 handler # Output: "hello" only once
Utils.isWebKit()
Returns whether this is a WebKit browser.
print UtilsisWebKit # Output true
Utils.isChrome()
Returns whether this is a Chrome browser.
print UtilsisChrome # Output true
Utils.isSafari()
Returns whether this is a Safari browser.
print UtilsisSafari # Output true
Utils.isTouch()
Returns whether this is a touch enabled browser.
print UtilsisTouch # Output true
Utils.isDesktop()
Returns whether this is a desktop browser.
print UtilsisDesktop # Output true
Utils.isPhone()
Returns whether this is a phone device.
print UtilsisPhone # Output true
Utils.isTablet()
Returns whether this is a tablet device.
print UtilsisTablet # Output true
Utils.isMobile()
Returns whether this is a mobile device (phones and tables).
print UtilsisMobile # Output true
VideoLayer
A videoLayer loads a video. VideoLayers have a layer.player
object to control the video. The browser supports many different types of video, including the Animation codec that supports alpha channels.
videoLayer.video <string>
Sets the video URL for the video layer.
# Set on creation layerA = video: "hello.mp4" # Change afterwards layerA.video = "bye.mp4"
videoLayer.player <object>
Player object for the video layer. Allows you to control the video and listen for playback events. See this overview of all video methods and properties.
# Set on creation layerA = video: "hello.mp4" # Enable auto play layerA.player.autoplay = true # Play the video layerAplayerplay # Jump to 5 seconds layerAplayerfastSeek5 # Listen to paused playback EventswraplayerAplayeron "pause"-> print "Video paused"