How to change Webflow Animation Properties with JS

After a couple of years needing this feature but never having the time to decrypt and fully understand webflow.js, I was finally able to get some time in a project to dig deep into Webflow.js and understand how someone can change the values of specific parts of a Webflow animation based on any kind of runtime variable, such as window.innerWidth for example

Here’s the Code + Explanation on how to do it:

// Helper function to deep clone an object and keeping it immutable
import cloneDeep from 'lodash.clonedeep';

// Util function to find specific animation actions based on the animation's name
const findAnimation = (animationName: string, ixData: Record<string, any>) => {
    const key = Object.keys(ixData.actionLists).find(k => ixData.actionLists[k].title === animationName);
    return key ? ixData.actionLists[key] : undefined;
};

window.Webflow.push(() => {
  const { store, actions } = window.Webflow.require('ix2');

  // Preparing a new object for new Animation Data
  const newIxData = { ...cloneDeep(store.getState().ixData) };

  // Finding the animation we want to change based on the name that is
  // set in the Webflow Designer -> Animations Tab
  const animationToChange = findAnimation('home-hero-scroll', newIxData);

  /**
   * - Update any values we might need to update.
   * - You will likely want to inspect your webflow.js file or
   *   Webflow's store.state prop to see which values you can/want to
   *   update.
   * - VAR "continuousActionGroups" relates to the breakpoints you set in
   *   Webflow for your animation. Ex: [0%, 100%] for a
   *   scroll-based animation
   * - VAR "actionItems" relates to each change of style you set for an
   *   animation breakpoint in Webflow. Ex: A change of opacity for a
   *   specific element when you're at 50% scroll of a container
   */

  newIxData.actionLists[
    animationToChange['id']
  ].continuousParameterGroups[0].continuousActionGroups[1].actionItems[0].config.xValue = -(window.innerWidth / 3); // Action/Value to update

  // Update the store with the new object
  store.dispatch(actions.rawDataImported(newIxData));

  window.Webflow?.destroy();
  window.Webflow?.ready();
  window.Webflow?.require('ix2').init();
  document.dispatchEvent(new Event('readystatechange'));
});

I hope this helps anyone that needs this kind of control over Webflow Animations

3 Likes

@Jeandcc Thanks for sharing this! How would I target a specific re-initialization of a webflow interaction? Like, let’s say I’m importing content from another page, and then once the content is present I’d like only the specific webflow interaction to run.

Currently I’m re-initializing all interactions:

    $.ajax({
      url: nextPageLink,
      success: function (response) {
        let modalContent = $(response).find(".c-container.cc-overlay");
        let pageTitle = $(response).filter("title").text();
        $(".c-teammember-modal").append(modalContent);
        history.pushState({}, '', nextPageLink);
      },
      complete: function () {

        // re-initiate webflow ix2
		    window.Webflow && window.Webflow.destroy();
   		    window.Webflow && window.Webflow.ready();
    		window.Webflow && window.Webflow.require( 'ix2' ).init();
    		document.dispatchEvent( new Event( 'readystatechange' ) );
      },
    });
  });

Hi @Jeandcc.
Thank you for this. I have some problems getting this to work.
Did you write it in TypeScript? Also how do you import cloneDeep?
Do you put this in the page before closing body tag?

Curious to know more :slight_smile:

Hi!

Indeed built using typescript, inside the context of JavaScript code that gets ‘compiled’ by webpack and hosted with Firebase Hosting. You won’t be able to copy and paste this into the “code areas” of webflow, given it needs a tool like Weback to transform it into a bundle that browsers can understand.

It’s being used in a codebase similar to this one

Clone deep is simply a “node dependency”, something you can add with yarn add ... when you are working with an actual codebase instead of just dropping JS in webflow.