Adapters

Adapters are a simple way to avoid having to provide an object's config (e.g. its props types) and setting up its onValuesChange() listener.

Consider this example:





























 
 
 
 
 
 
 
 
 
 


 
 
 
 
 
 

const project = Theatre.getProject("My project")

const nativeObject = document.createElement("div")
nativeObject.style.cssText = `
  position: absolute;
  left: calc(10vw);
  bottom: 0;
  width: 50px;
  height: 50px;
  transform-origin: center bottom;
  background: #EEE;
`
document.body.appendChild(nativeObject)

const instanceName = "Box"
const timeline = project.getTimeline("Bounce", instanceName)

nativeObject.addEventListener("click", () => {
  timeline.play()
})

// Create an object:
const object = timeline.getObject(
  // The name of the object is "The box":
  "The box",
  // Leave a reference to the native object, which in this case is a div:
  nativeObject,
  // Define the properties of our object
  {
    props: {
      y: {
        type: "number"
      },
      stretch: {
        type: "number"
      }
    }
  }
)

object.onValuesChange(newValues => {
  const div = object.nativeObject
  div.style.transform = `translateY(${-newValues.y}px) scaleY(${
    newValues.stretch
  }) scaleX(${1 / newValues.stretch})`
})

We can simply remove the highlighted lines above and move them into an adapter, making it a bit easier to create more instances of the box object.

This is how our adapter will look like:



 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 











 
 















 


const project = Theatre.getProject("My project")

project.adapters.add({
  // Adapters have unique names:
  name: "MovableAndStretchable",

  // This function returns true if the nativeObject is an html element and
  // has the class "movableAndStretchable. If not, Theatre will look for another
  // adapter to handle this object
  canHandle(nativeObject) {
    return (
      nativeObject instanceof HTMLElement &&
      nativeObject.classList.contains("movableAndStretchable")
    )
  },

  // The config of the object (currently the only configurable aspect is an object's prop types)
  getConfig(nativeObject) {
    return {
      props: {
        x: {
          type: "number"
        },
        y: {
          type: "number"
        },
        stretch: {
          type: "number"
        }
      }
    }
  },

  // This will be called whenever an object that's "handlable" by this adapter is added
  // to any timeline within this project.
  start(object) {
    const unsubscribe = object.onValuesChange(newValues => {
      const div = object.nativeObject
      div.style.transform =
        `translateX(${newValues.x}px) ` +
        `translateY(${-newValues.y}px) ` +
        `scaleY(${newValues.stretch}) ` +
        `scaleX(${1 / newValues.stretch})`
    })

    // we need to return a function that basically "stops" whatever is going on in the "start()" function
    // This will be called if an object or its timeline are taken out of the scene
    return unsubscribe
  }
})

const nativeObject = document.createElement("div")
nativeObject.style.cssText = `
  position: absolute;
  left: calc(10vw);
  bottom: 0;
  width: 50px;
  height: 50px;
  transform-origin: center bottom;
  background: #EEE;
`
// Make this div handlable by the adapter
nativeObject.classList.add("movableAndStretchable")
document.body.appendChild(nativeObject)

const instanceName = "Box"
const timeline = project.getTimeline("Bounce", instanceName)

nativeObject.addEventListener("click", () => {
  timeline.play()
})

// Create an object:
const object = timeline.getObject(
  // The name of the object is "The box":
  "The box",
  // Leave a reference to the native object, which in this case is a div:
  nativeObject
  // note that we do not need to provide a config anymore
)

Now our code will behave exactly as before, but upon creating more instances of "The Box", we won't need to provide any props or set up its onValuesChange() listener.

Now let's go through the different parts of each adapter:

  1. name must be a string unique within this project, in this case "MovableAndStretchable".
  2. canHandle() is a function that takes a native object and returns a boolean. If the returned value is true, Theatre will use this adapter to provide the props of this object and set up its onValuesChange() listener. In this case, we make sure the native object is an HTML element, and it has the movableAndStretchable CSS class.
  3. getConfig() will return the config of the object (its prop types). By setting up getConfig(), you won't need to provide a config argument anymore in timeline.getObject(name, nativeObject, config).
  4. start() gets called every time such an object is added to any timeline within the current project. You're free to perform any task within the start() method, but most commonly you'd set up the onValuesChange() listener. It is also required that the start() function returns a stop() function. The stop function gets called whenever the object is removed from the scene.
Last Updated: 2/6/2019, 8:10:14 PM