在 Web 中展示图片
Web 支持使用标准的 Image
组件来展示图片。然而,Web 浏览器和手机以及桌面平台相比,在处理图片上会有一定的局限性,因为它需要以安全的方式运行未信任的代码。本页面内容解释了这些限制,并提供一些解决方法。
背景
#本节概括了 Flutter Web 中可用的技术,下述的解决方案都基于此。
Flutter 中的图片
#Flutter 提供了 Image
组件以及底层的 dart:ui/Image
类来渲染图片。
Image
组件的功能足够满足大部分使用场景。
dart:ui/Image
类可用于需要精细控制图片的场景。
Web 中的图片
#Web 提供了多种展示图片的方式,下面是几种常见的:
每种方式都有各自的优缺点。例如:内置的元素和其他 HTML 元素完美契合,并且自带浏览器缓存、内置图片优化和内存管理的优势。这使得你可以安全地展示任意来源的图片(超越了下节中的 CORS)。当图片必须和 <canvas>
元素中渲染的其他内容适配时,drawImage
更合适。当 CORS 政策允许时,你也可以获取图片尺寸的控制权,读取像素信息用于进一步处理。最后,WebGL 给予了你最大限度的图片控制权。你不仅可以读取像素信息、应用自定义的图片算法,还可以使用 GLSL 实现硬件加速。
跨域资源共享 (CORS)
#CORS 是一种浏览器用来控制一个站点如何获取另一个站点的资源的机制。默认情况下,一个网站不允许使用 XHR 或者 fetch
的方式向另一个站点发送 HTTP 请求。这样可以阻止另一个站点代表用户执行脚本,以及无需权限就可以获取另一个站点的资源。
当使用 <img>
、<picture>
或者 <canvas>
时,如果浏览器发现图片来源于另一个站点,且 CORS 政策不允许访问数据时,浏览器会自动阻止信息的访问权限。
WebGL 需要访问图片信息以用于渲染图片。因此要想使用 WebGL 渲染图片,该图片的来源服务所在的域名必须配置有效且可用的 CORS 策略。
Web 中的 Flutter 渲染器
#Flutter 在 Web 中提供了两种可供选择的渲染器:
CanvasKit
该渲染器使用了 WebGL 渲染 UI,因此需要访问图片的像素信息。
HTML
该渲染器使用了 HTML、CSS、Canvas 2D 和 SVG 组合的方式渲染 UI。使用 <img>
元素渲染图片。
因为 HTML 渲染器使用了 <img>
元素,所以可以展示任意来源的图片。但是,这也给你带来了以下限制:
-
对
Image.toByteData
的支持有限。 -
不支持
OffsetLayer.toImage
和Scene.toImage
。 -
无法获取动图中的帧信息(
Codec.getNextFrame
,frameCount
永远为 1,repetitionCount
永远为 0)。 -
不支持
ImageShader
。 -
应用于图片的着色器效果的支持有限。
-
不可控制图片内存(
Image.dispose
无效)。内存由浏览器自行控制。
CanvasKit 完全实现了 Flutter 中的图片 API。但它需要访问图片的像素信息,因此受制于 CORS 政策。
解决方案
#内存、asset 和同源网络图片
#如果图片在应用内存中有编码后的字节信息、或者以 asset 的方式提供、或者和应用存储在同一服务器上(也就是同源),则不需要做额外工作。图片既可以在 HTML 也可以在 CanvasKit 模式下,使用 Image.memory
、
Image.asset
和 Image.network
来展示。
跨域图片
#HTML 渲染器可以加载跨域图片,无需额外配置。
CanvasKit 需要应用获取编码后的图片的字节信息。有多种获取方式,如下文所述。
在支持 CORS 的 CDN 中部署你的图片
#通常,可以配置内容分发网络 (CDN) 来自定义哪些域名可以访问你的内容。例如:Firebase 站点托管允许在 firebase.json
文件中,
指定一个自定义的 Access-Control-Allow-Origin
头。
没有图片服务器控制权?使用一个 CORS 代理
#如果无法从你的应用层面去配置图片服务器的 CORS,你依然可以通过另一个服务器代理请求,从而加载图片。这要求中转服务器对图片加载有充分的访问权。
此方法适用于源图片服务器公开提供了图片,却没有正确配置 CORS 头的情况。
例子:
在平台视图中使用 <img>
#
Flutter 支持在应用中使用 HtmlElementView
嵌入 HTML。通过它可以创建一个 <img>
元素来渲染另一个域名的图片。但是,一定要记住,此方法也会受到
Web 中的 Flutter 渲染器 一节中提到的限制。
除非另有说明,本文档之所提及适用于 Flutter 的最新稳定版本,本页面最后更新时间: 2024-09-04。 查看文档源码 或者 为本页面内容提出建议。