Hana Hana - 7 months ago 31
Javascript Question

create an angularjs directive to wrap jquery tagcanvas plugin

I want to implement an animated word cloud. Since I did not found any angular or Ionic ready plugins to do what i wanted, I decided (and I found it interesting to learn) to create an angular wrapper for a jquery code.
The plugin is tagcanvas, and the usage example is this

What I have done so far:


  • I added the jquery js file to my index.html

  • I created a js file where I declared my directive, and added it to index.html:



tagcanvas.js

angular.module('tagCanvas', [])

.directive('tagCanvas', function() {

return {

restrict: 'E',
link: function (scope, element, attrs) {


element.tagcanvas({


outlineColour: attrs.outlineColour,
reverse: attrs.reverse,
depth: attrs.depth,
maxSpeed: attrs.maxSpeed,
textFont: attrs.textFont,
textColour: attrs.textColour,
weightMode: attrs.weightMode,
weight: attrs.weight
}, attrs.canvas);



}
};

});


As you can see in the codepen example, there are attributes that I need to call, and a html element id
canvas
, which I did not know how to call them in my directive.

My second problem is that I don't know how to create and call the words that I want to display in my tag cloud.
I looked over lots of tutorials, but I still don't know how to do it. Any help will be appreciated.

Lex Lex
Answer

First, I would not name your Angular app and directive with the same name. Not only is it confusing, but it may not work properly. Second, although there may be many ways to approach this, here is how I would do it:

directive
(I have changed the directive to an attribute rather than an element and used an isolate scope for the attributes. The link function is wrapped in a $timeout to ensure the element exists in the DOM prior to trying to call tagcanvas.)

.directive("tagCanvas", function($timeout) {
    return {
        restrict: "A",
        scope: {
            canvasId: "@",
            outlineColour: "@",
            reverse: "@",
            depth: "@",
            maxSpeed: "@",
            textFont: "@",
            textColour: "@",
            weightMode: "@",
            weight: "@"
        },
        link: function (scope, element) {
            $timeout(function() {
                element.tagcanvas({
                    outlineColour: scope.outlineColour,
                    reverse: scope.reverse,
                    depth: scope.depth,
                    maxSpeed: scope.maxSpeed,
                    textFont: scope.textFont,
                    weightMode: scope.weightMode,
                    weight: scope.weight
                }, scope.canvasId);
            });
        }
    };
})

controller
(You would likely want to get your word list from a service or some other storage, but for illustration I have hardcoded an array in the controller)

.controller("ctrl", function ($scope) {
    $scope.wordList = [
        {
            href: "#",
            fontSize: "2.83ex",
            text: "1000"
        }, {
            href: "#",
            fontSize: "4.8ex",
            text: "example"
        }, {
            href: "#",
            fontSize: "8.77ex",
            text: "gif"
        }, {
            href: "#",
            fontSize: "2.83ex",
            text: "svg"
        }, {
            href: "#",
            fontSize: "8.77ex",
            text: "jpg"
        }, {
            href: "#",
            fontSize: "10.68ex",
            text: "png"
        }, {
            href: "#",
            fontSize: "2.83ex",
            text: "bmp"
        }, {
            href: "#",
            fontSize: "4.8ex",
            text: "img"
        }
    ];
})

html

<div>
    <canvas width="300"
            height="300"
            id="myCanvas"
            tag-canvas
            canvas-id="tags"
            outline-colour="#ff00ff"
            text-font="Arial"
            text-colour="#ff00ff"
            reverse="true"
            depth="0.8"
            max-speed="0.05"
            weight-mode="both" 
            weight="true"></canvas>
</div>
<div id="tags" style="font-size: 50%;">
    <a ng-repeat="word in wordList" href="{{word.href}}" style="font-size: {{word.fontSize}}">{{word.text}}</a>
</div>