How to animate notations on scroll using RoughNotation.js in Bricks

How to animate notations on scroll using RoughNotation.js in Bricks

This tutorial provides the PHP & JS codes that can be pasted in order to animate notations on scroll using the RoughNotation library inside the Bricks Builder.

Table of Contents

Requirements

The JavaScript

First of all, let’s create our init.js file inside our child theme. In this example, I created a roughNotation_init.js file inside my /js/ folder and added the following code to it:

import { annotate } from 'https://unpkg.com/rough-notation?module';
window.addEventListener('load', () =>{
    const annotations = {
        'highlight-1': { type: 'highlight', color: '#fcc2d2', iterations: 4, multiline: true, animate: true },
        'highlight-2': { type: 'highlight', color: 'orange', iterations: 4, multiline: true, animate: true },
        'underline': { type: 'underline', color: 'yellow', iterations: 4, multiline: true, animate: true },
        'box': { type: 'box', color: 'purple', iterations: 2, multiline: true, animate: true },
        'circle': { type: 'circle', color: 'green', iterations: 1, multiline: true, animate: true },
        'strike-through': { type: 'strike-through', color: 'red', iterations: 1, multiline: true, animate: true },
        'crossed-off': { type: 'crossed-off', color: 'black', iterations: 2, multiline: true, animate: true },
        'bracket': { type: 'bracket', brackets: ['left','right'], color: 'blue', iterations: 2, multiline: true, animate: true },
    };  
    // Set the variables
    var iOSupported = "IntersectionObserver" in window; /* true if supported */
    var box = document.querySelectorAll('.notation');
    
    // Check if IntersectionObserver is supported by the browser
    if (!iOSupported) {
        return;
    }

    // Set the config options 
    const config = {
        root: null, // sets the framing element to the viewport
        rootMargin: '0% 0% -25% 0%', // the animation will be triggered when at 25% from the bottom of the viewport
        threshold: 0 
    };
    
    // Init the observer
    let observer = new IntersectionObserver((entries) => {
        entries.forEach((item) => {
            let annotationType = item.target.dataset.notationType;
            let annotation = annotate(item.target, annotations[annotationType]);
        
            if (item.isIntersecting) {
                // Show the annotation when intersecting and stop observing after it.
                annotation.show();
                observer.unobserve(item.target);

            } else {
                // Add an action when the target is not intersecting anymore.

            }    
        });  
    }, config);


    box.forEach((item) => {
        observer.observe(item);
    });
})

There are two different sections in the script:

  • the first one is dedicated to creating an object with all our different animation styles. There are a lot of different options you can add such as type, color, iterations, padding, etc. For a complete list of the options available, check the author’s page. To show an overview of all the available types of notations, I created the following list of animations:
const annotations = {
        'highlight-1': { type: 'highlight', color: '#fcc2d2', iterations: 4, multiline: true, animate: true },
        'highlight-2': { type: 'highlight', color: 'orange', iterations: 4, multiline: true, animate: true },
        'underline': { type: 'underline', color: 'yellow', iterations: 4, multiline: true, animate: true },
        'box': { type: 'box', color: 'purple', iterations: 2, multiline: true, animate: true },
        'circle': { type: 'circle', color: 'green', iterations: 1, multiline: true, animate: true },
        'strike-through': { type: 'strike-through', color: 'red', iterations: 1, multiline: true, animate: true },
        'crossed-off': { type: 'crossed-off', color: 'black', iterations: 2, multiline: true, animate: true },
        'bracket': { type: 'bracket', brackets: ['left','right'], color: 'blue', iterations: 2, multiline: true, animate: true },
};
  • the second part of the script is dedicated to triggering our animations on scroll. We are using the intersectionObserver API to keep things super lightweight, as described in this tutorial:
// Set the variables
    var iOSupported = "IntersectionObserver" in window; /* true if supported */
    var box = document.querySelectorAll('.notation');
    
    // Check if IntersectionObserver is supported by the browser
    if (!iOSupported) {
        return;
    }

    // Set the config options 
    const config = {
        root: null, // sets the framing element to the viewport
        rootMargin: '0% 0% -25% 0%', // the animation will be triggered when at 25% from the bottom of the viewport
        threshold: 0 
    };
    
    // Init the observer
    let observer = new IntersectionObserver((entries) => {
        entries.forEach((item) => {
            let annotationType = item.target.dataset.notationType;
            let annotation = annotate(item.target, annotations[annotationType]);
        
            if (item.isIntersecting) {
                // Show the annotation when intersecting and stop observing after it.
                annotation.show();
                observer.unobserve(item.target);

            } else {
                // Add an action when the target is not intersecting anymore.

            }      
        });     
    }, config);


    box.forEach((item) => {
        observer.observe(item);
    });

Enqueue the script

Since the RoughNotation library is using a javascript module, the enqueue process is slightly trickier than usual. Paste the following code inside the functions.php file of your child theme in order to add type="module" to the script tag:

add_action( 'wp_enqueue_scripts', function() {
	// Enqueue your files on the canvas & frontend, not the builder panel. Otherwise custom CSS might affect builder)
   if ( ! bricks_is_builder_main() && class_exists( 'ACF' ) ) {
  
      // Rough Notation
      if ( get_field( 'activate_roughnotationjs' ) ) {
    	    wp_enqueue_script( 'roughNotation_init', get_stylesheet_directory_uri() . '/js/roughNotation_init.js', array(), filemtime( get_stylesheet_directory() . '/js/roughNotation_init.js' ) );
      }
   }
});

// Add type="module" to our script tag
function add_type_attribute( $tag, $handle, $src ) {
    // if not your script, do nothing and return original $tag
    if ( 'roughNotation_init' !== $handle ) {
        return $tag;
    }
    // change the script tag by adding type="module" and return it.
    $tag = '<script type="module" src="' . esc_url( $src ) . '"></script>';
    return $tag;
}
add_filter( 'script_loader_tag', 'add_type_attribute' , 10, 3 );

Note that we are using an ACF field to conditionally enqueue the script on each page as described in this tutorial.

The HTML code

Typically we want to target a portion of text inside a Heading, a Basic, or a Rich Element in Bricks. To do that, we’ll need to wrap the content inside a <span> tag, add a specific class that will trigger the animation on scroll, and specify which type of animation we want to run. Here is an example of how to apply the highlight effect to our header:

I am an awesome <span class="notation" data-notation-type="highlight-1">heading</span>
  • The class .notation will trigger the intersectionObserver API script
  • the data-attribute data-notation-type with value highlight-1 will be used by our script to animate the highlight-1 object we set previously in our annotations constant.

Note that if you plan to annotate a full element rather than a portion of it, you don’t need to wrap your content in a <span> tag. In this case, you could just use the Bricks in-built fields to add the .notation class and the data-notation-type data-attribute.

Conclusion

If everything works as expected, here is the result you should see on frontend:

Happy notations and see you soon for the next tutorial!

Get access to all 524 Bricks code tutorials with BricksLabs Pro

3 comments

  • Many thanks Maxime. This is really great and so easy to use together with ACF.

  • What if I want to use WPCodeBox instead of child theme etc..?

    • Maxime Beguin

      Hey Kareem, I don’t own WPCodeBox so I can’t give you much details about it - but you should be able to add the files separately to it and enqueue the files directly in WPCodeBox. You’ll have have to substitute the WordPress enqueue logic with the WPCodeBox logic (which I don’t know) but the JavaScript code and the bricks settings are the same.

Leave your comment

 

Related Tutorials..

GSAP in Bricks: a concrete example

GSAP in Bricks: a concrete example

In this tutorial, we're going to create a custom timeline with different popular GSAP animations and integrate it into the Bricks Builder. Introduction We released…
Categories:
Pro
Stacking Post Cards in Bricks

Stacking Post Cards in Bricks

How we can stack posts in a query loop so they stick on top of the previous one when scrolling.
Categories:
Tags:
How to populate a map with dynamic markers from a CPT using ACF in Bricks (PART 2)

How to populate a map with dynamic markers from a CPT using ACF in Bricks (PART 2)

This tutorial provides the PHP & JS codes that can be pasted in order to create a flying effect on map markers each time your…
How to integrate fullPage.js with Bricks

How to integrate fullPage.js with Bricks

This tutorial provides the JavaScript and CSS codes that can be pasted in order to integrate the JS library fullPage.js inside Bricks Builder.
Categories:
Introduction to GSAP in Bricks

Introduction to GSAP in Bricks

In this tutorial, we'll learn how to run basic GSAP animations inside the Bricks Builder using JSON objects inside specific data-attributes. Introduction Not everyone like…
Categories:
Custom Animations on Scroll without plugins in Bricks

Custom Animations on Scroll without plugins in Bricks

This tutorial provides the Javascript and CSS codes that can be pasted in order to create custom CSS animations on scroll without any third-party plugins…
Categories:
Pro
Horizontal Scrolling Sections in Bricks Using GSAP’s ScrollTrigger

Horizontal Scrolling Sections in Bricks Using GSAP’s ScrollTrigger

In this Pro tutorial we'll use GSAP's ScrollTrigger library in Bricks to create a section that will scroll horizontally across a number of full width…