大图片,请别把我的页面撑破了——不,一秒都不行。

作者: nick 分类: js 发布时间: 2011-03-12 12:37 ė 6没有评论

示例:http://www.uini.net/resource/demo/autoIMG/

在上一篇文章 《再谈javascript图片预加载技术》中实现了获取图片文件头的尺寸数据,这篇文章将根据此写一个应用:让图片未加载完毕就实现按比例自适应,防止图片撑破布局(尤其是外链图片)。

为了防止图片撑破布局,最常见的仍然是通过onload后获取图片尺寸再进行调整,所以加载过程中仍然会撑破。而Qzone日志的图片在此进行了改 进,onload完毕后才显示原图。我以前用onload写过一个小例子:http://www.planeart.cn/?p=1022

通过imgReady可以跨浏览器在dom ready就可以实现图片自适应,无需等待img加载,代码如下:

// jQuery.autoIMG.js v0.2
// Tang Bin - http://planeArt.cn/ - MIT Licensed
(function ($) {

	var // 设置加载状态的替换图像
		tempPath = './images/loading.png',
		// 设置加载错误的替换图像
		errorPath = './images/error.png',
		// 检测是否支持css2.1 max-width属性
		isMaxWidth = 'maxWidth' in document.documentElement.style,
		// 检测是否IE7浏览器
		isIE7 = !-[1,] && !('prototype' in Image) && isMaxWidth;

	new Image().src = tempPath;

	$.fn.autoIMG = function () {
		var $this = this,
			// 获取容器宽度
			maxWidth = $this.width();

		return $this.find('img').each(function (i, img) {

			// 如果支持max-width属性则使用此,否则使用下面预加载方式
			if (isMaxWidth) return img.style.maxWidth = maxWidth + 'px';

			var path = img.getAttribute('data-src') || img.src,
				next = img.nextSibling,
				parent = img.parentNode,
				temp = new Image();

			// 删除img图像,并替换成loading图片
			img.style.display = 'none';
			img.removeAttribute('src');
			img.parentNode.removeChild(img);
			temp.src = tempPath;
			next ? next.insertBefore(temp) : parent.appendChild(temp);

			// 图片尺寸就绪执行
			imgReady(path, function (width, height) {
				if (width > maxWidth) {
					// 等比例缩放
					height = maxWidth / width * height,
					width = maxWidth;

					// 删除loading图像
					temp.parentNode.removeChild(temp);

					// 恢复显示调整后的原图像
					img.style.display = '';
					img.style.width = width + 'px';
					img.style.height = height + 'px';
					img.setAttribute('src', path);
					next ? next.insertBefore(img) : parent.appendChild(img);
				};
			}, function () {
				// 加载错误
				temp.src = errorPath;
				temp.title = 'Image load error!';
			});

		});
	};

	// IE7缩放图片会失真,采用私有属性通过三次插值解决
	isIE7 && (function (c,d,s) {s=d.createElement('style');d.getElementsByTagName('head')[0].appendChild(s);s.styleSheet&&(s.styleSheet.cssText+=c)||s.appendChild(d.createTextNode(c))})('img {-ms-interpolation-mode:bicubic}',document);

	// 获取图片头的尺寸数据
	// http://www.planeart.cn/?p=1121
	// @param	{String}	图片路径
	// @param	{Function}	获取尺寸的回调函数 (参数1接收width;参数2接收height)
	// @param	{Function}	加载错误的回调函数 (可选)
	var imgReady = function (url, callback, error) {
		var width, height, offsetWidth, offsetHeight, intervalId, check, div,
			accuracy = 1024,
			doc = document,
			container = doc.body || doc.getElementsByTagName('head')[0],
			img = new Image();

		img.src = url;

		// 如果图片被缓存,则直接返回缓存数据
		if (img.complete) {
			return callback(img.width, img.height);
		};

		// 向页面插入隐秘图像,监听图片尺寸就绪状态
		if (container) {
			div = doc.createElement('div');
			div.style.cssText = 'visibility:hidden;position:absolute;left:0;top:0;width:1px;height:1px;overflow:hidden';
			div.appendChild(img)
			container.appendChild(div);
			width = img.offsetWidth;
			height = img.offsetHeight;

			check = function () {
				offsetWidth = img.offsetWidth;
				offsetHeight = img.offsetHeight;

				// 如果图像尺寸开始变化,则表示浏览器已经获取了图片头数据并占位
				// 经过实测只有监听img.offsetWidth才有效,同时检测img.offsetHeight是为了保险
				// 如果新插入的图片面积大于预设尺寸,很可能是执行前图片以及在其他地方加载中,如基于webkit的浏览器
				if (offsetWidth !== width || offsetHeight !== height || offsetWidth * offsetHeight > accuracy) {
					clearInterval(intervalId);
					callback(offsetWidth, offsetHeight);

					// 清空img的事件与元素,避免IE内存泄漏
					img.onload = null;
					div.innerHTML = '';
					div.parentNode.removeChild(div);
				};
			};

			check();

			// 定期执行检测
			intervalId = setInterval(check, 150);
		};

		// 等待图片完全加载完毕
		// 这是一个保险操作,如果上面的监听尺寸方法失败则会启用此
		// 如果很小的图像有可能加载时间小于定时器定义的检测间隔时间,则会停止定时器
		img.onload = function () {
			callback(img.width, img.height);
			img.onload = img.onerror = null;
			clearInterval(intervalId);
			container && img.parentNode.removeChild(img);
		};

		// 图像加载错误
		img.onerror = function () {
			error && error();
			clearInterval(intervalId);
			container && img.parentNode.removeChild(img);
		};

	};

})(jQuery);

autoIMG压缩后:1.74kb,兼容:Chrome | Firefox | Sifari | Opera | IE6 | IE7 | IE8 | …

调用演示:$(‘#demo p’).autoIMG()

同样,令人愉悦的DEMO地址在这里:http://www.planeart.cn/demo/autoIMG/

后记:虽然有了上一篇文章imgReady技术的铺垫,我以为会很简单的实现这个图片自适应插件,可是过程中却在webkit内核的浏览器碰了一鼻子灰,后来才得知webkit有BUG未修复,我折腾许久后更新了imgReady函数。

planeArt.cn原创文章,原文地址: http://www.planeart.cn/?p=1157

本文出自 传播、沟通、分享,转载时请注明出处及相应链接。

本文永久链接: https://www.nickdd.cn/?p=1412

发表评论

您的电子邮箱地址不会被公开。

Ɣ回顶部