Physical Actions

In this section, we will get an in depth idea of what physical actions are and how they work.

Physical Actions in Muze are the basic browser actions that are physically initiated by the user/developer. Any of the predefined actions, like click, hover, keypress or drag are considered as a Physical Actions.

Each physical action has its own target element and a method which triggers the change in the behaviour attached to it. This triggering of behaviour change is called dispatching a behaviour. Let us first understand how the physical action works.

Let's try and understand how this works with the simple cars.json data.

How do Physical Actions Work?

Whenever a physical action is triggered(by the various browser events or user defined events), it retrieves the data set attached to it.

Let us understand what the data set attached to an event refers to by taking the example of a simple bar chart:

main
run-button
run-button
reset-button
loadData('/static/cars.json').then((res) => {    
  let node = document.getElementById('chart-container');    
  const env = muze();    
  const canvas = env.canvas();    
  const DataModel = muze.DataModel;  	
  loadData('/static/cars-schema.json').then((schema) => {
    const dataModelInstance = new DataModel(res, schema);
          canvas
          	.width(600)
          	.height(400)
			.rows(['Miles_per_Gallon'])
			.columns(['Cylinders'])
    		.layers([{
              	mark: 'bar'
            }])
			.data(dataModelInstance)
    		.mount(node)
    });
})

In the example above, we can interact with the chart by either hovering or clicking or brushing on the bars. Let us see what physical actions does when we hover on a certain bar in the chart as can be seen below:

Tooltip

When hovering over the bar, we see a tooltip occur. The data present in the tooltip is generated when the physical action retrieves the information about the event itself. For instance, while hovering in the above example, the physical action determines that the data associated with the event belongs to the Cylinder value of 3.

It then passes this information to the behavioural action to trigger the change in behaviour. This is called dispatching of behaviours.

Let us now see how this execution happens in the code.

Action Behaviour Map

Muze stores the set of pre-defined physical actions along with the behaviours mapped to it.

const actionBehaviourMap = {
         click: {
            behaviours: ['select'],
        }
    }

For instance, as you can see in the object above, a map of the click action with the select behaviour has been created. Thus, whenever a the click action is triggered, the select behaviour gets triggered.

An action can have multiple behaviours attached to it as you can see below:

const actionBehaviourMap = {
         click: {
            behaviours: ['select', 'crossline'],
        }
    }

Both select and crossline are examples of behaviours. Read more about behaviours here.

For now, let us understand what does a physical action actually do before it can initiate a change in behaviour.

Physical Action Payload

It is the responsibility of each physical action to generate a payload attached to that event. This payload contains the criteria based on which the behaviour has to be dispatched and an optional position config specifying where in the visualization the interaction has occurred, i.e., the (x,y) position. This position might be useful in creating additional reactions to a particular action but it is not necessary to provide unless required.

For example, if the criteria for a particular action has to contain the Origin 'Japan' and Cylinder values → 3, 6 and 8, then the criteria and the payload will look like this:

payload: {
        criteria: {
            Origin: ['Japan'],
            Cylinders: [3, 6, 8]
        }
    }

The objective of the physical action is to create this criteria and dispatch the behaviour attached to it. In order to create this criteria, the action retrieves the data attached to the point(s) in the visualization where the interaction takes place.

This data is retrieved by converting the pixel value of the point where the interaction takes place to an actual row(s) in the DataModel.

In addition to that, the action also retains the position for further use.

The physical action is not directly related to any interaction. It just acts as a mediator between the actual event and the expected result from that event. The actual result of a particular action is triggered by the behaviour(s) dispatched by it.

Dispatching Behaviour

Finally, the physical action needs to dispatch the behaviours attached to it. Dispatching a behaviour triggers a behavioural action, i.e., it causes the canvas to react to the physical action.

It uses Muze's Firebolt to dispatch the behaviours attached to it: and providing the generated payload as seen in the code below:

 behaviours.forEach(behaviour => firebolt.dispatchBehaviour(behaviour, payload));

Once the behaviour(s) receive the payload, they execute their respective behavioural actions. If you want to understand how behaviours work, read here.

Wrapping Up

To summarize:

  • A Physical Action is triggered everytime an event occurs
  • It creates a payload with a criteria based on the set of data attached to that event
  • It then dispatches the behaviour attached to it with that respective payload
  • The behaviour attached to every physical action is stored in the actionBehaviourMap