简体   繁体   中英

Angular custom directives not working with external javascript plugin

I am creating a custom angular directive that will use the Image Tilt Effect plugin.

<tilt></tilt>

the template looks like this.

<li class="grid__item">
<div class="grid__img grid__img--example-1" >
    <img src="img/3.jpg" class="tilt-effect" alt="grid01" data-tilt-options='{ "opacity" : 0.3, "extraImgs" : 3, "movement": { "perspective" : 1200, "translateX" : -5, "translateY" : -5, "rotateX" : -5, "rotateY" : -5 } }' />
</div>

The problem I have is this script that I am loading at the bottom of the page doesnt seem to be on when the custom directive is injected into the page.

<script src="js/tiltfx.js"></script>

If I try and move the script into the html fragment for the custom directive I get an Error: $compile:tplrt

I've created a wrapper directive for this the Image Tilt Effect plugin ( fiddle ).

When you have a DOM plugin you need to use in angular, don't use auto initialization, such as the data-tilt-options of this plugin, because they are hard to predict, and may cause weird behavior, memory leaks, etc... This plugin has a manual init method - new TiltFx(element, options) , so we can use that.

Another problem is that this plugin must wait for angular to finish rendering, before it should be initialized. The simple fix is just using setTimeout or $timeout (if we need to update the digest cycle), to put the init at the end of the JS queue. We can also use mutation observers to do that, but that's out of this answer's scope.

One troubling aspect of using a DOM plugin in angular, is memory leaks. Plugins should have some sort of a cleaning mechanism. This plugin doesn't. So, you'll have to check for memory leaks, and if there are stray event handlers remove them, when the wrapped element is removed.

Directive code:

appModule.directive('tilt', function tilt() {
    var ddo = {
        template: '<div class="grid__img"><img class="tilt-effect" ng-src="{{imgSrc}}" alt="The image" />',
        restrict: 'E',
        replace: true,
        scope: {
            imgSrc: '@', // the image src
            tiltOptions: '=?' // the tilt options object - optional
        },
        link: function (scope, $el) {
            var img = $el[0].querySelector('img.tilt-effect'); // find the img element
            var tilt;

            setTimeout(function () { // wait 'till directive is rendered
                tilt = new TiltFx(img, scope.tiltOptions); // apply tilt on image with options (if any)
            });

            $el.on('$destroy', function() {
                // use tilt variable to perform cleanup on wrapper and img if needed
                tilt = null;
            });
        }
    };

    return ddo;
});

Usage:

<div ng-app="tilt">
    <tilt img-src="http://cdn.cutestpaw.com/wp-content/uploads/2013/12/Most-Famous-Felines-034.jpg" tilt-options='{ "opacity" : 0.3, "extraImgs" : 3, "movement": { "perspective" : 1500, "translateX" : -5, "translateY" : -5, "rotateX" : -5, "rotateY" : -5 } }'></tilt>
    <tilt img-src="http://www.cats.org.uk/uploads/images/pages/photo_latest14.jpg"></tilt>
</div>

Don't forget that this plugin requires the container to have fixed width and height, for example:

.grid__img {
    width: 400px;
    height: 400px;
}

Change

<script src="js/tiltfx.js"></script>

to

<script ng-src="js/tiltfx.js"></script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM