【问题标题】:caching images in angularjs - ngRepeat在 angularjs 中缓存图像 - ngRepeat
【发布时间】:2015-09-18 13:30:50
【问题描述】:

我想知道如何在 AngularJS 中实现图像缓存,或者一种在同一个应用程序中加载图像并多次使用它的方法

我必须在 ui-select 中显示目录列表。下拉列表可能包含文件夹或文件。对于文件夹,我想显示一个文件夹图标,对于文件,我想显示一个文件图标。我正在使用 ng-repeat 来迭代文件和文件夹数组

[ {name: "abc/", folder: true}, {name: "pqr.txt", folder: false}, ......]

在 ng-repeat 中,我有一个 ng-if,它显示一个文件夹图标,如果文件夹属性为 true,否则它显示一个文件图标。现在,我正在使用标签来加载图像。图像在我的本地目录中,它会降低性能吗?我应该使用缓存吗?

【问题讨论】:

    标签: javascript angularjs image caching


    【解决方案1】:

    对于来自 Cordova/Phonegap + Angular 组合的任何人;我遇到了一个问题,我不喜欢任何可用的解决方案,并且由于缺乏操作系统支持,似乎流行的 christen/imgcache 插件解决方案不值得关注(看起来 chrome 是唯一支持的操作系统)@ 987654321@

    所以我决定编写一个 AngularJS 目录来处理整个过程,只需在任何带有背景图像的 img/元素上添加一个“cacheimg”属性。

    以下基础是它使用cordova文件+文件传输插件下载图像文件并将其写入设备上的临时存储(此插件工作需要两者!)

    var LOG_TAG = 'DIR_IMGCACHE: ';
    app.directive('cacheimg', function() {
        return {
            restrict: 'A',
            link: function(scope, elem, attrs) {
                console.log(LOG_TAG + 'Starting Directive.');
    
                // Watch any value changes
                scope.$watch(function () {
                    return elem.css(attrs.style);
                },  function(){
    
                    // Style has been changed so check image hasn't been modified
                    findImageURLs(elem, attrs);
    
                }, true);
    
                scope.$watch(function () {
                    return attrs.src;
                },  function(){
    
                    // Image source has been changed so check image hasn't been modified
                    findImageURLs(elem, attrs);
    
                }, true);
    
    
                // Do an initial search for anything pre-set
                findImageURLs(elem, attrs);
    
            }
        };
    });
    
    function findImageURLs(elem, attrs){
        // Check for  background image
        if (elem.css('background-image') !== 'none'){
            console.log(LOG_TAG + 'Background Image');
    
            var backimgsrc = elem.css('background-image');
            if (backimgsrc.startsWith('url(')){
                backimgsrc = backimgsrc.substring(4, backimgsrc.length -1);
            }
    
            // Retrieve from the cache (or download if we havent already)
            GetFromCache(backimgsrc, function(imgPath){
                console.log(LOG_TAG + 'Got image - setting now');
    
                // Got the image, set it now
                elem.css('background-image', 'url(' + imgPath + ')');
    
            }, function(err){
                console.log(LOG_TAG + 'Failed to get image from cache');
    
                // SET BROKEN LINK IMAGE HERE
                elem.css('background-image', 'url(../../img/brokenlink.png)');
    
            });
    
        }
    
        // Check for a src tag
        if (attrs.src !== undefined){
            console.log(LOG_TAG + 'Found Src Tag');
    
            // Retrieve from the cache (or download if we havent already)
            GetFromCache(attrs.src, function(imgPath){
                console.log(LOG_TAG + 'Got image - setting now');
    
                // Got the image, set it now
                attrs.$set('src', imgPath);
    
            }, function(err){
                console.log(LOG_TAG + 'Failed to get image from cache');
    
                // SET BROKEN LINK IMAGE HERE
                attrs.$set('src', '../../img/brokenlink.png');
    
            });
    
        }
    }
    
    
    // Build a file key - this will be what the filename is within the cache
    function buildFileKey(url){
        console.log(LOG_TAG + 'Building file key for url: ' + url);
        var parts = url.split('.');
        var result = (parts.slice(0,-1).join('') + '.' + parts.slice(-1)).toString().replace(/[\/,:]/g,'_').toLowerCase();
        console.log(LOG_TAG + 'Built file key: ' + result);
        return result;
    }
    
    // Either get hold of the file from the cache or if we don't currently have it
    // then attempt to download and store in the cache ready for next time
    function GetFromCache(sourceUrl, success, fail) {
        console.log(LOG_TAG + 'Getting image from the cache');
        var FOLDER_IMAGE_CACHE = 'IMAGE_CACHE';
        var fileKey = buildFileKey(sourceUrl);
        var cacheExpiry = new Date().getTime() - (86400000 * 3); // 3 days
    
        // Get the file system for temporary storage
        window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function(fs){
    
            console.log(LOG_TAG + 'Opened File System: ' + fs.name);
    
            // Get hold of the directory (Or create if we haven't already)
            fs.root.getDirectory(FOLDER_IMAGE_CACHE, { create:true }, function(dirEntry){
    
                var downloadToPath = dirEntry.toURL() + fileKey;
    
                // Check to see if we have the file
                doesFileExist(dirEntry, fileKey, function(fileEntry){
    
                    // File exists - check if it needs to be renewed
                    if (new Date(fileEntry.lastModifiedDate).getTime() < cacheExpiry){
                        console.log(LOG_TAG + 'Image has passed the expiry threshold - re-getting the file');
                        downloadFile(sourceUrl, downloadToPath, success, fail);
                    }
    
                    // Return the file path
                    console.log(LOG_TAG + 'Passing back the image path ' + fileEntry.toURL());
                    return (success(fileEntry.toURL()));
    
                }, function(){
    
                    // File does not exist so download
                    console.log(LOG_TAG + 'Image doesnt exist - getting file');
                    downloadFile(sourceUrl, downloadToPath, success, fail);
    
                });
    
            }, fail);
    
        }, fail);
    
    }
    
    // Check to see if the given image already exists in our cache
    function doesFileExist(dir, fileKey, existsCallback, notExistsCallback){
        console.log(LOG_TAG + 'Checking if file exists');
    
        // Check the directory for this file
        dir.getFile(fileKey, { create:false }, function(fileEntry){
            existsCallback(fileEntry);
        }, notExistsCallback);
    
    }
    
    // Download a file into the cache
    function downloadFile(url, downloadToPath, success, fail){
        console.log(LOG_TAG + 'Downloading file ' + url);
        var fileTransfer = new FileTransfer();
    
        // File download function with URL and local path
        fileTransfer.download(encodeURI(url), downloadToPath,
            function (fileEntry) {
                console.log(LOG_TAG + 'Download Complete to path: ' + fileEntry.toURL());
                success(fileEntry.toURL());
    
    
            },
            function (error) {
                //Download abort errors or download failed errors
                console.log(LOG_TAG + 'Download Failed: ' + error.source);
                //alert("download error target " + error.target);
                //alert("upload error code" + error.code);
            }
        );
    
    }
    

    因此,对于不确定如何处理上述问题的任何人(如果这种方法不是“非常有角度”,我深表歉意 - 我自己对 Angular 还是很陌生!)只需复制代码,将其粘贴到您的新文件中项目 js 文件夹,确保在项目中包含此文件:

    <script type="text/javascript" src="js/directives/dir_imgcache.js"></script>
    

    将“app.directive”更改为 [yourappname].directive,然后您只需将属性“cacheimg”添加到您的元素...

    // Handling a background-image source
    <div cacheimg style="background-image:url(img/myimage.png);"></div>
    
    // Handling an image element source
    <img cacheimg src="img/myimage.png" />
    
    // Handling a AngularJS scoped image background source
    <div cacheimg style="background-image:url({{ item.myimagesource }});"></div>
    

    为了上一个示例的目的,我必须坚持使用 $watch,因为该指令在设置背景图像之前被调用!如果您不打算从范围变量中设置图像,我强烈建议您删除 $watch!

    还值得一提的是,目前我还没有删除 - 最好不要依赖操作系统来删除文件,因此我计划进一步调整此目录以删除一段时间内未请求的任何图像。

    无论如何,希望对某人有所帮助! :)

    【讨论】:

    【解决方案2】:

    如果您不通过$http 服务使用,您可能会使用为所有Angular 服务生成缓存对象的$cacheFactory 服务。在内部, $cacheFactory 创建一个默认缓存对象,即使我们没有显式创建一个。

    然后您可以使用put 方法,该方法允许将任何 JavaScript 对象值的键(字符串)放入 缓存。

    cache.put(key, value);
    

    你可以通过

    cache.get(key);
    

    或者如果您通过 $http 服务使用,您可以通过将 cache 参数设置为 true 来启用缓存:

    $http({
       method: 'GET',
       url: '/api/users.json',
       cache: true
    });
    

    【讨论】:

      【解决方案3】:

      只要您的图片来自同一个 URL,您的浏览器就会自动进行缓存。

      【讨论】:

      • 我很想知道@clearScreen 评论的答案 :)
      • @DevidFarinelli 然后再次下载图像 =\
      猜你喜欢
      • 2016-12-08
      • 2014-03-18
      • 1970-01-01
      • 2019-04-09
      • 2013-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-13
      相关资源
      最近更新 更多