Scripted natural motion with react-beautiful-dnd
Tags: react, rbd
Published: 2019-10-28 23:00:46

---
title: Scripted natural motion with react-beautiful-dnd
published: true
description: Using the fluidLift method of react-beautiful-dnd to programmatically perform drag and drop
tags: react, rbd
cover_image: https://images.unsplash.com/photo-1488188840666-e2308741a62f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2253&q=80
---

React-beautiful-dnd `v12` ships with a [Sensor API](https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/sensors/sensor-api.md#sensor-api-) that allows us to control the drag and drop actions programmatically. This is going to open up a [wide range of possibilities](https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/sensors/sensor-api.md#examples). We can programmatically move a draggable using either a [`snap dragging`](https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/sensors/sensor-api.md#snap-dragging) or a [`fluid dragging`](https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/sensors/sensor-api.md#fluid-dragging).

This blog post goes into the details of how to perform good looking fluid drags using the new `fluidLift` method. 

The `fluidLift` method would allow us to create beautiful scripted experiences without user interaction. For example, a trip planner app, as shown below, could provide an interactive onboarding experience using the new `fluidLift` method by showing the user how to plan a trip.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/c2haakc513cjqwsg379s.gif)


## Take full control of draggable using fluid dragging

The `fluidLift` method allows us to freely move a draggable to a new position by providing a coordinate.

Let's say if we want to move a draggable from it's initial position to a new position with the coordinate 400, 500, we could call the `.move()` method with `{ x: 400, y: 500 }` as the argument as shown below.

```javascript
 function useMyCoolSensor(api) {
    const startDrag = function start() {
      const preDrag = api.tryGetLock("my-draggable-item");
      if (!preDrag) {
        return;
      }
     
      const drag = preDrag.fluidLift({ x: 0, y: 0 });
      const end = { x: 400, y: 500 };
      drag.move(end);
      drag.drop()
    };
  }
```

This will make our draggable move to the new position. In the illustration below, you might have noticed that the box jumps from its initial position to its target position.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/zccdyoeurm3fmummpc2q.gif)

## Making the motion natural

In order to achieve a more natural motion, we have to tell react-beautiful-dnd to move the draggable element coordinate by coordinate through time towards the target position.

So instead of calling the `.move()` just once, we are going to call it multiple times with multiple coordinates which lies between the start coordinate and the end coordinate so the drag motion would be more natural.

To create the coordinates between the start and the end coordinates, we are going to use a helper library called [tween-functions](https://github.com/chenglou/tween-functions). The API of the tween-functions library goes as below.

```javascript
tweenFunction.tweenName(currentTime, beginValue, endValue, totalDuration)
```

Let's go ahead and generate 20 points between the start position and the end position and then call the `.move()` method with our new set of coordinates in  `requestAnimationFrame`. 

```javascript
import * as tweenFunctions from "tween-functions";

function useMyCoolSensor(api) {
    const startDrag = function start() {
      const preDrag = api.tryGetLock("my-draggable-item");
      if (!preDrag) {
        return;
      }

      const start = { x: 0, y: 0 };
      const end= { x: 400, y: 500 };
      const drag = preDrag.fluidLift(start );

      const points = [];

      // we want to generate 20 points between the start and the end
      const numberOfPoints = 20;

      for (let i = 0; i < numberOfPoints ; i++) {
        points.push({
          x: tweenFunctions.easeOutCirc(i, start.x, end.x, numberOfPoints),
          y: tweenFunctions.easeOutCirc(i, start.y, end.y, numberOfPoints)
        });
      }
      
      moveStepByStep(drag, points);
    };
  }

function moveStepByStep(drag, values) {
  requestAnimationFrame(() => {
    const newPosition = values.shift();
    drag.move(newPosition);

    if (values.length) {
      moveStepByStep(drag, values);
    } else {
      drag.drop();
    }
  });
}
```

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/hr2lqvgadabkz3s3on42.gif)

That looks much better.

Here is the full codesandbox example.
{% codesandbox react-beautiful-dnd-fluid-lift-demo-42x7i %}


The new Sensor API unlocks a vast amount of possibilities. Experiment with it and go build amazing things.