之前的文章中,我们讨论了图片的尺寸自适应、裁切与缩放、压缩、动态webp等技术。这些技术都是对单张图片的处理,而在实际项目中,我们往往需要处理大量的图片。本文将讨论如何高效批量优化图片,并介绍一些图片加载技巧。
图片预加载(Preloading Images)是一种提前加载即将使用的图片资源的技术。通过在页面加载时就将未来可能用到的图片资源进行预加载,可以在用户真正需要这些图片时,减少等待时间,提升用户体验。
HTML中的预加载
在HTML中,可以通过<link>标签的rel属性来实现图片预加载。例如,我们可以在页面的`<head>`标签中添加如下代码:
<link rel="preload" href="image.jpg" as="image" fetchpriority="high">
该 <link> 标签用于预加载一个图片资源。让我们逐个解释其中的属性及其作用:
当前<link>标签的用途是预加载资源。preload告诉浏览器提前加载指定的资源(在这里是图片),以便在后续使用时能够更快地提供资源。这有助于提高页面的加载性能,尤其是在资源密集型的网站上。
指定要预加载的资源的URL。href属性是一个URL,指向需要预加载的资源。在这个例子中,image.jpg是要预加载的图片的路径。
指定预加载资源的类型。as属性告诉浏览器预加载资源的类型,以便正确地处理和优化加载过程。在这个例子中,as="image"明确了资源是一个图片。这对于浏览器优化资源加载顺序和优先级非常重要。
指定预加载资源的获取优先级。fetchpriority属性是一个新的属性,用于指示浏览器在预加载资源时的优先级。在这个例子中,fetchpriority="high"告诉浏览器这是一个高优先级的资源,应该尽快加载。这在需要确保关键资源(如首屏图片)快速加载时非常有用。
CSS中的预加载
在CSS中,可以通过background-image属性来实现图片预加载。例如,我们可以在CSS文件中添加如下代码:
.preload {
background-image: url('image.jpg');
}
这段CSS代码定义了一个`.preload`类,其中包含了一个 background-image 属性,指定了要预加载的图片资源的URL。在页面加载时,浏览器会提前加载这个图片资源,以便在后续使用时能够更快地提供资源。
JavaScript中的预加载
在JavaScript中,可以通过Image对象来实现图片预加载。例如,我们可以在JavaScript代码中添加如下代码:
var img=new Image();
img.src='image.jpg';
这段JavaScript代码创建了一个新的Image对象,并设置了src属性为要预加载的图片资源的URL。当这段代码执行时,浏览器会开始加载这个图片资源,以便在后续使用时能够更快地提供资源。
二、图片懒加载
图片懒加载(Lazy Loading Images)是一种延迟加载图片资源的技术。通过在页面加载时只加载可见区域内的图片资源,可以减少页面的加载时间,提升用户体验。
img loading属性
在HTML中,可以通过loading属性来实现图片懒加载。例如,我们可以在<img>标签中添加如下代码:
<img src="image.jpg" loading="lazy" alt="Image">
loading属性是一个新的属性,用于指定图片的加载方式。它有三个可能的值:
Intersection Observer API
在JavaScript中,可以通过Intersection Observer API来实现图片懒加载。Intersection Observer API是一种用于监视元素与视口交叉状态的API,可以用于实现懒加载、无限滚动等功能。
例如,我们可以在JavaScript代码中添加如下代码:
// 创建一个IntersectionObserver实例
const intersectionObserver=new IntersectionObserver((entries)=> {
entries.forEach(entry=> {
if (entry.isIntersecting) {
// 当元素与视窗交叉时执行的操作
const img=entry.target; // entry.target是交叉的元素
// 假设data-src属性包含了图片的路径
img.src=img.dataset.src;
intersectionObserver.unobserve(img); // 停止观察该元素
}
});
});
// 为所有需要滚动加载的元素(例如图片)设置观察
document.querySelectorAll('img[data-src]').forEach((img)=> {
intersectionObserver.observe(img);
});
这段JavaScript代码创建了一个IntersectionObserver实例,并为所有带有data-src属性的图片元素设置了观察。当图片元素与视口交叉时,会加载图片资源,并停止观察该元素。
Scroll事件
在JavaScript中,也可以通过监听scroll事件来实现图片懒加载。例如,我们可以在JavaScript代码中添加如下代码:
// 获取所有带有data-src属性的图片元素
const lazyImages=document.querySelectorAll('img[data-src]');
// 懒加载函数
function lazyLoad() {
lazyImages.forEach((img)=> {
if (img.offsetTop < window.innerHeight + window.pageYOffset + 200) {
img.src=img.dataset.src;
img.removeAttribute('data-src');
}
});
// 更新 lazyImages,排除已加载的图片
lazyImages=document.querySelectorAll('img[data-src]');
// 如果所有的图片都已经加载,则移除事件监听器
if (lazyImages.length===0) {
document.removeEventListener('scroll', lazyLoad);
}
}
// 监听scroll事件
document.addEventListener('scroll', lazyLoad);
// 初始检查一次,以便在页面加载时懒加载位于视窗中的图片
lazyLoad();
这段JavaScript代码监听了scroll事件,并在图片元素进入视口时加载图片资源。当图片进入视口时,会加载图片资源,并移除data-src属性。
结合多种方法来实现图片懒加载
在实际项目中,我们可以结合多种方法来实现图片懒加载,以便在不同浏览器和环境下提供最佳的用户体验。例如,我们可以先检查浏览器是否支持loading属性,如果支持,则使用`loading`属性实现图片懒加载;如果不支持,则检查浏览器是否支持Intersection Observer API,如果支持,则使用Intersection Observer API实现图片懒加载;如果不支持,则使用scroll事件实现图片懒加载。
下面是一个示例代码,演示了如何结合多种方法来实现图片懒加载:
html
<body>
<img src="placeholder.jpg" data-src="image1.jpg" alt="Description 1">
<img src="placeholder.jpg" data-src="image2.jpg" alt="Description 2">
<img src="placeholder.jpg" data-src="image3.jpg" alt="Description 3">
<!-- 更多 img -->
<script src="lazyload.js"></script>
</body>
javascript
const lazyImages=document.querySelectorAll('img[data-src]');
// 判断浏览器是否支持 loading 属性
if('loading' in HTMLImageElement.prototype) {
lazyImages.forEach(img=> {
img.src=img.dataset.src;
});
} else if('IntersectionObserver' in window) {
// 使用Intersection Observer API实现懒加载
const intersectionObserver=new IntersectionObserver((entries)=> {
entries.forEach(entry=> {
if (entry.isIntersecting) {
const img=entry.target;
img.src=img.dataset.src;
intersectionObserver.unobserve(img);
}
});
});
lazyImages.forEach((img)=> {
intersectionObserver.observe(img);
});
} else {
// 使用scroll事件实现懒加载
let lazyImages=document.querySelectorAll('img[data-src]');
function lazyLoad() {
lazyImages.forEach((img)=> {
if (img.offsetTop < window.innerHeight + window.pageYOffset + 200) {
img.src=img.dataset.src;
img.removeAttribute('data-src');
}
});
lazyImages=document.querySelectorAll('img[data-src]');
if (lazyImages.length===0) {
document.removeEventListener('scroll', lazyLoad);
}
}
document.addEventListener('scroll', lazyLoad);
lazyLoad();
}
三、渐进式图片加载
图片渐进式加载(Progressive Image Loading)是一种逐步加载图片资源的技术。通过在图片加载过程中逐步显示模糊的低分辨率图片,可以提升用户体验,减少等待时间。这种技术不仅适用于优化页面性能,还可以为用户提供视觉上的反馈,使页面显得更加流畅。
渐进式 JPEG
渐进式 JPEG (Progressive JPEG) 是一种通过逐步显示图片的技术,渐进式 JPEG 与标准的 JPEG 图片区别在于,渐进式 JPEG 图片在加载时会逐步显示图片的分辨率,而不是一次性显示完整的图片。这种逐步加载的方式可以提升用户体验,减少等待时间。渐进式 JPEG 图片最初会显示的是一张模糊的低分辨率图片,随着数据的不断加载,图片的分辨率会逐步提高,直至达到全分辨率。这种方法特别适合需要加载大图的场景。
许多图像编辑工具和压缩工具都支持将图片保存为渐进式 JPEG。在实际项目中,例如,在 Photoshop 中保存图片时,可以勾选“渐进式”选项。也可以使用命令行工具如ImageMagick(https://imagemagick.org/index.php)来生成渐进式 JPEG:
1convert input.jpg -interlace Plane output.jpg
需要注意的是渐进式 JPEG 图片的文件大小通常会比标准的 JPEG 图片稍大,因为渐进式 JPEG 图片包含了更多的数据,用于逐步显示图片的分辨率,但是这种额外的数据可以提升用户体验。因此,在选择使用渐进式 JPEG 图片时,需要权衡图片质量和文件大小之间的关系。
占位图技术
占位图技术(Placeholder Image)通常使用一个非常小的、模糊的低分辨率图像作为占位符,在高分辨率图像加载完成之前先显示出来。这种方法通过减少初始加载时间和网络请求,可以显著提升页面的首屏加载速度。
占位图实现原理很简单,只需要在页面中插入一个占位图像,然后在高分辨率图像加载完成后替换为真实图像即可。
代码示例:
html:
<img src="https://fs.autohome.com.cn/energyspace_views/image_demo/compress_before.png?format=webp&dis_rule=20x0_q50_" data-src="https://fs.autohome.com.cn/energyspace_views/image_demo/compress_before.png?format=webp&dis_rule=400x0_q90_" alt="Description">
javascript:
document.addEventListener('DOMContentLoaded', function() {
const lazyImages=document.querySelectorAll('img[data-src]');
lazyImages.forEach(img=> {
const placeholder=new Image();
placeholder.src=img.src;
placeholder.onload=()=> {
img.src=img.dataset.src;
};
});
});
img src 属性中的图片是一个模糊的小图,data-src 属性中的图片是高分辨率图像。在页面加载时,先显示模糊的小图,待高分辨率图像加载完成后再替换。
使用占位图技术可以有效减少页面的加载时间,提升用户体验。同时,占位图技术也可以结合图片懒加载技术一起使用,进一步提升页面性能。
四、Base64 编码
在 Web 开发中,将图片转换为 Base64 编码是一种优化页面加载速度的方法,但需要权衡其优缺点。一般来说,适用于 Base64 编码的图片大小取决于几个因素,包括页面的总体加载时间、HTTP 请求的数量以及文件大小。
Base64 编码的优点
Base64 编码的缺点
适合转为 Base64 的图片大小一般为 1KB 到 10KB 的图片:通常,文件大小在 1KB 到 10KB 之间的图片是转为 Base64 编码的最佳选择。这样的图片往往是小图标、按钮、背景图案等。对于这些小图片,Base64 编码可以显著减少 HTTP 请求的数量,从而提升页面加载速度。
在实际Web项目开发中,使用 Webpack或 Vite 将小图片自动转换为 Base64 编码是一个常见的优化方法。这种自动化的处理可以简化开发流程,并确保在构建过程中优化资源。
webpack 配置示例:
module.exports={
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 10240, // 10KB
},
},
],
},
],
},
};
Vite 配置示例:
import { defineConfig } from 'vite';
export default defineConfig({
build: {
assetsInlineLimit: 10240, // 10KB
},
});
在以上配置中,limit 或 assetsInlineLimit 选项指定了图片转为 Base64 编码的阈值,超过这个阈值的图片将被单独打包为文件,而小于这个阈值的图片将被转为 Base64 编码。
五、结语
通过结合多种图片加载与优化技术,可以提升页面性能,提供更好的用户体验。预加载、懒加载、渐进式加载等技术在不同场景下有着不同的优势,通过合理地选择和组合这些技术,可以有效地优化图片加载过程。
在实际项目中,建议根据项目的具体需求,选择合适的技术和工具进行图片优化和加载。希望本文所介绍的技术和示例代码能够帮助您更好地实现图片批量处理与加载优化,提升网页的加载速度和用户体验。
WEB 图片优化的相关文章到此结束,希望对你有所帮助。如果有任何问题或建议,欢迎在评论区留言,谢谢!
作者:之家-梁家玮
来源-微信公众号:之家前端共享流
出处:https://mp.weixin.qq.com/s/bhxtIED32lJP7PY9g28GNA
网页设计中,添加图片并为其添加超链接是常见的需求。通过使用HTML,我们可以轻松实现这些功能。下面将详细介绍如何实用地添加图片,并为图片添加超链接。
html代码
首先,我们需要了解HTML中如何添加图片。在HTML中,我们使用`<img>`标签来插入图片。`<img>`标签有几个重要的属性,包括`src`、`alt`和`width`、`height`等。`src`属性用于指定图片的URL地址,`alt`属性用于提供图片无法加载时的替代文本,而`width`和`height`属性则用于设置图片的宽度和高度。
下面是一个简单的示例,展示如何在HTML中添加图片:
<img src="这里写图片地址,要带http协议,比如:https://www.chaojilu.com" alt="看不到图片,就显示这个文字" width="500" height="300">
在这个示例中,我们使用了`<img>`标签,并通过`src`属性指定了图片的URL地址。同时,我们还设置了`alt`属性以提供替代文本,并通过`width`和`height`属性设置了图片的尺寸。
接下来,我们来看如何为图片添加超链接。在HTML中,我们使用`<a>`标签来创建超链接。`<a>`标签的`href`属性用于指定链接的目标地址。为了将图片包含在超链接中,我们可以将`<img>`标签放置在`<a>`标签内部。
下面是一个示例,展示如何为图片添加超链接:
<a href="https://www.chaojilu.com">
<img src="image.jpg" alt="看不到图片,就显示这个文字"width="这里写宽度" height="高度">>
</a>
在这个示例中,我们将`<img>`标签放置在`<a>`标签内部,并通过`href`属性指定了链接的目标地址。当用户点击图片时,将会跳转到指定的网址。同时,我们还通过`alt`属性为图片提供了替代文本,以便在图片无法加载时为用户提供提示。
除了基本的添加图片和超链接功能外,我们还可以通过一些技巧来优化图片的显示和加载效果。例如,我们可以使用CSS样式来设置图片的边框、圆角等外观属性,提升页面的美观度。同时,我们还可以通过压缩图片文件大小、使用懒加载等技术来优化图片的加载速度,提高用户体验。
需要注意的是,在添加图片和超链接时,我们需要确保所使用的图片资源是合法且可访问的。避免使用未经授权或侵权的图片资源,以免引发法律问题。同时,我们还应该关注图片的版权和使用协议,确保在使用图片时遵守相关规定。
总之,通过使用HTML的`<img>`和`<a>`标签,我们可以轻松地在网页中添加图片并为图片添加超链接。通过合理设置属性和优化技巧,我们可以提升图片的显示效果和加载速度,为用户提供更好的浏览体验。
各位鹿友有什么不懂可以在评论区留言,咱们一起探讨学习。
者:麦乐
来源:恒生LIGHT云社区
想要得到更好的性能体验,只靠资源压缩与恰当的文件格式选型,是很难满足期望的。我们还需要针对资源加载过程进行优化。
下图是京东商城的手机端首页,当元素没有滑动到视线内时,图片src属性放置了一个很小的图片,init_src属性放置了真正的图片,只要当该元素滑动到视线内部,才会将init_src属性赋值给src去加载真实的图片,这就是一个简单的图片延迟加载的过程。
就是事件监听的方式,通过监听scroll事件与resize事件,并在事件的回调函数中去判断,需要进行延迟加载的图片是否进入视窗区域。
我们只需要关注三个属性。
加入页面中有多张这样的图片需要加载。具体的JavaScript实现逻辑如下,在文档的DOMContentLoaded事件中,添加延迟加载处理逻辑,首先获取class属性名为lazy的所有〈img〉标签,将这些标签暂存在一个名为lazyImages的数组中,表示需要进行延迟加载但还未加载的图片集合。当一个图片被加载后,便将其从lazyImages数组中移除,直到lazyImages数组为空时,表示所有待延迟加载的图片均已经加载完成,此时便可将页面滚动事件移除。
这里使用了getBoundingClientRect()函数获取元素的相对位置.
rectObject=object.getBoundingClientRect();
rectObject.top:元素上边到视窗上边的距离;
rectObject.right:元素右边到视窗左边的距离;
rectObject.bottom:元素下边到视窗上边的距离;
rectObject.left:元素左边到视窗左边的距离;
对于只可上下滚动的页面,判断一个图片元素是否出现在屏幕视窗中的方法其实显而易见,即当元素上边缘距屏幕视窗顶部的top值小于整个视窗的高度window.innerHeight时,预加载的事件处理代码如下:
document.addEventListener(DOMContentLoaded, function() {
const imags=[].slice.call(document.querySelector('.lazy'))
const active=false; // 限制函数被频繁调动
function load() {
if(active===false) {
active=true
setTimeout(()=> {
imags.forEach((img)=> {
const objPos=img.getBoundingClientRect();
if(objPos.top <=window.innerHeight && objPos.bottom >=0 && img.display !=='done') {
img.src=img.dataset.src;
img.classList.remove('lazy')
imags.filter((i)=> (i !==img))
if(imags.length===0) {
document.removeEventListener('scroll', load)
window.removeEventListener('resize', load)
window.removeEventListener('orientationchange', load)
}
}
})
active=false
}, 200)
}
}
document.addEventListener('scroll', load)
window.addEventListener('resize', load)
window.addEventListener('orientationchange', load)
})
这种方式的有点就是兼容性比较好,缺点是频繁地进行计算必然会影响性能,代码也会比较繁琐。
现代浏览器已大多支持了Intersection Observer API,用一句话简述:每当因页面滚动或窗口尺寸发生变化,使得目标元素(target)与设备视窗或其他指定元素产生交集时,便会触发通过Intersection Observer API配置的回调函数,在该回调函数中进行延迟加载的逻辑处理,会比传统方式显得更加简洁而高效。
简单来说,目标元素的可见性变化时,就会调用观察器的回调函数 callback。
callback一般会触发两次。一次是目标元素刚刚进入视口(开始可见),另一次是完全离开视口(开始不可见)。
document.addEventListener(DOMContentLoaded, function() {
const imags=[].slice.call(document.querySelector('.lazy'))
if(window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype.intersectionRatio) {
var lazyImgObserver=new IntersectionObserver((entries, observer)=> {
entries.forEach((entry)=> {
if(entry.isIntersecting) {
var lazyImg=entry.target;
lazyImg.src=lazyImg.dataset.src;
lazyImg.classList.remove('lazy');
lazyImgObserver.unobserve(lazyImg)
}
})
})
imags.forEach((img)=> {
lazyImgObserver.observe(img)
})
}
})
这种方式判断元素是否出现在视窗中更为简单直观,应在实际开发中尽量使用,但其问题是并非所有浏览器都能兼容。
(1)做好尽量完备浏览器兼容性检查,对于兼容Intersection Observer API的浏览器,采用这种方式进行处理,而对于不兼容的浏览器,则切换回传统的实现方式进行处理。 (2)使用相应兼容的polyfill插件,在W3C官方GitHub账号下就有提供。
这种实现方式通过CSS的background-image属性来加载图片,与判断〈img〉标签src属性是否有要请求图片的URL不同,CSS中图片加载的行为建立在浏览器对文档分析基础之上。
document.addEventListener(DOMContentLoaded, function() {
const imags=[].slice.call(document.querySelector('.lazy'))
if(window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype.intersectionRatio) {
var lazyImgObserver=new IntersectionObserver((entries, observer)=> {
entries.forEach((entry)=> {
if(entry.isIntersecting) {
var lazyImg=entry.target;
lazyImg.classList.add('visible');
lazyImgObserver.unobserve(lazyImg)
}
})
})
imags.forEach((img)=> {
lazyImgObserver.observe(img)
})
}
})
这种方式限制于需要提前写好css样式。
除了上述通过开发者手动实现延迟加载逻辑的方式,从Chrome 75版本开始,已经可以通过〈img〉和〈iframe〉标签的loading属性原生支持延迟加载了,loading属性包含以下三种取值。
● lazy:进行延迟加载。 ● eager:立即加载。 ● auto:浏览器自行决定是否进行延迟加载。
测试:image标签就是 img
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- <script src="js/file2.js"></script> -->
<!-- <script src="js/file3.js"></script> -->
<!-- <link rel="stylesheet" href="css/index.css"> -->
<style>
img {
width: 700px;
height: 200px;
display: block;
}
</style>
</head>
<body>
<imgage loading="lazy" src='./image/home-1.png' alt="photo" />
<imgage loading="lazy" src='./image/home-2.png' alt="photo" />
<imgage loading="lazy" src='./image/home-3.png' alt="photo" />
<imgage loading="lazy" src='./image/home-4.png' alt="photo" />
<imgage loading="lazy" src='./image/home-5.png' alt="photo" />
<imgage loading="lazy" src='./image/home-6.png' alt="photo" />
<imgage loading="lazy" src='./image/home-7.png' alt="photo" />
<imgage loading="lazy" src='./image/home-8.png' alt="photo" />
<imgage loading="lazy" src='./image/home-9.png' alt="photo" />
<imgage loading="lazy" src='./image/home-10.png' alt="photo" />
<imgage loading="lazy" src='./image/home-11.png' alt="photo" />
<imgage loading="lazy" src='./image/home-12.png' alt="photo" />
<imgage loading="lazy" src='./image/home-13.png' alt="photo" />
<imgage loading="lazy" src='./image/home-14.png' alt="photo" />
<imgage loading="lazy" src='./image/home-15.png' alt="photo" />
<imgage loading="lazy" src='./image/home-16.png' alt="photo" />
<imgage loading="lazy" src='./image/home-17.png' alt="photo" />
<imgage loading="lazy" src='./image/home-18.png' alt="photo" />
<imgage loading="lazy" src='./image/home-19.png' alt="photo" />
<imgage loading="lazy" src='./image/home-20.png' alt="photo" />
<imgage loading="lazy" src='./image/home-21.png' alt="photo" />
<imgage loading="lazy" src='./image/home-22.png' alt="photo" />
<imgage loading="lazy" src='./image/home-23.png' alt="photo" />
<imgage loading="lazy" src='./image/home-24.png' alt="photo" />
<imgage loading="lazy" src='./image/home-25.png' alt="photo" />
<imgage loading="lazy" src='./image/home-26.png' alt="photo" />
<imgage loading="lazy" src='./image/home-27.png' alt="photo" />
<imgage loading="lazy" src='./image/home-28.png' alt="photo" />
<imgage loading="lazy" src='./image/home-29.png' alt="photo" />
<imgage loading="lazy" src='./image/home-30.png' alt="photo" />
</body>
</html>
可以看到,首次加载的个数是13个,首屏一般只能放下4个左右,13个以后的img滚动到视线内部会自动去加载。
实践发现有以下几个特点:
与JavaScript有关的几个行为特征:
*请认真填写需求信息,我们会在24小时内与您取得联系。