Skip to main content

Custom (Browser) Clips

Intro

There might be cases that the “native” HTMLClip exposed by MC is not good enough to serve your Plugin’s special needs. For example Clips that use webGL or canvas or anything else that can not be represented as just HTML and CSS or Clips that do very specific things and accept tailored made Effects (e.g. a map clip that will accept pan and zoom effects).

In such cases the developer needs to extend the BrowserClip and create new types of Clips that on initialisation they render whatever needs to be rendered and define custom entities kept in their context so they can be later accessed via selectors from (also) custom Effects.

For example, let's suppose that we want to create a Clip that takes on its attributes an object that defines a number of circles and rectangles to be rendered, renders them on a canvas and exposes them via selectors so they can be targeted by Effects which will be able to change their looks and position.

Import {BrowserClip} from "@donkeyclip/motorcortex";

class MyCustomClip extends BrowserClip {
// overwrite afterRender method
afterRender(){
// create a canvas
const ctx = this.context.document.createElement('canvas');

// draw all rects and circles in it. Here you have full access to the attributes passed to your Clip on initialization via the “this.attrs” property
...

// store each of the rects and circles as custom entities via the “setCustomEntity” method provided. The setCurstomEntity method accepts exactly three arguments: the id of the custom element, the custom element itself, optionally an array of the classes the element belongs to
this.setCustomEntity('myRect_1', myRectObject, ['class1', 'class2'];

// put the canvas on the Clip's DOM. this.context.rootElement always refers to the root HTML element of you Clip, which can host whatever an HTML element can host
this.context.rootElement.appendChild(ctx);
}
}

How to think / mind the portability

The type of elements that your Clip supports (rectangles and circles in our example, a map or a video in another example etc) is up to the plugin developer to decide. In general, the way to think is the following:

  1. Decide on what your Custom Clip will render and what Effects it will support
  2. Decide on the entities that your Clip will expose via selectors so they can be accessed via Effects
  3. Develop your Clip so it accepts attributes that:
    • Define the number, types and characteristics of the entities to be renderd along with any other information your Clip needs in order to render properly (e.g. map center, colors or any other relative information)
    • Can be exported to JSON (no references to Classe instances nor anything else that can not be stored as JSON). Don’t forget, here you are developing a custom MotorCortex Clip and in MotorCortex all Clips (even the custom ones) must always be: playable, dynamic, parametric, isolated and portable. By extending BrowserClip MC makes sure all these specs are met except the portability. This should be guaranteed by you by designing your Clip to accept attrs that can be stored (and transferred) in JSON format.
  4. Extend the BrowserClip Class to create your own Custom Clip
  5. Overwrite the afterRender method of it so you can: a. Render your Clip (e.g. create and append a canvas, a map or anything else on your rootElement b. Store all of your custom entities so they can be accessed via selectors by Effects (which you can develop later)

onAfterRender

The method to overwrite is onAfterRender. That’s where you should put all of your rendering logic and create your custom elements.

The name “onAfterRender” refers to the host of your Clip. At this point your host, rootElement (can be accessed by this.context.rootElement) is a DIV that will host your entire Clip. At this point, this host is already rendered on the DOM so you can work with it as you would work with any other DIV of a DOM.

Setting custom entities

On onAfterRender method you can define and store custom entities in your context so it can later be accessed by Effects’ selectors. The concept is straightforward:

  • Each entity must have a unique id
  • Each entity can belong to a number of different classes

You can store as entities literally anything you want. A map object, an svg element, a rectangle on a canvas, a 3d light, anything.

As each custom entity has an id and can belong to a number of classes, Effects can access them via selectors that extremely similar with plain CSS selectors (# and .). Only this time you need to add the “!” character in front of the selector to indicate that you target a custom entity.

Examples

  • !#idX: targets the custom entity with id === “idX”
  • !.classX: targets all custom entities that belong to the class .classX But how exactly do you define your custom entities? Via the “setCustomEntity” method of BrowserClip.

setCustomEntity method takes exactly three arguments:

  1. The id of the entity (must be unique among all custom entities)
  2. The entity itself
  3. Optionally an array of strings defining the classes it belongs to

Custom Effects

Once you design your plugin, decide on its functionality, render and store its custom entities it’s time to create your custom Effects that will affect your custom entities. Developing a custom Effect tailor made for your own custom entities is as simple as developing any other Effect. Just extend the MotorCortex.Effect class and do exactly what you you do with a simple Effect. The only difference with the simple Effect is that this.element now refers to the custom entity and not to an HTML Element. The rest of the Effect operates in the exact same way it does on the simple case.

All of your Effects can be directly added to your custom Clip in the obvious way (clip.addIncident(effect, millisecond)), can be used with combos, and in general do not differ at all from common Effects except that they accept “!” selectors (for custom entities).