Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用Angular.js预加载图像的最佳方法_Javascript_Angularjs_Image Preloader - Fatal编程技术网

Javascript 使用Angular.js预加载图像的最佳方法

Javascript 使用Angular.js预加载图像的最佳方法,javascript,angularjs,image-preloader,Javascript,Angularjs,Image Preloader,Angular的ng src保留以前的模型,直到它在内部预加载图像。我在每个页面上为横幅使用不同的图像,当我切换路线时,我更改主视图,保持标题视图不变,只有在有横幅时更改横幅模型 这将导致在加载新的横幅图像时看到以前的横幅图像 我很惊讶还没有关于它的指令,但我想在尝试构建一个之前进行讨论 我想我要做的是在自定义属性上使用banner模型。比如: <img preload-src="{{bannerUrl}}" ng-src="{{preloadedUrl}}"> 然后$scop

Angular的ng src保留以前的模型,直到它在内部预加载图像。我在每个页面上为横幅使用不同的图像,当我切换路线时,我更改主视图,保持标题视图不变,只有在有横幅时更改横幅模型

这将导致在加载新的横幅图像时看到以前的横幅图像

我很惊讶还没有关于它的指令,但我想在尝试构建一个之前进行讨论

我想我要做的是在自定义属性上使用banner模型。比如:

<img preload-src="{{bannerUrl}}" ng-src="{{preloadedUrl}}">

然后$scope.watch查看bannerUrl的更改,一旦更改,首先用loader微调器替换ng src,然后创建temproary img dom元素,从preload src预加载图像,然后将其分配到preload URL

例如,需要考虑如何处理画廊的多个图像

有人对此有任何意见吗?或者有人可以告诉我现有的代码

我在github上看到过使用背景图像的现有代码,但这不适用于我,因为我需要动态的高度/宽度,因为我的应用程序是响应性的,我不能使用背景图像


谢谢

指令上有两个URL似乎过于复杂了。我认为最好是编写一个指令,其工作原理如下:

<img ng-src="{{bannerUrl}}" spinner-on-load />
通过这种方式,元素的行为非常类似于带有
ngsrc
属性的标准img,只是附加了一些额外的行为


如果有人感兴趣,这是我的最终解决方案:我使用twitter引导。所以,在所有图像中添加了“淡入淡出”类,只需在加载图像时用指令切换“淡入淡出”类即可

angular.module('myApp').directive('imgPreload', ['$rootScope', function($rootScope) {
    return {
      restrict: 'A',
      scope: {
        ngSrc: '@'
      },
      link: function(scope, element, attrs) {
        element.on('load', function() {
          element.addClass('in');
        }).on('error', function() {
          //
        });

        scope.$watch('ngSrc', function(newVal) {
          element.removeClass('in');
        });
      }
    };
}]);

<img img-preload class="fade" ng-src="{{imgSrc}}">
angular.module('myApp')。指令('imgPreload',['$rootScope',函数($rootScope){
返回{
限制:“A”,
范围:{
ngSrc:“@”
},
链接:函数(范围、元素、属性){
on('load',function(){
元素addClass('in');
}).on('error',function()){
//
});
范围.$watch('ngSrc',函数(newVal){
element.removeClass('in');
});
}
};
}]);
工作示例:

仅用于共享^^

 //css
.media-box{
                position: relative;
                width:220px;
                height: 220px;
                overflow: hidden;
            }
            .media-box div{
                position: absolute;
                left: 0;
                top: 0;
            }
            .spinner{
                position: absolute;
                left: 0;
                top: 0;
                background: #CCC url(./spinner.gif) no-repeat center center;
                display: block;
                width:220px;
                height: 220px;
            }
            .feed img.spinner-show{
                visibility: visible;
            }
            .feed img.spinner-hide{
                visibility: hidden;
            }

//html
<div class="media-box">
  <div>
    <img data-ng-src="{{item.media}}" alt="" title="" data-spinner-on-load>
  </div>
</div>

//js
.directive('spinnerOnLoad', function() {
            return {
                restrict: 'A',
                link: function(scope,element){
                    element.on('load', function() {
                        element.removeClass('spinner-hide');
                        element.addClass('spinner-show');
                        element.parent().find('span').remove();
                    });
                    scope.$watch('ngSrc', function() {
                        element.addClass('spinner-hide');
                        element.parent().append('<span class="spinner"></span>');
                    });      
                }
            }
        });
//css
.媒体盒{
位置:相对位置;
宽度:220px;
高度:220px;
溢出:隐藏;
}
.传媒室{
位置:绝对位置;
左:0;
排名:0;
}
斯宾纳先生{
位置:绝对位置;
左:0;
排名:0;
背景:#CCC url(./spinner.gif)无重复中心;
显示:块;
宽度:220px;
高度:220px;
}
.feed img.spinner-show{
能见度:可见;
}
.进料img.spinner-hide{
可见性:隐藏;
}
//html
//js
.directive('spinnerOnLoad',function(){
返回{
限制:“A”,
链接:功能(范围、元素){
on('load',function(){
element.removeClass('spinner-hide');
元素addClass('spinner-show');
element.parent().find('span').remove();
});
作用域:$watch('ngSrc',function(){
元素addClass('spinner-hide');
element.parent().append(“”);
});      
}
}
});
而不是使用

element.on('load', function() {});
使用插件。它将大大加快你的图像

因此,最终的代码是:

link: function(scope, element) {
  imagesLoaded(element, function() {

  });
  scope.$watch('ngSrc', function() {

  });
}

如果需要,您可以将映像失败和映像加载程序作为指令的属性传递

myApp.directive("mySrc", function() {
    return {
      link: function(scope, element, attrs) {
        var img, loadImage;
        var IMAGE_LOAD="123.jpg";
        var IMAGE_FAIL="123.jpg";
        img = null;

        loadImage = function() {

          element[0].src = IMAGE_LOAD;

          img  = new Image();
          img.src = attrs.mySrc;

          img.onload = function() {
            element[0].src = attrs.mySrc;
          };
          img.onerror=function ()
          {
              element[0].src = IMAGE_FAIL;
          }
        };

        loadImage();


      }
    };
  });

我发现一个简单的解决方案是在分配新值之前将url更改为“/:0”

$scope.bannerUrl = 'initial value'; 

// When we want to change it
$scope.bannerUrl = '//:0';  // remove the previous img so it's not visible while the new one loads
$scope.bannerUrl = scope.preloadedUrl

我有一个指令,当img src改变时,它会显示一个微调器:

<img-with-loading
      img-src="{{src}}"
      spinner-class="{{spinnerClass}}"
/>


此处代码:

我认为这可能是最优雅的解决方案,因为该指令实际上创建了微调器并自动将其删除:

app.directive('spinnerLoad', [function spinnerLoad() {
    return {
        restrict: 'A',
        link: function spinnerLoadLink(scope, elem, attrs) {
            scope.$watch('ngSrc', function watchNgSrc() {
                elem.hide();
                elem.after('<i class="fa fa-spinner fa-lg fa-spin"></i>');  // add spinner
            });
            elem.on('load', function onLoad() {
                elem.show();
                elem.next('i.fa-spinner').remove(); // remove spinner
            });
        }
    };
}]);
app.directive('spinnerLoad',[function spinnerLoad(){
返回{
限制:“A”,
链接:功能spinnerLoadLink(范围、元素、属性){
作用域.$watch('ngSrc',函数watchNgSrc(){
隐藏元素();
元素(“”);//添加微调器
});
元素on('load',函数onLoad(){
元素show();
elem.next('i.fa-spinner').remove();//remove spinner
});
}
};
}]);
以下是html:

<img ng-src='{{imgUrl}}' spinner-load />


注意:您需要使用font awesome才能按此处所述工作

可以使用factory和resolve在路线更改时预加载图像:

// call REST
                    return getContent.get().$promise.then(function(response) {

                                //return response;

                                // preload images from response
                                var imageLocations = [
                                  // put image(s) from response to array
                                  response.PostImage.big[0],
                                ];

                                // check do we have (all) image(s) in array
                                console.log(imageLocations);

                                // return when all images are preloaded
                                return preloader.preloadImages( imageLocations )
                                .then(function() {

                                    //if it was success 
                                    return response;
                                },
                                function() {

                                        //if it failed 
                                    return response;
                                });

                            });
在此完成教程:

通常的解决方法是使用CSS将图像设置为
可见性:隐藏
,直到在将其更改为
可见性:可见
时加载最终图像,从而只看到最终图像。@jfriend00所以将所有图像设置为
可见性:隐藏
,然后使用javascript查看数组中的所有图像何时加载,并将所有图像设置为
可见性:visible
那么?完全有意义,谢谢。我今天下午试试。谢谢你,先生。我进一步扩展了您的想法,效果非常好。JSFIDLE中的图像不起作用。即使我使用的是一个有效的图像,它也不会移除微调器。如果你想知道,小提琴的角度为1.2及以上,这引入了一些突破性的变化耶!Thanx@JanKlimo!感谢链接到一个工作的现实世界的例子,但是你能把这些好东西分到一个Plunker或一些其他在线沙盒测试环境中吗?谢谢你,这正是我想要的。谢谢,这是一个愚蠢的问题,但是我如何在一个HTML模板中使用这个指令呢
// call REST
                    return getContent.get().$promise.then(function(response) {

                                //return response;

                                // preload images from response
                                var imageLocations = [
                                  // put image(s) from response to array
                                  response.PostImage.big[0],
                                ];

                                // check do we have (all) image(s) in array
                                console.log(imageLocations);

                                // return when all images are preloaded
                                return preloader.preloadImages( imageLocations )
                                .then(function() {

                                    //if it was success 
                                    return response;
                                },
                                function() {

                                        //if it failed 
                                    return response;
                                });

                            });