前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter Web:图片加载及跨域问题

Flutter Web:图片加载及跨域问题

作者头像
BennuCTech
发布2022-05-31 09:33:01
3.4K0
发布2022-05-31 09:33:01
举报
文章被收录于专栏:BennuCTech

加载网络图片

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

Failed to load network image. Image URL: https://cdnimagelive.knowbox.cn/image/784111920965119.png Trying to load an image from another domain? Find answers at: https://flutter.dev/docs/development/platform-integration/web-images

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

The web offers several methods for displaying images. Below are some of the common ones: The built-inand HTML elements. The drawImage method on the element. Custom image codec that renders to a WebGL canvas.

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

代码语言:javascript
复制
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包装即可,如下:

代码语言:javascript
复制
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: https://unpkg.com/canvaskit-wasm@0.24.0/bin/canvaskit.js 223:448 ga https://unpkg.com/canvaskit-wasm@0.24.0/bin/canvaskit.js 1:1 Surface$_flush https://unpkg.com/canvaskit-wasm@0.24.0/bin/canvaskit.js 12:230 flush lib/_engine/engine/canvaskit/surface.dart 290:14 flush lib/_engine/engine/canvaskit/surface.dart 266:5 [_presentSurface] ... ════════════════════════════════════════════════════════════════════════════════════════════════════

其实在上面的官方文档(https://flutter.dev/docs/development/platform-integration/web-images )中已经提到了

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 theelements. 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,如何使用这两个?

根据https://flutter.cn/docs/development/tools/web-renderers 官方文档,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。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 BennuCTech 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 加载网络图片
  • HTML renderer
    • 后续影响
    相关产品与服务
    云开发 CLI 工具
    云开发 CLI 工具(Cloudbase CLI Devtools,CCLID)是云开发官方指定的 CLI 工具,可以帮助开发者快速构建 Serverless 应用。CLI 工具提供能力包括文件储存的管理、云函数的部署、模板项目的创建、HTTP Service、静态网站托管等,您可以专注于编码,无需在平台中切换各类配置。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档