Implement a draggable element with inertia

351 views Asked by At

I've just stumbled upon the new famous 0.5 release and things seem to be quite different (looking good). I want to implement a draggable element with inertia, but I can't figure it out by looking at the new docs.

Can anyone give me some tip on how to do this?

1

There are 1 answers

0
talves On

Here is a simple example of using the GestureHandler to track the start, move and end of a drag in the famous engine. The Position component will place our node with respect to the delta of our drag event. Notice how the node is passed to the GestureHandler to track our drag events.

Warning: As of this posting, the engine is still in Beta (0.5.2), so there is an edge case issue with trying to drag too close to the outside of the element. It may have to do with the default interval of render updates.

var rootScene = FamousEngine.createScene('body');
var rootNode = rootScene.addChild();
rootNode.setAlign(0.5, 0.5);

function Draggable(root) {
  this.node = root;
  this.node
    .setProportionalSize(0.5, 0.5)
    .setMountPoint(0.5, 0.5);

  this.position = new Position(this.node);
  console.log(this.position);

  var base = (Math.random() * 360) | 0;

  this.el = new DOMElement(this.node, {
    properties: {
      'textAlign': 'center',
      'color': 'white',
      'fontSize': '30px',
      'lineHeight': '40px',
      'background': 'hsl(' + ((base += 37) % 360) + ',40%,50%)',
      'cursor': 'pointer'
    }
  });

  this.el.setContent('Drag Me');

  var gestures = new GestureHandler(this.node, [{
    event: 'drag',
    callback: drag.bind(this)
  }]);

  function drag(e) {
    //console.log('drag', e.status, e);
    switch (e.status) {
      case 'start':
        console.log('start drag', this.position.getValue());
        break;
      case 'end':
        console.log('end drag', this.position.getValue());
        break;
      case 'move':
        var d = e.centerDelta;

        console.log('move drag', this.position.getValue(), d);
        var pos = this.position.getValue();
        this.position.set(pos.x + d.x, pos.y + d.y, pos.z);
        break;
    }
  }
}

var dragger = new Draggable(rootNode);
FamousEngine.init();

Run the snippet example

var DOMElement = famous.domRenderables.DOMElement;
var Position = famous.components.Position;
var FamousEngine = famous.core.FamousEngine;
var GestureHandler = famous.components.GestureHandler;

var rootScene = FamousEngine.createScene('body');
var rootNode = rootScene.addChild();
rootNode.setAlign(0.5, 0.5);

function Draggable(root) {
  this.node = root;
  this.node
    .setProportionalSize(0.5, 0.5)
    .setMountPoint(0.5, 0.5);

  this.position = new Position(this.node);
  console.log(this.position);

  var base = (Math.random() * 360) | 0;

  this.el = new DOMElement(this.node, {
    properties: {
      'textAlign': 'center',
      'color': 'white',
      'fontSize': '30px',
      'lineHeight': '40px',
      'background': 'hsl(' + ((base += 37) % 360) + ',40%,50%)',
      'cursor': 'pointer'
    }
  });

  this.el.setContent('Drag Me<hr>');

  var gestures = new GestureHandler(this.node, [{
    event: 'drag',
    callback: drag.bind(this)
  }]);

  function drag(e) {
    //console.log('drag', e.status, e);
    switch (e.status) {
      case 'start':
        console.log('start drag', this.position.getValue());
        break;
      case 'end':
        console.log('end drag', this.position.getValue());
        break;
      case 'move':
        var d = e.centerDelta;

        console.log('move drag', this.position.getValue(), d);
        var pos = this.position.getValue();
        this.position.set(pos.x + d.x, pos.y + d.y, pos.z);
        break;
    }
  }
}

var dragger = new Draggable(rootNode);
FamousEngine.init();
html,
  body {
    width: 100%;
    height: 100%;
    margin: 0px;
    padding: 0px;
  }
  body {
    position: absolute;
    -webkit-transform-style: preserve-3d;
    transform-style: preserve-3d;
    -webkit-font-smoothing: antialiased;
    -webkit-tap-highlight-color: transparent;
    -webkit-perspective: 0;
    perspective: none;
    overflow: hidden;
  }
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="icon" href="favicon.ico?v=1" type="image/x-icon">
<meta name="description" content="Draggable [email protected]">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="http://code.famo.us/famous/0.5.2/famous.min.js"></script>