使用 Angular 管理图像断点
已发表: 2022-03-10作为 Web 开发人员,我们经常需要创建响应式和媒体丰富的应用程序。 有这样的要求意味着我们需要处理图像断点以及媒体查询,因为我们希望为最终用户提供最佳体验。 添加到需求列表中,我们可能需要使用前端框架,例如 Angular,它非常适合创建 SPA 和其他应用程序类型。
在本文中,我们将了解图像断点、它们的用例以及整个动手示例; 我们将使用 Angular 自己的 BreakPoint Observer 在 Angular 应用程序中实现它们。 在使用这种方法时,我们还将强调为什么这个流行的框架可以帮助我们以无缝的方式使用上述技术。
图像断点和响应式图像
在响应式布局时代(我们根据视口大小捕获断点并根据断点更改页面布局),我们还需要确保图像可以以正确的尺寸显示——即使在布局之后改变。 对于现代响应式网站来说,选择正确的图像是相当具有挑战性的。
让我们讨论一下开发人员目前可以使用的两个选项。
srcset
srcset
让我们定义一个图像列表,浏览器根据渲染的<img>
大小和显示的密度在这些图像之间切换。
我们来看一个例子:
<img src="tuscany.jpg" />
在上面,我们指定了 3 张图像,其中w
表示图像的像素宽度。 当将上述内容与srcset
一起使用时,我们还需要指定sizes
属性(这是必需的,因为规范要求如果我们使用srcset
和w
,我们也必须有一个 sizes 属性)。 这个属性的目的是什么? 浏览器需要在布局页面之前从源集中选择要加载的资源(在他们知道图像最终会有多大之前)。 我们可以将sizes
视为对浏览器的提示,在布局之后,图像将占据视口宽度的 100%(这就是vw
所指的)。 浏览器在加载时知道实际的视口宽度(以及图像的 DPR),因此它可以通过数学计算来确定它需要什么大小的资源并从源集中选择一个。
<picture>
和<source media="">
元素组合让我们可以切换图像资源以响应媒体查询,例如布局断点处的那些。
让我们也看一个这样的例子:
<picture> <source media="(min-width: 1440px)"> <source media="(min-width: 900px)"> <source media="(min-width: 600px)"> <img src="../assets/images/tuscany-sm.jpg" /> </picture>
使用您选择的具有小尺寸、中尺寸和大尺寸的图像在本地更改上面的代码。 请注意,通过调整浏览器大小,您将获得不同的图像。
以上所有内容的关键要点是,如果我们想在特定断点处交换图像,我们可以使用<picture>
元素将媒体查询直接放入标记中。
注意:如果您有兴趣探索<picture>
和srcset
+ sizes
之间的区别,我建议您阅读 Eric Portis 的精彩文章: srcset
and sizes
。
到目前为止,我们已经讨论了如何在纯 HTML 环境中使用图像断点和媒体查询。 即使完全不必指定媒体查询,如果有一种方便的、几乎半自动化的方式来生成图像断点以及断点的相应图像,难道不是更好吗? 幸运的是,Angular 有一个内置机制来帮助我们,我们还将看看使用第三方服务根据特定条件动态生成适当的图像。
角度布局模块
Angular 带有一个布局模块,它位于 CDK(组件开发工具包)工具集中。 Angular CDK 包含经过充分测试的工具来帮助进行组件开发。 CDK 的一部分是包含BreakpointObserver
的布局模块。 这个助手提供了对媒体查询断点的访问,这意味着当浏览器大小(屏幕大小)直观地改变时,组件(及其内容)可以适应变化。
推荐阅读:布局模块
现在我们已经了解了理论,让我们开始做生意并创建一个将实现响应式图像断点的应用程序。 在第一次迭代中,我们将通过 Angular CLI 创建应用程序的外壳: ng new bpo
并选择必要的选项。
要使用BreakpointObserver
,我们还需要安装 Angular 的 CDK 布局模块,我们可以通过 npm 来完成: npm i @angular/cdk
。
安装后,我们将能够向我们希望的任何组件添加必要的导入语句:
// app.component.ts import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
使用BreakpointObserver
我们可以订阅视口宽度的变化,Angular 为我们提供了方便的访问器,这意味着我们根本不需要使用媒体查询! 让我们继续尝试一下:
// app.component.ts constructor(public breakpointObserver: BreakpointObserver) { } ngOnInit() { this.breakpointObserver.observe([ Breakpoints.XSmall, Breakpoints.Small, Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge ]).subscribe(result => { if (result.breakpoints[Breakpoints.XSmall]) { // handle XSmall breakpoint } if (result.breakpoints[Breakpoints.Small]) { // handle Small breakpoint } if (result.breakpoints[Breakpoints.Medium]) { // handle Medium breakpoint } if (result.breakpoints[Breakpoints.Large]) { // handle Large breakpoint } if (result.breakpoints[Breakpoints.XLarge]) { // handle XLarge breakpoint } }); }
如前所述,上面的访问器属性以下列方式反映媒体查询:

-
Breakpoints.XSmall
: 最大宽度 = 599.99px -
Breakpoints.Small
:最小宽度 = 600 像素和最大宽度 = 959.99 像素 Breakpoints.Medium
:最小宽度 = 960px 和最大宽度 = 1279.99px-
Breakpoints.Large
: min-width = 1280px 和 max-width = 1919.99px -
Breakpoints.XLarge
: 最小宽度 = 1920px
我们现在一切就绪,这意味着我们可以开始生成适当的图像。
图像的响应断点
我们有几个选项来生成响应式图像:
- 响应式图像断点生成器
使用这个工具,我们可以上传任何图像,设置各种选项,例如我们希望生成的图像数量。 运行该工具后,我们将获得有关生成图像的可视化表示,我们可以将它们下载为 zip 文件以及一些使用前面提到的<picture>
元素的生成代码。 - 另一种解决方案是为我们的项目创建一个构建步骤,以通过 NPM 存储库中可用的一些包生成断点,例如
gulp-responsive
或grunt-responsive-images
。 这两者都依赖于我们需要为我们的操作系统安装的其他库。 (请检查相应的存储库以获取更多信息。) - 另一种解决方案是使用 Cloudinary 之类的服务来存储图像并以我们只需要修改所请求资源的 URL 的大小和格式提供它们。 这将是我们的方法,因为这给了我们最大的灵活性。
推荐阅读: Eric Portis 使用响应式图像断点生成器自动化艺术指导
我已将原始图像上传到我的 Cloudinary 帐户,这意味着我可以通过以下 URL 访问该图像:
https://res.cloudinary.com/tamas-demo/image/upload/breakpoints-article/tuscany.jpg
这是我们将使用的全尺寸、原始、原始和未更改的图像。
我们可以修改图像的 URL 以生成更小的版本。 例如,如果我们想要一个宽度为 600 像素的图像,我们可以将 Cloudinary URL* 更新为以下内容:
https://res.cloudinary.com/tamas-demo/image/upload/w_600/breakpoints-article/tuscany.jpg
* 注意添加到 URL 的w_600
。
希望到此为止,您会看到这一切的发展方向。 基于上述方法,我们可以很快开始为正确的断点生成正确的图像。
使用 Cloudinary 意味着我们不需要创建、存储和管理同一图像的多个版本——它由 Cloudinary 即时为我们完成。
让我们更新我们的代码:
<!-- app.component.html --> <div> <h1>Current breakpoint: {{ breakpoint }}</h1> <img [src]="imagePath"> </div>
// app.component.ts import { Component, OnInit } from '@angular/core'; // ... export class AppComponent implements OnInit { imagePath; constructor(public breakpointObserver: BreakpointObserver) { } ngOnInit() { this.breakpointObserver.observe([ ... } }
我们可以从前面提到的列表中选择任意数量的断点来观察,并且由于我们有一个观察者,我们可以订阅更改并对其采取行动:
this.breakpointObserver.observe([ Breakpoints.XSmall, Breakpoints.Small, Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge ]).subscribe(result => { if (result.breakpoints[Breakpoints.XSmall]) { // handle this case } });
为了处理 Cloudinary 中不同图像的选项,我们将使用一种非常容易遵循的方法。 对于每种情况,我们将创建一个选项变量并更新最终的 Cloudinary URL。
在组件定义的顶部添加以下内容:
// app.component.ts imagePath; breakpoint; cloudinaryOptions; baseURL = 'https://res.cloudinary.com/tamas-demo/image/upload/breakpoints-article/tuscany.jpg';
并将以下内容添加到第一个if
语句中:
// app.component.ts let url = this.baseURL.split('/'); let insertIndex = url.indexOf('upload'); const options = 'c_thumb,g_auto,f_auto,q_auto,w_400'; url.splice(insertIndex + 1, 0, options); this.imagePath = url.join('/'); this.breakpoint = Breakpoints.XSmall;
结果将是一个更新的 Cloudinary URL:
https://res.cloudinary.com/tamas-demo/image/upload/c_thumb,g_auto,f_auto,q_auto,w_400/breakpoints-article/tuscany.jpg
我们在这里设置的选项是什么?
-
c_thumb
(生成图像的缩略图); -
g_auto
(专注于最有趣的部分;我们在缩略图中看到了大教堂); -
f_auto
(为给定浏览器提供最合适的格式,即 Chrome 的 WebP); -
q_auto
(在不影响视觉效果的情况下降低图像的质量,从而降低整体尺寸); -
w_400
(将图像的宽度设置为 400 像素)。
出于好奇,让我们将原始图像大小与这个新生成的图像进行比较:2.28 MB 与 29.08 KB!
我们现在有一个简单的工作:我们需要为不同的断点创建不同的选项。 我在 StackBlitz 上创建了一个示例应用程序,因此您可以立即对其进行测试(您也可以在此处查看预览)。
结论
当今网络中使用的各种桌面和移动设备以及媒体数量已经达到了惊人的水平。 作为 Web 开发人员,我们必须站在创建可在任何设备上运行且不影响视觉体验的 Web 应用程序的最前沿。
有很多方法可以确保将正确的图像加载到正确的设备(甚至在调整设备大小时)。 在本文中,我们回顾了一种利用称为 BreakPoint Observer 的内置 Angular 功能的方法,它为我们提供了一个强大的界面来处理响应式图像。 此外,我们还研究了一项允许我们在云中提供、转换和管理图像的服务。 拥有如此引人注目的工具,我们仍然可以创建身临其境的视觉网络体验,而不会失去访问者。