Draggable Animations

In notebook:
FrontEndMasters SVG Animation
Created at:
2016-11-20
Updated:
2016-11-21
Tags:
JavaScript libraries animation
Draggable
  Draggable.create(".box", {type:"x,y", edgeResistance:0.65, 
  bounds:"#container", throwProps:true});
Very easy to create a draggable element. 
  • Device-enabled for touchscreen
  • Impose bounds- containing units or pixel parameters bounds:{top:100, left:0, width:1000, height:800}
  • Momentum: If you have ThrowPropsPlugin you can set throwProps:true
  • Draggable.hitTest() to sense if elements touch eachother (more on this in a moment (there's a gotcha with SVG)
  • Honors transform-origin
  • Still works on transformed elements (like scaled down)
  • Lock movement to an axis lockAxis:true
  • GPU-accelerated (not for SVG) and requestAnimationFrame-driven
  • more
Codepen demo of draggable
An excerpt from the above demo:
  Draggable.create(circ, {
  type: "x,y",
  edgeResistance: 0.5,
  bounds: "#container",
  throwProps: true
});

TweenMax.staggerTo(circ, 3, {
  rotation: 360,
  scale: 0.85,
  repeat: -1,
  yoyo: true,
  transformOrigin: "50% 50%",
  ease: Elastic.easeInOut
}, 0.35);

Rich Callback System and Event Dispatching

Callback: 
  • onPress
  • onDragStart
  • onDrag
  • onDragEnd
  • onRelease
  • onLockAxis
  • onClick
​this​ refers to the draggable element itself 

You can also use event listeners: 
yourDraggable.addEventListener("dragend", yourFunc);
A GSAP Codepen
  var droppables = $('.box');
// You can specify any percentage
var overlapThreshold = "50%";


//we'll call onDrop() when a Draggable is dropped on top of one of the "droppables"
function onDrop(dragged, dropped) {
  TweenMax.fromTo(dropped, 0.1, {opacity:1}, {opacity:0, repeat:3, yoyo:true});
}

Draggable.create(droppables, {
  bounds:window,
  onDrag: function(e) {
    var i = droppables.length;
		 while (--i > -1) {
		  // this where we chack for overlap
		  // the most important part of the code:
       if (this.hitTest(droppables[i], overlapThreshold)) {
         $(droppables[i]).addClass("highlight");
       } else {
        // for this, you need jQuery 3.0 (operate on SVG)
         $(droppables[i]).removeClass("highlight");
       }
    }
  },
  onDragEnd:function(e) {
		var i = droppables.length;
		while (--i > -1) {
		  // this is important:
			if (this.hitTest(droppables[i], overlapThreshold)) {
				onDrop(this.target, droppables[i]);
			}
		}
	}
});
You can also set draggable to rotation (like 360º)! Codepen 
She's controlling an animations timeline with draggable rotation:
  TweenMax.set($("#flowers1, #radio, #burst, #magnolia, #flowers2, #starfish, #berries1, #berries2, #berries3, #skulls, #tv, #glitch, #shadow, #lights"), {
  visibility: "visible"
});

// the first scene
function sceneOne() {
  var tl = new TimelineMax();

  tl.add("start");
  tl.staggerFromTo($f1, 0.3, {
    scale: 0
  }, {
    scale: 1,
    ease: Back.easeOut
  }, 0.05, "start");
  ...
  
  return tl;
}

// note: paused:true, so that the animation doesn't start
var master = new TimelineMax({paused:true});
master.add(sceneOne(), "scene1");
Note: you don't need jQuery to use GSAP. 

SVGOrigin

This a GSAP thing. You can use it to do responsive designs.

​hitTest()​ and SVG

The problem here is that the DOM doesn't see the paths inside an SVG but treats it as one big rectangle. So the bounds are a box. 

Extra: ​clipPath

This is to crop the SVG with a shape (the output is from Illustrator, so not very clean):
  <defs>
  <ellipse id="SVGID_3_" class="st2" cx="276" cy="147" rx="272" ry="147"/>
</defs>

<clipPath id="SVGID_4_">
  <use xlink:href="#SVGID_3_" />
</clipPath>
  .st4 { 
  clip-path: url(#SVGID_4_); 
}
A better code:
  <defs>
  <clipPath id="clippy">
    <ellipse cx="276" cy="147" rx="272" ry="147"/>
  </clipPath>
</defs>
  .img { 
  clip-path: url(#clippy); 
}
She's using an SVG element to the clipping. 

Support with CSS clip-path is very bad.
You can also animate clip-paths.