提升用户体验之道:图片预加载
2012-12-28 10:34
477 查看
随着网站构建越来越倾向于实现“桌面般的体验”,网站中的图片数量也开始显著地增长。想想网站中的对话框、Tabs、Tooltips、Sliders以及日历控件吧,这都是实现“桌面般体验”的必要元素。
预加载这一堆图片对网站性能及可用性的提升是有好处的,这样避免了图片加载过程中页面的闪烁、破裂(视觉上)等问题。
CSS sprites
CSS sprites技术可以用来减少页面产生的HTTP请求数。它是这么实现的,把所有的图型状态(比如按钮的默认状态,悬停及激活等状态)保存到一张图片中。并依据元素的状态,使用CSS对图片进行相应的定位、切割。
不过这样有个重要的缺点——需要提前加载的图片不适用这项技术。一些后面才需要显示的图片并没有被加载,这可能会导致一个延迟。因此,此技术一般适合静态站点,主要用来减少图片加载数。
JavaScript
另一个可以使用的技术是使用JavaScript的image对象。这个方法是这样的,先把网站中使用的每个图片的地址(URL)放到一个数组中。
var myImages = ["image_1.jpg', 'image_2.jpg', 'image_3.jpg', ...];
然后遍历这个数组,根据图片地址创建各自的image对象。这样可以保证所有的图片都能被浏览器缓存,等用到的时候就无需等待了。
for (var i = 0; i <= myImages.length; i++) {
var img = new Image();
img.src = myImages[i];
}
此方案费时的地方是,不仅要制造一个包含每张图片地址的数组,还要维护它的一致性。网站的每个需求变更(添加或更改图片地址)都会影响到这个数组。试想频繁变更的应用,又拥有数百张图片,这真会让人筋疲力尽的。
首先要分析页面中(包括外链及内联)的样式表。这可以通过遍历“document.styleSheets”对象来获得页面使用的所有样式表。
for (var i = 0; i < document.styleSheets.length; i++){
接下来要找出样式表的根目录。用来得到各个图片的绝对地址。
var baseURL = getBaseURL(document.styleSheets[i].href);
考虑到浏览器的兼容性,必须同时检查每个样式表的“cssRules”或“rules”中是否包含CSS规则。
if (document.styleSheets[i].cssRules) {
cssRules = document.styleSheets[i].cssRules
}
else if (document.styleSheets[i].rules) {
cssRules = document.styleSheets[i].rules
}
所有非空的CSS规则都要被解析,来确认它是否关联了图片。一个简单的正则表达式就可以解析出图片地址。
var cssRule = cssRules[j].style.cssText.match(/[^\(]+\.(gif|jpg|jpeg|png)/g);
然后,把这里收集到的所有图片地址保存到一个数组中供后面使用。
function analyzeCSSFiles() {
var cssRules; // CSS rules
for (var i = 0; i < document.styleSheets.length; i++) { // loop through all linked/inline stylesheets
var baseURL = getBaseURL(document.styleSheets[i].href); // get stylesheet's base URL
// get CSS rules
if (document.styleSheets[i].cssRules) {
cssRules = document.styleSheets[i].cssRules
}
else if (document.styleSheets[i].rules) {
cssRules = document.styleSheets[i].rules
}
// loop through all CSS rules
for (var j = 0; j < cssRules.length; j++) {
if (cssRules[j].style && cssRules[j].style.cssText) {
// extract only image related CSS rules
// parse rules string and extract image URL
var cssRule = cssRules[j].style.cssText.match(/[^\(]+\.(gif|jpg|jpeg|png)/g);
if (cssRule) {
// add image URL to array
cssRule = (cssRule + "").replace("\"", "")
imageURLs.push(baseURL + cssRule);
}
}
}
}
}
数组中存放的图片地址是绝对路径,为了得到它,我们实现了“getBaseUrl”函数来解析每个CSS文件的绝对地址。
function getBaseURL(cssLink) {
cssLink = (cssLink) ? cssLink : 'window.location.href'; // window.location.href for inline style definitions
var urlParts = cssLink.split('/'); // split link at '/' into an array
urlParts.pop(); // remove file path from URL array
var baseURL = urlParts.join('/'); // create base URL (rejoin URL parts)
if (baseURL != "")
{
baseURL += '/'; // expand URL with a '/'
}
return baseURL;
}
现在,遍历这个列表,为网站的每个图片创建一个JavaScript图片对象,来实现图片预加载并强制浏览器进行缓存。请注意“setTimeout”的使用,它确保了每个图片加载是依序执行的,当前图片加载完成才会加载下一个。原因是某些浏览器无法同时处理超过2个请求(译者注:IE6单域下的并发连接数限制就是2个)。为了避免可能的死锁,这里使用jQuery的bind方法给“load”、“onreadystatechange”和“error”事件绑定了一个处理器。这样可以确保遇到无法加载的遗失图片时,“errorTimer”可以把你带回正确的轨道。
function preloadImages() {
if (imageURLs && imageURLs.length && imageURLs[imagesLoaded]) { // if image URLs array isn't empty
var img = new Image(); // create a new imgage object
img.src = imageURLs[imagesLoaded]; // set the image source to the extracted image URL
setTimeout(function () {
if (!img.complete) {
jQuery(img).bind('onreadystatechange load error', onImageLoaded); // bind event handler
} else {
onImageLoaded(); // image loaded successfully, continue with the next one
}
errorTimer = setTimeout(onImageLoaded, 1000); // handle missing files (load the next image after 1 second)
}, 25);
}
else {
showPreloadedImages();
}
}
function onImageLoaded() {
clearTimeout(errorTimer); // clear error timer
imagesLoaded++; // increase image counter
preloadImages(); // preload next image
}
为了提升预加载时的用户体验,这里对“onImageLoaded”事件处理器做点改动,来添加一个进度条。
首先,引入jQuery UI的样式和显示进度条所需要的JavaScript文件。
<link type="text/css" href="css/ui-lightness/jquery-ui-1.8.6.custom.css" rel="stylesheet" />
<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.6.custom.min.js"></script>
然后在DOMReady事件被触发时初始化进度条。
$(document).ready(function () {
$("#progressbar").progressbar({ value: 0 }); // initialize progress bar
});
最后要做的一件事是扩展“onImageLoaded”事件处理函数。每加载完一张图片,就计算一次进度并更新进度条。
为了验证预加载的效果,这里把所有图片都添加到页面中。在预加载全部完成时,所有的图片会同时显示。
function onImageLoaded() {
clearTimeout(errorTimer); // clear error timer
$("#imagelist").append("<span>" + imagesLoaded + ": </span><img src='" + imageURLs[imagesLoaded] + "'/>"); // append image tag to image list
imagesLoaded++; // increase image counter
var percent = parseInt(100 * imagesLoaded / (imageURLs.length - 1)); // calculate progress
$("#progressbar").progressbar({ value: percent }); // refresh progress bar
$("#progressbarTitle").text("Preloading progress: " + percent + "%");
preloadImages(); // preload next image
}
进度条可以让用户知道加载的进展,避免用户的冷落感。另外,jQuery提供了大批优秀组件,进度条就是其中一个,只需简单的配置就可以满足我们的需求。使用它们无疑能显著提升你的网站形象。
希望这篇文章能给你带来灵感,去思考你的项目是否也能从这里描述的技术受益。
最后附上zip文件,它包含所有上面的预加载示例文件。下载并解压后,用浏览器打开preloading.html,并单击“Start preloading”就可以观看示例了。
再做些简单修改,你就可以把它集成到你自己的项目里了。
原文:Improving User Experience: Preload Images
预加载这一堆图片对网站性能及可用性的提升是有好处的,这样避免了图片加载过程中页面的闪烁、破裂(视觉上)等问题。
常用的技术
有两种常用的图片预加载技术:CSS sprites
CSS sprites技术可以用来减少页面产生的HTTP请求数。它是这么实现的,把所有的图型状态(比如按钮的默认状态,悬停及激活等状态)保存到一张图片中。并依据元素的状态,使用CSS对图片进行相应的定位、切割。
不过这样有个重要的缺点——需要提前加载的图片不适用这项技术。一些后面才需要显示的图片并没有被加载,这可能会导致一个延迟。因此,此技术一般适合静态站点,主要用来减少图片加载数。
JavaScript
另一个可以使用的技术是使用JavaScript的image对象。这个方法是这样的,先把网站中使用的每个图片的地址(URL)放到一个数组中。
var myImages = ["image_1.jpg', 'image_2.jpg', 'image_3.jpg', ...];
然后遍历这个数组,根据图片地址创建各自的image对象。这样可以保证所有的图片都能被浏览器缓存,等用到的时候就无需等待了。
for (var i = 0; i <= myImages.length; i++) {
var img = new Image();
img.src = myImages[i];
}
此方案费时的地方是,不仅要制造一个包含每张图片地址的数组,还要维护它的一致性。网站的每个需求变更(添加或更改图片地址)都会影响到这个数组。试想频繁变更的应用,又拥有数百张图片,这真会让人筋疲力尽的。
图片自动预加载(带进度指示器)
一个更好的方式是自动收集图片的地址。首先要分析页面中(包括外链及内联)的样式表。这可以通过遍历“document.styleSheets”对象来获得页面使用的所有样式表。
for (var i = 0; i < document.styleSheets.length; i++){
接下来要找出样式表的根目录。用来得到各个图片的绝对地址。
var baseURL = getBaseURL(document.styleSheets[i].href);
考虑到浏览器的兼容性,必须同时检查每个样式表的“cssRules”或“rules”中是否包含CSS规则。
if (document.styleSheets[i].cssRules) {
cssRules = document.styleSheets[i].cssRules
}
else if (document.styleSheets[i].rules) {
cssRules = document.styleSheets[i].rules
}
所有非空的CSS规则都要被解析,来确认它是否关联了图片。一个简单的正则表达式就可以解析出图片地址。
var cssRule = cssRules[j].style.cssText.match(/[^\(]+\.(gif|jpg|jpeg|png)/g);
然后,把这里收集到的所有图片地址保存到一个数组中供后面使用。
function analyzeCSSFiles() {
var cssRules; // CSS rules
for (var i = 0; i < document.styleSheets.length; i++) { // loop through all linked/inline stylesheets
var baseURL = getBaseURL(document.styleSheets[i].href); // get stylesheet's base URL
// get CSS rules
if (document.styleSheets[i].cssRules) {
cssRules = document.styleSheets[i].cssRules
}
else if (document.styleSheets[i].rules) {
cssRules = document.styleSheets[i].rules
}
// loop through all CSS rules
for (var j = 0; j < cssRules.length; j++) {
if (cssRules[j].style && cssRules[j].style.cssText) {
// extract only image related CSS rules
// parse rules string and extract image URL
var cssRule = cssRules[j].style.cssText.match(/[^\(]+\.(gif|jpg|jpeg|png)/g);
if (cssRule) {
// add image URL to array
cssRule = (cssRule + "").replace("\"", "")
imageURLs.push(baseURL + cssRule);
}
}
}
}
}
数组中存放的图片地址是绝对路径,为了得到它,我们实现了“getBaseUrl”函数来解析每个CSS文件的绝对地址。
function getBaseURL(cssLink) {
cssLink = (cssLink) ? cssLink : 'window.location.href'; // window.location.href for inline style definitions
var urlParts = cssLink.split('/'); // split link at '/' into an array
urlParts.pop(); // remove file path from URL array
var baseURL = urlParts.join('/'); // create base URL (rejoin URL parts)
if (baseURL != "")
{
baseURL += '/'; // expand URL with a '/'
}
return baseURL;
}
现在,遍历这个列表,为网站的每个图片创建一个JavaScript图片对象,来实现图片预加载并强制浏览器进行缓存。请注意“setTimeout”的使用,它确保了每个图片加载是依序执行的,当前图片加载完成才会加载下一个。原因是某些浏览器无法同时处理超过2个请求(译者注:IE6单域下的并发连接数限制就是2个)。为了避免可能的死锁,这里使用jQuery的bind方法给“load”、“onreadystatechange”和“error”事件绑定了一个处理器。这样可以确保遇到无法加载的遗失图片时,“errorTimer”可以把你带回正确的轨道。
function preloadImages() {
if (imageURLs && imageURLs.length && imageURLs[imagesLoaded]) { // if image URLs array isn't empty
var img = new Image(); // create a new imgage object
img.src = imageURLs[imagesLoaded]; // set the image source to the extracted image URL
setTimeout(function () {
if (!img.complete) {
jQuery(img).bind('onreadystatechange load error', onImageLoaded); // bind event handler
} else {
onImageLoaded(); // image loaded successfully, continue with the next one
}
errorTimer = setTimeout(onImageLoaded, 1000); // handle missing files (load the next image after 1 second)
}, 25);
}
else {
showPreloadedImages();
}
}
function onImageLoaded() {
clearTimeout(errorTimer); // clear error timer
imagesLoaded++; // increase image counter
preloadImages(); // preload next image
}
为了提升预加载时的用户体验,这里对“onImageLoaded”事件处理器做点改动,来添加一个进度条。
首先,引入jQuery UI的样式和显示进度条所需要的JavaScript文件。
<link type="text/css" href="css/ui-lightness/jquery-ui-1.8.6.custom.css" rel="stylesheet" />
<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.6.custom.min.js"></script>
然后在DOMReady事件被触发时初始化进度条。
$(document).ready(function () {
$("#progressbar").progressbar({ value: 0 }); // initialize progress bar
});
最后要做的一件事是扩展“onImageLoaded”事件处理函数。每加载完一张图片,就计算一次进度并更新进度条。
为了验证预加载的效果,这里把所有图片都添加到页面中。在预加载全部完成时,所有的图片会同时显示。
function onImageLoaded() {
clearTimeout(errorTimer); // clear error timer
$("#imagelist").append("<span>" + imagesLoaded + ": </span><img src='" + imageURLs[imagesLoaded] + "'/>"); // append image tag to image list
imagesLoaded++; // increase image counter
var percent = parseInt(100 * imagesLoaded / (imageURLs.length - 1)); // calculate progress
$("#progressbar").progressbar({ value: percent }); // refresh progress bar
$("#progressbarTitle").text("Preloading progress: " + percent + "%");
preloadImages(); // preload next image
}
优秀只需一小步
预加载图片是一个提升用户体验,以及让自己的网站看起来更专业的一个途径。通过自动分析CSS规则来进行图片的批量预加载也避免了大量的体力活。进度条可以让用户知道加载的进展,避免用户的冷落感。另外,jQuery提供了大批优秀组件,进度条就是其中一个,只需简单的配置就可以满足我们的需求。使用它们无疑能显著提升你的网站形象。
希望这篇文章能给你带来灵感,去思考你的项目是否也能从这里描述的技术受益。
最后附上zip文件,它包含所有上面的预加载示例文件。下载并解压后,用浏览器打开preloading.html,并单击“Start preloading”就可以观看示例了。
再做些简单修改,你就可以把它集成到你自己的项目里了。
原文:Improving User Experience: Preload Images
相关文章推荐
- 利用简洁的图片预加载组件提升h5移动页面的用户体验
- 为网站图片增加延迟加载功能,提升用户体验
- 利用简洁的图片预加载组件提升h5移动页面的用户体验
- 利用简洁的图片预加载组件提升h5移动页面的用户体验
- 利用简洁的图片预加载组件提升h5移动页面的用户体验--转载
- 【Android】提升用户体验,ListView显示加载中动画及空数据视图
- paip.提升用户体验---提取FLASH中图片
- 提升网页加载速度和体验以及图片优化的方法
- ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,下面就说实现方法,先贴上主方法的代码:
- SEO优化:网页加载速度优化提升用户体验
- 花瓣网方砖布局 图片内容无限加载 用户体验才是王道
- 前端图片懒加载(lazyload)的实现方法(提高用户体验)
- Paip.提升用户体验------在C++ Builder 不规则图片按钮实现总结
- 一个页面上有大量的图片(大型电商网站),加载很慢,你有哪些方法优化这些图片的加载,给用户更好的体验。
- 前端如何实现图片懒加载(lazyload) 提高用户体验
- 【转】使用jquery实现图片预加载提高页面加载速度和用户体验
- 图片显示提高用户体验—JS实现—图片预加载,图片延迟加载
- 前端如何实现图片懒加载(lazyload) 提高用户体验
- paip.提升用户体验---上传文件图片命名
- paip.提升用户体验-------在C++ Builder 中为Form窗体添加背景图片