Flutter Web:图片相关及跨域问题

简介: 在flutter web上也可以使用Image这个widget来加载显示图片。但是涉及到网络图片的时候就可能会出现问题,现象是不显示图片,控制台报错:

加载网络图片


在flutter web上也可以使用Image这个widget来加载显示图片。但是涉及到网络图片的时候就可能会出现问题,现象是不显示图片,控制台报错:


Failed to load network image.

Image URL: cdnimagelive.knowbox.cn/image/78411…

Trying to load an image from another domain? Find answers at:

flutter.dev/docs/develo…


看提示应该与跨域有关,根据官网的相关文档,Image这个widget在web上支持有限,这时候建议使用其他方式来加载图片


The web offers several methods for displaying images. Below are some of the common ones:

The built-in and  HTML elements.

The drawImage method on the  element.

Custom image codec that renders to a WebGL canvas.


我们选择使用img标签来显示,通过ImageElements来实现即可,代码如下:


import 'dart:html';
import 'dart:ui' as ui;
import 'package:flutter/cupertino.dart';
class WebImage extends StatelessWidget{
  String url;
  double width;
  double height;
  WebImage(this.url, this.width, this.height);
  @override
  Widget build(BuildContext context) {
    String _divId = "web_image_" + DateTime.now().toIso8601String();
    // ignore: undefined_prefixed_name
    ui.platformViewRegistry.registerViewFactory(
      _divId,
          (int viewId) => ImageElement(src: url),
    );
    return SizedBox(
      width: width,
      height: height,
      child: HtmlElementView(key: UniqueKey(),
        viewType: _divId,),
    );
  }
}
复制代码


注意,这种方式图片不能按照自身尺寸显示,所以必须设置宽高才可以。

如果想使用圆形图片,则用ClipOval包装即可,如下:


ClipOval(
  child: WebImage("https://cdnimagelive.knowbox.cn/image/784111920965119.png", 50, 50)
)
复制代码


HTML renderer


但是上面方式有一个很严重的问题,如果一个页面中图片特别多,比如列表,那么使用这种方式的话在pc上运行会特别卡,甚至卡死。会出现大量如下信息:


Flutter: restoring WebGL context.

Flutter: restoring WebGL context.

Flutter: restoring WebGL context.

...

════════ Exception caught by scheduler library ═════════════════════════════════════════════════════

The following JSNoSuchMethodError was thrown during a scheduler callback:

TypeError: Cannot set property 'name' of null

When the exception was thrown, this was the stack:

unpkg.com/canvaskit-w… 223:448  ga

unpkg.com/canvaskit-w… 1:1      Surface$_flush

unpkg.com/canvaskit-w… 12:230   flush

lib/_engine/engine/canvaskit/surface.dart 290:14                  flush

lib/_engine/engine/canvaskit/surface.dart 266:5                   [_presentSurface]

... ════════════════════════════════════════════════════════════════════════════════════════════════════


其实在上面的官方文档(flutter.dev/docs/develo… )中已经提到了


As of today, using too many HTML elements with the CanvasKit renderer may hurt performance. If images interleave non-image content Flutter needs to create extra WebGL contexts between the elements. If your application needs to display a lot of images on the same screen all at once, consider using the HTML renderer instead of CanvasKit.


如果在一个页面有很多图片,则使用HTML renderer来代替CanvasKit。

那么什么是HTML renderer,什么是CanvasKit,如何使用这两个?

根据flutter.cn/docs/develo… 官方文档,flutter对于web的渲染是有两种模式,即html和Canvaskit。


Canvaskit将 Skia 编译成 WebAssembly 格式,并使用 WebGL 渲染。应用在移动和桌面端保持一致,有更好的性能,以及降低不同浏览器渲染效果不一致的风险。但是应用的大小会增加大约 2MB。


默认情况下flutter自动选择渲染器。移动端浏览器选择 HTML,桌面端浏览器选择 CanvasKit。


但是我们如果想使用HTML renderer,就必须强制设置一下,而这个设置并不是在代码中,而是在启动参数中,如下


flutter run -d chrome --web-renderer html   (或canvaskit)//运行命令

flutter build web --web-renderer html  (或canvaskit)   //编译打包


我们通过在终端执行flutter run -d chrome --web-renderer html 来运行我们的应用,就会发现即使页面中有很多图片,也不会出现明显卡顿卡死的现象了。


如果使用Android studio,则需要对运行进行配置,如图:

网络异常,图片无法展示
|


在配置中的Additional arguments一栏中添加--web-renderer html即可,再运行就会以HTML renderer的方式来运行。

最后编译打包的时候也要加上--web-renderer html才可以。


后续影响


慢慢的,使用html render的问题就显示出来了:


Shadow Root问题导致很多三方js sdk无法使用


这个我后面单独开一篇详细将一下。


文本无法选择


改成html render后发现所有文字无法选择了,导致无法进行复制等行为。 运行后通过开发者工具查看页面节点信息,可以看到

整个body都被设置成了user-select: none; touch-action: none,这样就导致整个页面上的文本都无法选择。

这个是flutter框架的行为,目前在flutter项目中还没有发现可以取消这个配置的api。


目录
相关文章
|
2月前
|
小程序 前端开发 中间件
ThinkPHP 配置跨域请求,使用TP的内置跨域类配置,小程序和web网页跨域请求的区别及格式说明
本文介绍了如何在ThinkPHP框架中配置跨域请求,使用了TP内置的跨域类`\think\middleware\AllowCrossDomain::class`。文章还讨论了小程序和web网页在跨域请求格式上的区别,并提供了解决方案,包括修改跨域中间件源码以支持`Origin`和`token`。此外,还介绍了微信小程序跨域请求的示例和web网页前端发送Axios跨域请求的请求拦截器配置。
ThinkPHP 配置跨域请求,使用TP的内置跨域类配置,小程序和web网页跨域请求的区别及格式说明
|
1月前
|
开发框架 UED 计算机视觉
flutter:图片&stful 生命周期 (三)
本文档介绍了如何在Flutter中处理图片,包括加载网络图片、本地图片、创建圆形图片和带有圆角的图片,以及如何配置`pubspec.yaml`文件来添加资源文件。还展示了如何使用`AssetImage`对象来显示本地资源图片,并通过代码示例详细说明了这些操作的实现方法。最后,简要介绍了StatefulWidget的生命周期。
|
2月前
|
前端开发 Windows
【前端web入门第一天】02 HTML图片标签 超链接标签 音频标签 视频标签
本文档详细介绍了HTML中的图片、超链接、音频和视频标签的使用方法。首先讲解了`<img>`标签的基本用法及其属性,包括如何使用相对路径和绝对路径。接着介绍了`<a>`标签,用于创建超链接,并展示了如何设置目标页面打开方式。最后,文档还涵盖了如何在网页中嵌入音频和视频文件,包括简化写法及常用属性。
50 13
|
3月前
|
Dart 前端开发 Java
|
3月前
|
缓存
Flutter Image从网络加载图片刷新、强制重新渲染
Flutter Image从网络加载图片刷新、强制重新渲染
112 1
|
3月前
|
安全 前端开发 Java
Web端系统开发解决跨域问题——以Java SpringBoot框架配置Cors为例
在Web安全上下文中,源(Origin)是指一个URL的协议、域名和端口号的组合。这三个部分共同定义了资源的来源,浏览器会根据这些信息来判断两个资源是否属于同一源。例如,https://www.example.com:443和http://www.example.com虽然域名相同,但由于协议和端口号不同,它们被视为不同的源。同源(Same-Origin)是指两个URL的协议、域名和端口号完全相同。只有当这些条件都满足时,浏览器才认为这两个资源来自同一源,从而允许它们之间的交互操作。
Web端系统开发解决跨域问题——以Java SpringBoot框架配置Cors为例
|
3月前
|
数据可视化 Python
通过python建立一个web服务查看服务器上的文本、图片、视频等文件
通过python建立一个web服务查看服务器上的文本、图片、视频等文件
67 0
|
3月前
|
安全 开发者 UED
|
3月前
|
前端开发 JavaScript
【Azure 环境】前端Web通过Azure AD获取Token时发生跨域问题(CORS Error)
【Azure 环境】前端Web通过Azure AD获取Token时发生跨域问题(CORS Error)
|
3月前
|
前端开发 JavaScript Android开发
Flutter 调用本地 web
Flutter 调用本地 web
38 0