javascript 在 angularjs 中缓存图像 - ngRepeat
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31160518/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
caching images in angularjs - ngRepeat
提问by clearScreen
I wanted to know how to implement a image cache in AngularJS, or a way to load the image once and use it many times in the same application
我想知道如何在 AngularJS 中实现图像缓存,或者在同一个应用程序中加载一次图像并多次使用它的方法
I have to show a directory listing in ui-select. The drop down may contain folders or files. For folders I want to show a folder icon and for files I want to show a file icon. I am using ng-repeat to iterate the array of files and folders
我必须在ui-select 中显示目录列表。下拉菜单可能包含文件夹或文件。对于文件夹,我想显示一个文件夹图标,而对于文件,我想显示一个文件图标。我正在使用 ng-repeat 来迭代文件和文件夹的数组
[ {name: "abc/", folder: true}, {name: "pqr.txt", folder: false}, ......]
Inside the ng-repeat, I have a ng-if which shows a folder icon, if folder-attribute is true else it shows a file-icon. Right now, I am using tag to load the image. The image is in my local directory, will it slow down the performance? Should I use a cache?
在 ng-repeat 中,我有一个 ng-if,它显示一个文件夹图标,如果 folder-attribute 为真,则它显示一个文件图标。现在,我正在使用标签来加载图像。图像在我的本地目录中,它会降低性能吗?我应该使用缓存吗?
回答by Icycool
As long as your image is coming from the same URL, your browser will do the caching automatically.
只要您的图像来自相同的 URL,您的浏览器就会自动进行缓存。
回答by Endre Simo
If you are not using through an $http
service you might use the $cacheFactoryservice that generates cache objects for all Angular services. Internally,
the $cacheFactory creates a default cache object, even if we don't create one explicitly.
如果您不是通过$http
服务使用,您可以使用$cacheFactory服务为所有 Angular 服务生成缓存对象。在内部, $cacheFactory 创建一个默认缓存对象,即使我们没有明确创建一个。
Then you can use the the put
method which allows to to put a key (string) of any JavaScript object value into the
cache.
然后您可以使用put
允许将任何 JavaScript 对象值的键(字符串)放入缓存的方法。
cache.put(key, value);
You can access it by
您可以通过
cache.get(key);
Or if you are using through $http service you can enable the cache by setting the cache
parameter as true:
或者,如果您通过 $http 服务使用,您可以通过将cache
参数设置为 true来启用缓存:
$http({
method: 'GET',
url: '/api/users.json',
cache: true
});
回答by Neil Palethorpe
For anyone coming here from a Cordova/Phonegap + Angular mix; I was running into the issue where I didn't like any of the solutions available and the seemingly popular solution of the christen/imgcache plugin wasn't worth following due to lack of OS support (Looks like chrome is the only OS supported) https://github.com/chrisben/imgcache.js/
对于任何来自 Cordova/Phonegap + Angular 组合的人;我遇到了一个问题,我不喜欢任何可用的解决方案,并且由于缺乏操作系统支持,看似流行的 christen/imgcache 插件解决方案不值得遵循(看起来 chrome 是唯一支持的操作系统)https ://github.com/chrisben/imgcache.js/
So I decided to write an AngularJS directory that handles the entire process simply by adding a "cacheimg" attribute on any img/element with background image.
所以我决定编写一个 AngularJS 目录来处理整个过程,只需在任何具有背景图像的 img/元素上添加“cacheimg”属性。
The basics of the following are that it downloads and writes the image files into temporary storage on the device using the cordova file + filetransfer plugins (Both are required for this plugin to work!)
下面的基础是它使用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);
}
);
}
So for anyone unsure how to handle the above (and I apologise if this method is not 'very angular' - I'm still fairly new to Angular myself!) simply copy the code, stick it into a new file in your projects js folder, make sure you include this file in the project:
因此,对于不确定如何处理上述问题的任何人(如果此方法不是“非常有角度”,我深表歉意 - 我自己对 Angular 还是相当陌生!)只需复制代码,将其粘贴到项目 js 文件夹中的新文件中,请确保在项目中包含此文件:
<script type="text/javascript" src="js/directives/dir_imgcache.js"></script>
Change the "app.directive" to be [yourappname].directive, you can then just add the attribute "cacheimg" to your element...
将“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>
For the purpose of the last example I had to stick in a $watch because the directive gets called prior to the background image being set! If you don't plan on setting an image from a scope variable I strongly recommend removing the $watch!
出于最后一个示例的目的,我不得不坚持使用 $watch 因为该指令在设置背景图像之前被调用!如果您不打算从范围变量设置图像,我强烈建议您删除 $watch!
It is also worth mentioning that currently I haven't put in a delete - it is good practise to not rely on the OS to delete files so I plan on adapting this directory further to remove any image not requested for a while.
还值得一提的是,目前我还没有删除 - 不依赖操作系统删除文件是一种很好的做法,因此我计划进一步调整此目录以删除一段时间未请求的任何图像。
Anyway, hope that helps someone! :)
无论如何,希望对某人有所帮助!:)