Mapping a Behaviour to a Physical Action

In this section, we will get to know how to map a particular behaviour to a physical action.

Muze has a set of Physical Actions mapped to a set of Behaviours. You can override this mapping and/or add your own set of Physical Actions and map them with registered Behaviours. We will learn about registering Behaviours in a different section.

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

How to map Behaviours to Physical Actions?

Whenever we map a behaviour with a physical action, we are letting Muze know how a particular physical action will change the behaviour. Thus, everytime we interact with the chart and cause that particular physical action, the corresponding behavioural action will be triggered.

Let's take an example to see how this would work. Let's make a canvas having a bar chart of Horsepower vs Origin. In this chart, there is a registered physical action called 'ctrlClick' which acts whenever we click on the mouse with the Ctrl button. (To see how we can register such an action, check out registering physical actions here):

main
run-button
run-button
reset-button
          canvas
          	.width(600)
          	.height(400)
			.rows(['Horsepower'])
			.columns(['Origin'])
			.data(dataModelInstance)
    		.mount(node)

In this example, the registered physical action ctrlClick does not have any behaviours mapped to it. As such, there will not be any change in the canvas if we apply the interaction. Thus, we will attach a behaviour with it, such that everytime we Ctrl+Click on a bar in the chart, that behaviour changes, i.e., the bar is selected.

Let us map the select behaviour to the action. We will use the Action Model provided by Muze to do this mapping:

.registerPhysicalBehaviouralMap({
     ctrlClick: {
          behaviours: ['select']
      }
});

Note: We have removed the selection behaviour when you click on the bar. You can checkout how to do that here.

main
run-button
run-button
reset-button
          canvas
          	.width(600)
          	.height(400)
			.rows(['Horsepower'])
			.columns(['Origin'])
			.data(dataModelInstance)
    		.mount(node)
  
    ActionModel
     .for(canvas)
     .dissociateBehaviour(['select', 'click'])
     .registerPhysicalActions({  /* to register the action */ 
     ctrlClick: firebolt => (targetEl, behaviours) => {
          targetEl.on('click', function (data) {
          if (event.metaKey) {
               const event = utils.getEvent();
               const mousePos = utils.getClientPoint(this, event);
               const interactionConfig = {
                   data,
                   getAllPoints: true
               }
               const nearestPoint = firebolt.context.getNearestPoint(mousePos.x, mousePos.y,interactionConfig);
                   behaviours.forEach(behaviour => 
                    firebolt.dispatchBehaviour(behaviour, {
                     criteria: nearestPoint.id, 
                        }));
                      }
                  });
              }
          })
          
           ActionModel
            .registerPhysicalBehaviouralMap({
             ctrlClick: { // name of the physical action
                  behaviours: ['select'] // names of behaviours
              }
        });

In order to map a physical action to the behaviour, we call the registerPhysicalBehaviouralMap method supplied by the Action Model. For every physical action, there can be a set of behavioural actions.

Mapping multiple behaviours to a physical action

We can choose to map multiple behaviours to a certain physical action.

For instance, here we will be mapping the select and highlight behaviours with the ctrlClick physical action by specifying multiple behaviours in the array as shown below:

.registerPhysicalBehaviouralMap({
         ctrlClick: {    /* Mapping multiple behaviours to ctrlClick */
               behaviours: ['select', 'highlight']
          }
});

Now every time the ctrlClick physical action is triggered, the select and highlight behaviours are dispatched:

main
run-button
run-button
reset-button
          canvas
          	.width(600)
          	.height(400)
			.rows(['Horsepower'])
			.columns(['Origin'])
			.data(dataModelInstance)
    		.mount(node)
   
    ActionModel
     .for(canvas)
     .dissociateBehaviour(['select', 'click'])
    .dissociateBehaviour(['highlight', 'hover'])
     .registerPhysicalActions({  /* to register the action */ 
     ctrlClick: firebolt => (targetEl, behaviours) => {
          targetEl.on('click', function (data) {
          if (event.metaKey) {
               const event = utils.getEvent();
               const mousePos = utils.getClientPoint(this, event);
               const interactionConfig = {
                   data,
                   getAllPoints: true
               }
               const nearestPoint = firebolt.context.getNearestPoint(mousePos.x, mousePos.y,interactionConfig);
                   behaviours.forEach(behaviour => 
                    firebolt.dispatchBehaviour(behaviour, {
                     criteria: nearestPoint.id, 
                        }));
                      }
                  });
              }
          })

           ActionModel
            .registerPhysicalBehaviouralMap({
             ctrlClick: { // name of the physical action
                  behaviours: ['select', 'highlight'] // names of behaviours
              }
        });

Wrapping Up

We have a fair idea of how to map physical actions to behaviours. To summarize:

  • A pre-defined physical action is mapped to pre-defined behaviours in Muze
  • You can override this mapping by mapping a certain physical action to a different behaviour and dissociating the existing mapping
  • A newly registered physical action must be mapped in order for it to affect the canvas
  • A physical action can be mapped to a single or several behaviours