Parallax: Scroll Effects

Linton Ye

Parallax: Scroll Effects

Overview

sticky-headers

iphoneXR

svgtracing

This module makes it easy to create advanced scroll interactions. There are two ways of using the module:

  • Non-coding: just drag and drop components, you’ll be able to control the speed, opacity, rotation, scale etc. of a layer when scrolling.
  • Code overrides: a lot more control and flexibility (see below)!

Check out some quick demos:

Demo File:

Getting started

  • Non-coding:

    1. Drop a ParallaxScroll and connect with the entire scroll content. The usage is exactly the same as the standard Scroll component.
    2. Drop a few ParallaxLayer and connect them with respective content
    3. Tweak the parameters of a ParallaxLayer in the properties panel
    4. Profit!
  • Code overrides:

    1. Drop a ParallaxScroll and connect with the entire scroll content. The usage is exactly the same as the standard Scroll component.
    2. Add an override to any Frames in the scroll content (details below). Yes, it doesn’t have to be ParallaxLayer!
    3. Profit!

Code overrides

A simple example: make an item sticky

sticky

import { useSticky, useScroll } from "@framer/lintonye.parallax/code"

export function Sticky100400(): Override {
  // scrollY here is a MotionValue
  const { scrollY } = useScroll()
  // y is a MotionValue too
  const y = useSticky(scrollY, [100, 400])
  // This is short for { y: y }, where the first "y" is the property key, the second "y"
  // is the variable name.
  return { y }
};

You may see an error in Framer’s code editor. This is a known bug of Framer. The override still works. Or you can edit the file with an external editor.

import-error

Make an item sticky and then fades away

sticky and fade

import { useSticky, useScroll } from "@framer/lintonye.parallax/code"
import { Override, useTransform } from "framer"

export function Sticky100400(): Override {
  // scrollY here is a MotionValue
  const { scrollY } = useScroll()
  // y is a MotionValue too
  const y = useSticky(scrollY, [100, 400])
  const opacity = useTransform(scrollY, [400, 500], [1, 0])
  // short for { y: y, opacity: opacity }
  return { y, opacity }
};

Move an item move at a different speed

speed

import { useSpeed, useScroll } from "@framer/lintonye.parallax/code"

export function Speed0(): Override {
  const { scrollY } = useScroll()
  const y = useSpeed(scrollY, [0, 1000], 0)
  return { y }
};

export function Speed05(): Override {
  const { scrollY } = useScroll()
  const y = useSpeed(scrollY, [0, 1000], 0.5)
  return { y }
};

export function SpeedMinus1(): Override {
  const { scrollY } = useScroll()
  const y = useSpeed(scrollY, [0, 1000], -1)
  return { y }
};
...

Trigger an animation when scrolling into a range

trigger

import { useTrigger, useScroll } from "@framer/lintonye.parallax/code"
import { useAnimation } from "framer"
export const TriggerAnimation: Override = props => {
  const animate = useAnimation()
  const { scrollY } = useScroll()
  useTrigger(scrollY, [600, 650], direction => {
    animate.start({ rotate: direction > 0 ? 0 : 180 })
  })
  return {
    animate
  }
}

useSticky and other hooks

Check out the documentation here.

Contact

Change Log

  • 12/10/2019 (v1.52)
    • Fix BgColor of ParallaxLayer
    • Allow negative scroll range and values
    • Allow decimal for scale values
  • 10/08/2019
    • Add new hooks: useTrackScrollX, useTrackScrollY
  • 10/04/2019
    • Update to support the latest Framer library (1.1.3)! Yay!
    • You can now control the speed, rotation, scale and opacity of a layer WITHOUT CODE!
    • React Hook based API for more advanced control
  • 02/21/2019
    • Hide internal components
  • 02/03/2019
    • Add support for using object as op, instead of just an array
    • Fixed: onMove op function is always called when a data item is updated inside the function body
    • Now we can return true to ask the next onMove op function to run. If the return value is falsy (e.g. no return value is specified), the function will be only called once per scroll direction.
  • 01/29/2019
    • Fix id conflict issue. Now, as long as the ids are unique within a single scrollOverrides call, things should be fine.
  • 01/26/2019
    • Add support for horizontal scroll. Note: you’ll get an error when the scroll direction is “both”.
    • Add speed, sticky and snap functions, which work on both horizontal and vertical directions.
  • 01/23/2019
    • Fix issue in speed and sticky that causes layer to jump locations when crossing ranges
  • 01/17/2019
    • Add snapY function
  • 01/16/2019
    • Add support for advanced scroll interactions
  • 01/10/2019
    • Add override functions for sticky scrolls (Doc pending)
  • 10/09/2018
    • Support controlling positions with math expressions
  • 10/08/2018
    • Better performance - (dev note: no more cloning of children)
  • 10/07/2018
    • Better scrolling performance
    • We can now independently configure speed X and Y of a layer.
    • Pin in scroll direction
  • 10/02/2018 - Support horizontal scroll
  • 09/18/2018 - Use Scroll component instead of the hacky div