AngularJS – HTML5 Canvas Drag and Drop Directive Using KineticJS

January 7, 2014

no comments

Recently for one of my projects I needed to add drag and drop (DnD) functionality.

After examining the native HTML5 DnD I come to conclusion that the awesome HTML5 feature still suffers from cross browser computability issues, second of all the lack of mobile touch support really pissed me off. On the other hand, Canvas has no cross browser computability issues and has a great touch support.
To make a long story short, I implemented Canvas DnD functionality in AngularJS directive.

We use KineticJS -an HTML5 Canvas JavaScript framework that enables high performance animations, transitions, node nesting, layering, filtering, caching, event handling for desktop and mobile applications, and much more. (it’s free!)

1) Add JavaScript reference to kineticJS

<script src="/Scripts/kinetic-v4.7.4.min.js"></script>


2) Add directive
<div data-draggable-canvas data-kinetic-obj="kineticObj" data-kinetic-stage-obj="false" data-isdraggable=" true" id="canvas">&nbsp;</div>

3) Content of canvasModule.js file
(function () {
    "use strict";

    var module = angular.module("canvasModule", []);

    module.directive('draggableCanvas', ['$rootScope', function ($rootScope) {
        return {
            restrict: 'A',
            scope: {
                isdraggable: '=',
                kineticObj: '=',
                kineticStageObj: '=',
            },
            link: function (scope, el, attrs) {

                if (!scope.kineticStageObj) {
                    var id = attrs["id"];
                    //create random unique id
                    if (!id) {
                        id = Math.random().toString(36).substring(7);
                    }
                    if (!scope.kineticStageObj) {
                        scope.kineticStageObj = new Kinetic.Stage({
                            container: id,
                            width: 578,
                            height: 200
                        });
                    }
                    if (!scope.kineticStageObj.container) {
                        scope.kineticStageObj.attrs.container = id;
                    }
                }
                var layer = new Kinetic.Layer();
                var rectX = scope.kineticStageObj.getWidth() / 2 - 50;
                var rectY = scope.kineticStageObj.getHeight() / 2 - 25;

                //if kineticObj is null, init
                var options = {
                    x: rectX,
                    y: rectY,
                    width: 100,
                    height: 50,
                    fill: '#00D2FF',
                    stroke: 'black',
                    strokeWidth: 4,
                };
                if (scope.isdraggable) {
                    options.draggable = true;
                }
                if (!scope.kineticObj) {
                    scope.kineticObj = new Kinetic.Rect(options);
                }

                // add cursor styling
                scope.kineticObj.on('mouseover', function () {

                    document.body.style.cursor = 'pointer';

                });
                scope.kineticObj.on('mouseout', function () {
                    document.body.style.cursor = 'default';
                    $rootScope.$emit("CANVAS-MOUSEOUT");
                });

                layer.add(scope.kineticObj);
                scope.kineticStageObj.add(layer);

            }
        }
    }]);

})();

As you can see the directive is quite flexible, you can add your own kinetic objects, if not, you have default init options. take a look at kineticjs documents for more information, and of course you can always change the directive to fit your own project requirements.

4) Reference:
a) http://www.html5canvastutorials.com/
b) http://kineticjs.com/
c) Great post by Ason Turim called ANGULARJS NATIVE DRAG AND DROP

5) Working Example

Hope you’ll find this post helpful.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*