Skip to content

Latest commit

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ScrollController

ScrollController

ScrollController is a Framer module that helps you to animate, pin and trigger events based on scroll position. It's the module you need, if you want to:

  • animate based on scroll position
  • start an animation at a specific scroll position
  • synchronise an animation to the scroll movement
  • pin a layer indefinitely at a specific scroll position
  • pin a layer for a limited amount of scroll progress
  • add callbacks at specific scroll positions passing a progress parameter
  • easily create parallax effect
  • create infinite scrolling
  • create sticky headers

Works with Framer v120 or later

Table of contents

Installation
Demo
Quick start
Documentation
Known limitations
Releases
License
Author
Acknowledgement

Installation

Install with Framer Modules

  1. Open your project in Framer.
  2. Start Framer Modules and select ADD MODULE.
  3. Search for ScrollController, once found hit enter to install into your prototype.
Install with Framer Modules

Install manually

  1. Open your project in Framer.
  2. Download and unzip the module.
  3. Drag the file ScrollController.coffee into the code editor.
  4. Change ScrollController to {ScrollController} in the require command

Demo

ScrollController Example

Quick start

To get started using the ScrollController you must start by creating a Controller to make the required connection to the ScrollComponent. Secondly you must add at least one Scene which defines in what part of the page/view something should happen. Finally you may add at least one Tween or Pin to define what needs to happen. Alternatively you may listen for events with callbacks to trigger your prototype.

Step 1: Import module
# Import module
{ScrollController} =require'ScrollController'
Step 2: Create setting (with built-in components)
# Create ScrollComponentmyScrollComponent=newScrollComponentframe:Screen.framescrollHorizontal:false# Create containermyContainer=newLayerparent:myScrollComponent.contentwidth:Screen.widthheight:Screen.height*2backgroundColor:null# Create layermyLayer=newLayerparent: myContainer
point:Align.center
Step 3: Create controller and add scene, tween and pin
# Create controllermyController=newScrollControllersource: myScrollComponent
# Add scenemyScene=myController.addScenetriggerLayer: myLayer
duration:200guide:true# Add tweeenmyTween=myScene.addTweento: {rotation:-90, scale:0.2, backgroundColor:"#00AAFF"}
options: {time:0.25, curve:"Spring"}
# Add pinmyPin=myScene.addPin()
Step 4: Listen for events with callback
# Listen for event with callbackmyScene.onProgress (event, instance) ->myTextLayer.text="#{event.progress}"

Documentation

ScrollController consists of 4 components: Controller, Scene, Tween and Pin. Learn about each components and its properties in the documentation:

Components

Controller
Scene
Tween
Pin

Controller

The controller establishes the required connection to the ScrollComponent and manages attached scenes by either updating or refreshing them whenever the ScrollComponent changes its size or when its scroll position changes. The controller manages one direction - create two controllers if you need to manage both horizontal and vertical movement at the same time.

PropertyTypeDefaultDescription
new ScrollControllerClass-Create controller
Controller.sourceObject-Get controller source
Controller.nameString"."Get/Set controller name
Controller.directionString"vertical"Get controller scroll direction
Controller.throttleNumber0Get/Set controller throttling
Controller.enabledBooleantrueGet/Set controller enabled state
Controller.addSceneMethod-Add scene to controller
Controller.removeSceneMethod-Remove scene from controller
Controller.scrollToMethod-Scroll to scene, progress, layer or offset
Controller.updateMethod-Force controller update
Controller.refreshMethod-Force controller refresh
Controller.removeMethod-Remove controller

new ScrollController

Create controller.

Parameters:
  • source – ScrollComponent instance – required
  • name – controller name
  • direction – controller scroll direction
  • throttle – controller throttling
  • enabled – controller enabled state
# Create controller with default propertiesmyController=newScrollControllersource: myScrollComponent
# Create controller with custom propertiesmyController=newScrollControllersource: myScrollComponent
name:"myControllerName"direction:"horizontal"throttle:0.01enabled:false

Controller.addScene

Add scene to controller.

Parameters:
  • name – scene name
  • triggerLayer – scene triggerLayer to define the start of the scene
  • offset – scene offset, from top/left of screen or from triggerLayer
  • duration – scene duration
  • needle – scene needle position, from begining to end of screen (0 to 1)
  • reverse – scene reversable state
  • enabled – scene enabled state
  • guide – scene guide markers
  • guideNeedleColor – scene guide needle color
  • guideStartColor – scene guide start color
  • guideEndColor – scene guide end color
  • guideIndent – scene guide indent
# Add scene to controller with default propertiesmyScene=myController.addScene()
# Add scene to controller with custom propertiesmyScene=myController.addScenename:"mySceneName"triggerLayer: myLayer
offset:-100duration:200needle:0.65reverse:falseenabled:falseguide:trueguideNeedleColor:"blue"guideStartColor:"green"guideEndColor:"red"guideIndent:40

Controller.removeScene

Remove scene from controller.

Parameters:
  • reset – reset scene and all connected tweens and pins
# Remove scenes and all connected tweens and pinsmyController.removeScene myScene
# Remove and reset scene and all connected tweens and pinsmyController.removeScene myScene, true

Controller.scrollTo

Scroll to scene, scene progress, layer and offset

Parameters:
  • element – scene or layer
  • progress – scene progress (0 to 1)
  • offset – offset
# Scroll to scenemyController.scrollToelement: myScene
# Scroll to scene progressmyController.scrollToelement: myScene
progress:0.25# Scroll to layermyController.scrollToelement: myLayer
# Scroll to offsetmyController.scrollTooffset:100# Scroll to scene progress with offsetmyController.scrollToelement: myScene
progress:0.25offset:100

Controller.update

Update controller by recalculating scene, tween and pin properties then automatically refreshing the controller. This happens automatically and should only be used when required.

# Update controllermyController.update()

Controller.refresh

Refresh controller by redrawing scenes, tweens and pins. This happens automatically and should only be used when required.

# Refresh controllermyController.refresh()

Controller.remove

Remove controller.

Parameters:
  • reset – reset controller and all connected scenes, tweens and pins
# Remove controller and all connected scenes, tweens and pinsmyController.remove()
# Remove and reset controller and all connected scenes, tweens and pinsmyController.removetrue

Scene

The scene defines in what part of the page/view something should happen and manages all attached tweens and pins. The scene has a start position defined by either a layer (triggerLayer) and/or an offset (from the triggerLayer or from top/left of screen if no triggerLayer is defined). The scene can also have an end if a duration is defined. Every scene has a needle (defined by a number between 0 and 1, start of screen is 0, end of screen is 1). The needle triggers events once it reaches the start, the end and whenever it enters, progresses and leaves the scene. A scene can be setup easily and precisely by enabling the guide.

PropertyTypeDefaultDescription
Scene.sourceObjectScrollComponentGet scene ScrollComponent
Scene.controllerObjectControllerGet scene controller
Scene.nameString"."Get/Set scene name
Scene.triggerLayerLayerUndefinedGet/Set triggerLayer
Scene.needleNumber0.5Get/Set scene needle (0 to 1)
Scene.offsetNumber0Get/Set scene offset
Scene.durationNumber0Get/Set scene duration
Scene.reverseBooleantrueGet/Set scene reversable state
Scene.enabledBooleantrueGet/Set scene enabled state
Scene.guideBooleanfalseGet scene guide
Scene.guideNeedleColorColor"#0066FF"Get scene guide needle guide
Scene.guideStartColorColor"#009933"Get scene guide start color
Scene.guideEndColorColor"#FF3333"Get scene guide end color
Scene.stateString"before", "during" or "after"Get scene state
Scene.progressNumber-Get scene progress (0 to 1)
Scene.startNumber-Get scene start
Scene.endNumber-Get scene end
Scene.needlePosNumber-Get scene needle position
Scene.scrollOffsetNumber-Get scene scroll offset
Scene.offsetStartNumber-Get scene offset start
Scene.offsetEndNumber-Get scene offset end
Scene.tweensArray-Get scene tweens
Scene.pinsArray-Get scene pins
Scene.addTweenMethod-Add scene tween
Scene.removeTweenMethod-Remove scene tween
Scene.addPinMethod-Add scene pin
Scene.removePinMethod-Remove scene pin
Scene.triggerMethod-Trigger scene event
Scene.updateMethod-Force scene update
Scene.refreshMethod-Force scene refresh
Scene.removeMethod-Remove scene
Scene.onChangeValueEvent-On change value
Scene.onShiftEvent-On shift
Scene.onUpdateEvent-On update
Scene.onEnterEvent-On enter
Scene.onStartEvent-On start
Scene.onProgressEvent-On progress
Scene.onEndEvent-On end
Scene.onLeaveEvent-On leave

Scene.addTween

Add tween to scene.

Parameters:
  • name – tween name
  • layer – tween layer
  • from – tween from properties object - required if no to properties
  • to – tween to properties object - required if no from properties
  • options – tween animation object
  • init – tween initialisation state
  • enabled – tween enabled state
# Add tween to scene with default propertiesmyTween=myScene.addTweenfrom: {opacity:0}
# Add tween to scene with custom propertiesmyTween=myScene.addTweenname:"myTween"layer: myOtherLayer
from: {rotation:0, scale:2, backgroundColor:"white"}
to: {rotation:-90, scale:0.2, backgroundColor:"#00AAFF"}
options: {time:0.25, curve:"Spring", colorModel:"rgb"}
init:trueenabled:false

Scene.removeTween

Remove tween from scene.

Parameters:
  • reset – reset tween
# Remove tweenmyScene.removeTween myTween
# Remove and reset tweenmyScene.removeTween myTween, true

Scene.addPin

Add pin to scene.

Parameters:
  • name – pin name
  • layer – pin layer
  • enabled – pin enabled state
# Add pin to scene with default propertiesmyPin=myScene.addPin()
# Add pin to scene with custom propertiesmyPin=myScene.addPinname:"myPinName"layer: myOtherLayer
enabled:false

Scene.removePin

Remove pin from scene.

Parameters:
  • reset – reset pin
# Remove pinmyScene.removePin myPin
# Remove and reset pinmyScene.removePin myPin, true

Scene.trigger

Trigger scene event.

Parameters:
  • name – event name to trigger – required
  • event – event object for callback
# Trigger scene eventmyScene.triggername:"enter"event: {myVar}

Scene.update

Update by recalculating scene, tween and pin properties then automatically refreshing the scene. This happens automatically and should only be used when required.

# Update scenemyScene.update()

Scene.refresh

Refresh scene by redrawing tweens and pins. This happens automatically and should only be used when required.

# Refresh scenemyScene.refresh()

Scene.remove

Remove scene from controller.

Parameters:
  • reset – reset scene and all connected tweens and pins
# Remove scene and all connected tweens and pinsmyScene.remove()
# Remove and reset scene and all connected tweens and pinsmyScene.removetrue

Scene.onEvent

Listen for scene events.

Event listeners
# Listen for scene changemyScene.onChangeValue->print"Scene changed"# Listen for scene shiftmyScene.onShift->print"Scene shifted"# Listen for scene updatemyScene.onUpdate->print"Scene updated"# Listen for scene entermyScene.onEnter->print"Scene entered"# Listen for scene startmyScene.onStart->print"Scene started"# Listen for scene progressmyScene.onProgress->print"Scene progressed"# Listen for scene endmyScene.onEnd->print"Scene ended"# Listen for scene leavemyScene.onLeave->print"Scene left"
Event listeners with callbacks
# Listen for scene change with callbackmyScene.onChangeValue (event, instance) ->print"Scene changed"print"Event: #{event.property}, #{event.value}"# Listen for scene shift with callbackmyScene.onShift (event, instance) ->print"Scene shifted"print"Event: #{event.reason}"# Listen for scene update with callbackmyScene.onUpdate (event, instance) ->print"Scene updated"print"Event: #{event.start}, #{event.end}, #{event.scrollPos}"# Listen for scene enter with callbackmyScene.onEnter (event, instance) ->print"Scene entered"print"Event: #{event.progress}, #{event.state}, #{event.scrollDir}"# Listen for scene start with callbackmyScene.onStart (event, instance) ->print"Scene started"print"Event: #{event.progress}, #{event.state}, #{event.scrollDir}"# Listen for scene progress with callbackmyScene.onProgress (event, instance) ->print"Scene progressed"print"Event: #{event.progress}, #{event.state}, #{event.scrollDir}"# Listen for scene end with callbackmyScene.onEnd (event, instance) ->print"Scene ended"print"Event: #{event.progress}, #{event.state}, #{event.scrollDir}"# Listen for scene leave with callbackmyScene.onLeave (event, instance) ->print"Scene left"print"Event: #{event.progress}, #{event.state}, #{event.scrollDir}"

Tween

The tween defines what happens in a scene by animating a defined layer (triggerLayer by default) between states defined by from and/or to properties. The tween will start its animation (with its defined animation options) when its scene starts or it will modulate based on scroll progress between from and to when its scene starts until it ends if the scene has a duration. Multiple tweens can be added on the same layer with the same properties if their scenes are defined in succession and the tweens define both from and to properties and disable their initialisation.

PropertyTypeDefaultDescription
Tween.sourceObjectScrollComponentGet tween ScrollComponent
Tween.controllerObjectControllerGet tween controller
Tween.sceneObjectSceneGet tween scene
Tween.nameString"."Get/Set tween name
Tween.layerObjectScene.triggerLayerGet tween layer
Tween.fromObject-Get tween from properties
Tween.toObject-Get tween to properties
Tween.optionsObjectFramer.Defaults.AnimationGet tween animation options
Tween.initBooleantrueGet tween animation initialisation state
Tween.enabledBooleantrueGet/Set tween enabled state
Tween.removeMethod-Remove tween

Tween.remove

Remove tween from scene.

Parameters:
  • reset – reset tween
# Remove tweenmyTween.remove()
# Remove and reset tweenmyTween.removetrue

Pin

The pin defines what happens in a scene by pinning a defined layer (triggerLayer by default). The pin will pin its layer when its scene starts and unpins its layer when its scene ends if the scene has a duration. Multiple pins can be added on the same layer in the same direction if their scenes are defined in succession.

PropertyTypeDefaultDescription
Pin.sourceObjectScrollComponentGet pin ScrollComponent
Pin.controllerObjectControllerGet pin controller
Pin.sceneObjectSceneGet pin scene
Pin.nameString"."Get/Set pin name
Pin.layerLayerScene.triggerLayerGet pin layer
Pin.enabledBooleantrueGet/Set pin enabled state
Pin.stateString"pinned" or "unpinned"Get pin state
Pin.removeMethod-Remove pin

Pin.remove

Remove pin from scene.

Parameters:
  • reset – reset pin
# Remove pinmyPin.remove()
# Remove and reset pinmyPin.removetrue

Known limitations

  • It is not recommended to use ScrollController for “clicky” mousewheel scrolling due to the nature of its scrolling behavior.
  • Overlapping pins on the same layer in the same direction is not supported, use successive pinning instead.
  • Overlapping tweens on the same layer with the same properties is not supported, use successive tweening instead and define from, to and init: false for all but the first tween.
  • Removing tweens on a layer with remaining tweens is not supported.

Releases

  • v1.0.1 - Minor optimisations
  • v1.0.0 - Initial release

License

This project is licensed under the MIT license.

Author

Developed by Jesper Bentzen.

Star this repository if you like it, and if you find that this plugin somehow saves your day, then consider buying me a coffee via PayPal. It will surely help motivate me to further support this module. :)

Acknowledgement

A special thank you to @janpaepke for creating ScrollMagic which helped guide the approach used in this module. Also thank you to the entire Framer Slack community and especially @steveruizok and @marckrenn for sharing their thoughts and hard work to study and build upon.

About

ScrollController is a Framer module that helps you to animate, pin and trigger events based on scroll position.

Topics

Resources

Stars

19 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages