YUI 3.x Home -

YUI Library Examples: Drag & Drop: Animated Drop Targets

Drag & Drop: Animated Drop Targets

This example will show you how to make an animated node a Drop target.

Setting up the HTML

First we will create our HTML.

  1. <div id="dock"></div>
  2. <div id="drag">Drag #1</div>
  3. <div id="anim1" class="anim">Anim #1</div>
  4. <div id="anim2" class="anim">Anim #2</div>
  5. <div id="anim3" class="anim">Anim #3</div>
  6. <div id="anim4" class="anim">Anim #4</div>
  7. <div id="anim5" class="anim">Anim #5</div>
<div id="dock"></div>
<div id="drag">Drag #1</div>
<div id="anim1" class="anim">Anim #1</div>
<div id="anim2" class="anim">Anim #2</div>
<div id="anim3" class="anim">Anim #3</div>
<div id="anim4" class="anim">Anim #4</div>
<div id="anim5" class="anim">Anim #5</div>

Now we give that HTML some CSS to make it visible.

  1. .anim {
  2. position: relative;
  3. height: 50px;
  4. width: 100px;
  5. border: 1px solid black;
  6. background-color: #00B8BF;
  7. top: 100px;
  8. }
  9. #drag {
  10. height: 50px;
  11. width: 50px;
  12. border: 1px solid black;
  13. background-color: #004C6D;
  14. color: white;
  15. cursor: move;
  16. z-index: 5;
  17. }
  18. #dock {
  19. height: 600px;
  20. width: 75px;
  21. background-color: #D00050;
  22. border: 1px solid black;
  23. position: absolute;
  24. top: 5px;
  25. right: 0px;
  26. }
  27. .anim.yui-dd-drop-over {
  28. background-color: #EDFF9F;
  29. }
  30. .anim.done {
  31. background-color: white;
  32. }
  33. #drag1.yui-dd-drag-over {
  34. opacity: .5;
  35. filter: alpha(opacity=50);
  36. }
.anim {
    position: relative;
    height: 50px;
    width: 100px;
    border: 1px solid black;
    background-color: #00B8BF;
    top: 100px;
}
#drag {
    height: 50px;
    width: 50px;
    border: 1px solid black;
    background-color: #004C6D;
    color: white;
    cursor: move;
    z-index: 5;
}
#dock {
    height: 600px;
    width: 75px;
    background-color: #D00050;
    border: 1px solid black;
    position: absolute;
    top: 5px;
    right: 0px;
}
.anim.yui-dd-drop-over {
    background-color: #EDFF9F;
}
.anim.done {
    background-color: white;
}
#drag1.yui-dd-drag-over {
    opacity: .5;
    filter: alpha(opacity=50);
}

Setting up the YUI Instance

Now we need to create our YUI instance and tell it to load the dd-drop, dd-plugin, dd-drop-plugin and anim modules.

  1. YUI().use('dd-drop', 'anim', 'dd-plugin', 'dd-drop-plugin');
YUI().use('dd-drop', 'anim', 'dd-plugin', 'dd-drop-plugin');

Making the Node draggable

Now that we have a YUI instance with the modules loaded, we need to instantiate the Drag instance on this Node.

In this example we will be using Node plugins to accomplish our tasks.

  1. YUI().use('dd-drop', 'anim', 'dd-plugin', 'dd-drop-plugin', function(Y) {
  2. //Get the node #drag
  3. var d = Y.Node.get('#drag');
  4. d.plug(Y.Plugin.Drag, { dragMode: 'intersect' });
  5. });
YUI().use('dd-drop', 'anim', 'dd-plugin', 'dd-drop-plugin', function(Y) {
    //Get the node #drag
    var d = Y.Node.get('#drag');
    d.plug(Y.Plugin.Drag, { dragMode: 'intersect' });
});

Animating the Nodes

Now we will setup the Animation sequence that we want to run.

  1. //Get all the div's with the class anim
  2. var anims = Y.Node.all('div.anim');
  3. var counter = 0;
  4. anims.each(function(v, k, items) {
  5. //Get a reference to the Node instance
  6. var a = v;
  7. counter++;
  8. //Add the FX plugin
  9. a.plug(Y.Plugin.NodeFX);
  10. //Add the Drop plugin
  11. a.plug(Y.Plugin.Drop);
  12.  
  13. //Set the attributes on the animation
  14. a.fx.setAttrs({
  15. from: {
  16. left: 0
  17. },
  18. to: {
  19. curve: function() {
  20. var points = [],
  21. n = 10;
  22.  
  23. for (var i = 0; i < n; ++i) {
  24. points.push([
  25. Math.floor(Math.random()*Y.DOM.winWidth() - 60 - a.get('offsetWidth')),
  26. Math.floor(Math.random()*Y.DOM.winHeight() - a.get('offsetHeight'))
  27. ]);
  28. }
  29. return points;
  30. }
  31. },
  32. //Do the animation 20 times
  33. iterations: 20,
  34. //Alternate it so it "bounces" across the screen
  35. direction: 'alternate',
  36. //Give all of them a different duration so we get different speeds.
  37. duration: ((counter * 1.75) + 1)
  38. });
  39. });
    //Get all the div's with the class anim
    var anims = Y.Node.all('div.anim');
    var counter = 0;
    anims.each(function(v, k, items) {
        //Get a reference to the Node instance
        var a = v; 
        counter++;
        //Add the FX plugin
        a.plug(Y.Plugin.NodeFX);
        //Add the Drop plugin
        a.plug(Y.Plugin.Drop);
 
        //Set the attributes on the animation
        a.fx.setAttrs({
            from: {
                left: 0
            },
            to: {
                curve: function() {
                    var points = [],
                        n = 10;
 
                    for (var i = 0; i < n; ++i) {
                        points.push([
                            Math.floor(Math.random()*Y.DOM.winWidth() - 60 - a.get('offsetWidth')),
                            Math.floor(Math.random()*Y.DOM.winHeight() - a.get('offsetHeight'))
                        ]);
                    }
                    return points;
                }
            },
            //Do the animation 20 times
            iterations: 20,
            //Alternate it so it "bounces" across the screen
            direction: 'alternate',
            //Give all of them a different duration so we get different speeds.
            duration: ((counter * 1.75) + 1)
        });
    });

Making the Node A Target

Using the dd-drop-plugin, we now need to make this animated Node a Drop Target.

To do that, we need to add the plugin after the fx plugin.

  1. //Add the FX plugin
  2. a.plug(Y.Plugin.NodeFX);
  3. //Add the Drop plugin
  4. a.plug(Y.Plugin.Drop);
//Add the FX plugin
a.plug(Y.Plugin.NodeFX);
//Add the Drop plugin
a.plug(Y.Plugin.Drop);

Syncing the Target with the Animation

The Drop Target needs to be in sync with the animation, since we are changing the height, width, top and left style.

We do this by adding a listener to the tween event on the animation instance.

  1. //on tween of the original anim, we need to sync the drop's shim.
  2. a.fx.on('tween', function() {
  3. //Do we have an active Drag?
  4. if (Y.DD.DDM.activeDrag) {
  5. //Size this shim
  6. this.drop.sizeShim();
  7. //Force an over target check since we might not be moving the mouse.
  8. Y.Lang.later(0, a, function() {
  9. this.drop._handleTargetOver();
  10. });
  11. }
  12. }, a);
//on tween of the original anim, we need to sync the drop's shim.
a.fx.on('tween', function() {
    //Do we have an active Drag?
    if (Y.DD.DDM.activeDrag) {
        //Size this shim
        this.drop.sizeShim();
        //Force an over target check since we might not be moving the mouse.
        Y.Lang.later(0, a, function() {
            this.drop._handleTargetOver();
        });
    }
}, a);

Full example source

  1. YUI().use('dd-drop', 'anim', 'dd-plugin', 'dd-drop-plugin', function(Y) {
  2. //Get the node #drag
  3. var d = Y.Node.get('#drag');
  4. d.plug(Y.plugin.Drag, { dragMode: 'intersect' });
  5.  
  6. //Get all the div's with the class anim
  7. var anims = Y.Node.all('div.anim');
  8. var counter = 0;
  9. anims.each(function(v, k) {
  10. //Get a reference to the Node instance
  11. var a = v;
  12. //Add the FX plugin
  13. a.plug(Y.Plugin.NodeFX);
  14. //Add the Drop plugin
  15. a.plug(Y.Plugin.Drop);
  16.  
  17. //Set the attributes on the animation
  18. a.fx.setAttrs({
  19. from: {
  20. left: 0
  21. },
  22. to: {
  23. curve: function() {
  24. var points = [],
  25. n = 10;
  26.  
  27. for (var i = 0; i < n; ++i) {
  28. points.push([
  29. Math.floor(Math.random()*Y.DOM.winWidth() - 60 - a.get('offsetWidth')),
  30. Math.floor(Math.random()*Y.DOM.winHeight() - a.get('offsetHeight'))
  31. ]);
  32. }
  33. return points;
  34. }
  35. },
  36. //Do the animation 20 times
  37. iterations: 20,
  38. //Alternate it so it "bounces" across the screen
  39. direction: 'alternate',
  40. //Give all of them a different duration so we get different speeds.
  41. duration: ((counter * 1.75) + 1)
  42. });
  43.  
  44. //When this drop is entered, pause the fx
  45. a.drop.on('drop:enter', function() {
  46. this.fx.pause();
  47. }, a);
  48. //When the drop is exited, run the fx again
  49. a.drop.on('drop:exit', function() {
  50. this.fx.run();
  51. }, a);
  52. //When a drop is on the node, do something special
  53. a.drop.on('drop:hit', function(e) {
  54. //Stop the animation
  55. this.fx.stop();
  56. //remove the tween listener
  57. this.fx.unsubscribeAll('tween');
  58. //move it to the dock
  59. this.fx.setAttrs({
  60. from: {
  61. opacity: 1
  62. },
  63. to: {
  64. height: 50,
  65. width: 50,
  66. left: function() {
  67. var dW = Y.Node.get('body').get('viewportRegion').right;
  68. return ((dW - 60)); //Minus 60 for the dock
  69. },
  70. top: 15,
  71. opacity: .5
  72. },
  73. direction: 'normal',
  74. iterations: 1,
  75. duration: .5,
  76. //We are using reverse above for the "bouncing", reset it here.
  77. reverse: false
  78. });
  79.  
  80. //On end, add a class and destroy the target
  81. this.fx.on('end', function() {
  82. this.drop.get('node').addClass('done');
  83. this.drop.destroy();
  84. }, this);
  85. //Run this animation
  86. this.fx.run();
  87.  
  88. //others that were dropped on.
  89. Y.each(e.others, function(v, k) {
  90. var node = v.get('node');
  91. node.fx.run();
  92. });
  93.  
  94. }, a);
  95.  
  96. //on tween of the original anim, we need to sync the drop's shim.
  97. a.fx.on('tween', function() {
  98. //Do we have an active Drag?
  99. if (Y.DD.DDM.activeDrag) {
  100. //Size this shim
  101. this.drop.sizeShim();
  102. //Force an over target check since we might not be moving the mouse.
  103. Y.Lang.later(0, a, function() {
  104. this.drop._handleTargetOver();
  105. });
  106. }
  107. }, a);
  108.  
  109. a.fx.run();
  110. });
  111. });
YUI().use('dd-drop', 'anim', 'dd-plugin', 'dd-drop-plugin', function(Y) {
    //Get the node #drag
    var d = Y.Node.get('#drag');
    d.plug(Y.plugin.Drag, { dragMode: 'intersect' });
 
    //Get all the div's with the class anim
    var anims = Y.Node.all('div.anim');
    var counter = 0;
    anims.each(function(v, k) {
        //Get a reference to the Node instance
        var a = v; 
        //Add the FX plugin
        a.plug(Y.Plugin.NodeFX);
        //Add the Drop plugin
        a.plug(Y.Plugin.Drop);
 
        //Set the attributes on the animation
        a.fx.setAttrs({
            from: {
                left: 0
            },
            to: {
                curve: function() {
                    var points = [],
                        n = 10;
 
                    for (var i = 0; i < n; ++i) {
                        points.push([
                            Math.floor(Math.random()*Y.DOM.winWidth() - 60 - a.get('offsetWidth')),
                            Math.floor(Math.random()*Y.DOM.winHeight() - a.get('offsetHeight'))
                        ]);
                    }
                    return points;
                }
            },
            //Do the animation 20 times
            iterations: 20,
            //Alternate it so it "bounces" across the screen
            direction: 'alternate',
            //Give all of them a different duration so we get different speeds.
            duration: ((counter * 1.75) + 1)
        });
 
        //When this drop is entered, pause the fx
        a.drop.on('drop:enter', function() {
            this.fx.pause();
        }, a);
        //When the drop is exited, run the fx again
        a.drop.on('drop:exit', function() {
            this.fx.run();
        }, a);
        //When a drop is on the node, do something special
        a.drop.on('drop:hit', function(e) {
            //Stop the animation
            this.fx.stop();
            //remove the tween listener
            this.fx.unsubscribeAll('tween');
            //move it to the dock
            this.fx.setAttrs({
                from: {
                    opacity: 1
                },
                to: {
                    height: 50,
                    width: 50,
                    left: function() {
                        var dW = Y.Node.get('body').get('viewportRegion').right;
                        return ((dW - 60)); //Minus 60 for the dock
                    },
                    top: 15,
                    opacity: .5
                },
                direction: 'normal',
                iterations: 1,
                duration: .5,
                //We are using reverse above for the "bouncing", reset it here.
                reverse: false
            });
 
            //On end, add a class and destroy the target
            this.fx.on('end', function() {
                this.drop.get('node').addClass('done');
                this.drop.destroy();
            }, this);
            //Run this animation
            this.fx.run();
 
            //others that were dropped on.
            Y.each(e.others, function(v, k) {
                var node = v.get('node');
                node.fx.run();
            });
 
        }, a);
 
        //on tween of the original anim, we need to sync the drop's shim.
        a.fx.on('tween', function() {
            //Do we have an active Drag?
            if (Y.DD.DDM.activeDrag) {
                //Size this shim
                this.drop.sizeShim();
                //Force an over target check since we might not be moving the mouse.
                Y.Lang.later(0, a, function() {
                    this.drop._handleTargetOver();
                });
            }
        }, a);
 
        a.fx.run();
    });
});

Copyright © 2009 Yahoo! Inc. All rights reserved.

Privacy Policy - Terms of Service - Copyright Policy - Job Openings