加载应用程序之前的 Flutter Web 应用程序进度指示器?

Flutter web app progress indicator before loading app?

您好,我是一名移动应用程序开发人员,对 Web 开发不太熟悉,在加载 Gmail 加载屏幕等 Flutter Web 应用程序之前,我一直在寻找实现进度指示器的任何方法。 Flutter web 很酷,但它需要几分钟才能加载应用程序。我们可以为这个加载持续时间添加任何指标吗?任何在 flutter 中实现的代码都将成为 flutter app 的一部分,它不会起作用,应该有另一种方法来实现这一点。

在你的问题中你提到了

Any code implemented in flutter would be the part of flutter app and it won't work,...

我假设您尝试为 android 或 IOS 添加启动画面方法。由于 flutter-web 只是一个 index.html 和几个 js 文件(例如,main.dart.js),您或许应该尝试 CSS 加载动画技巧。由于您没有共享任何代码,所以我没有编写任何代码,但以下是我的方法,正如这个红色订书机 video. He/she kindly provided a lot of CSS based animations here 以及代码笔实现所解释的那样。

下面是我在 flutter_web_project\web\index.html 文件中的步骤。

  1. index.html 的正文中添加一个 span 元素以显示 css 动画本身。
  2. 创建一个 div 包装器以在您的 index.html 中定位跨度动画。
  3. 然后监听 window 的 onLoad 事件并从您的页面中删除 div 元素或按照视频中的描述将其淡出。

在@Abhilash 的帮助下,我得以完成此任务。我从 w3schools.

获得了加载程序代码

我的project/web/index.html是这样的

<html>

<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script defer src="index.dart.js" type="application/javascript"></script>

  <style>
    .loading {
      display: flex;
      justify-content: center;
      align-items: center;
      margin: 0;
      position: absolute;
      top: 50%;
      left: 50%;
      -ms-transform: translate(-50%, -50%);
      transform: translate(-50%, -50%);
    }
    
    .loader {
      border: 16px solid #f3f3f3;
      border-radius: 50%;
      border-top: 16px solid blue;
      border-right: 16px solid green;
      border-bottom: 16px solid red;
      border-left: 16px solid pink;
      width: 120px;
      height: 120px;
      -webkit-animation: spin 2s linear infinite;
      animation: spin 2s linear infinite;
    }
    
    @-webkit-keyframes spin {
      0% {
        -webkit-transform: rotate(0deg);
      }
      100% {
        -webkit-transform: rotate(360deg);
      }
    }
    
    @keyframes spin {
      0% {
        transform: rotate(0deg);
      }
      100% {
        transform: rotate(360deg);
      }
    }
  </style>
</head>

<body>
  <div class="loading">
    <div class="loader"></div>
  </div>

  <script src="main.dart.js" type="application/javascript"></script>
</body>

</html>

除了@Shahzad Akram 的回答之外,您还应该删除 loading div 因为在 Safari 浏览器中它可能会导致闪烁。因此,在第一个屏幕中,您需要执行以下代码(例如,在 initState 方法中):

import 'package:universal_html/html.dart'

...

@override
void initState() {
  super.initState()
  // Remove `loading` div
  final loader = document.getElementsByClassName('loading');
  if(loader.isNotEmpty) {
    loader.first.remove();
  }
}

P.S。对于不错的装载机,您可以访问 loading.io.

如果你想删除仅使用 JS 的加载 div,请使用此代码

  <script>
    window.onload = (event) => {
      console.log('page is fully loaded');
      var element = document.getElementById("loader");
      element.parentNode.removeChild(element);
    };
  </script>

注意它假设 loader 是一个 <div id="loader"></div> 标签

除了@Shahzad 和@BambinoUA 的回答,我还需要为 main.dart.js 脚本添加 defer 关键字还有标签。

<script defer src="main.dart.js" type="application/javascript"></script>

以下是我需要的场景:

  • 应用托管在 Gitlab 页面上
  • 浏览器 Chrome(网速较慢)

在这种情况下,在下载整个脚本之前只能看到空白屏幕。然后动画仅显示 0.5 秒,之后立即加载 flutter 小部件。从而未能达到加载动画的目的。这在本地测试中不会发生。

我也试过将动画 div 放在所有脚本之前,但没有用。

Adam 的回答会在实际加载 flutter 之前移除 loader。

我发现这个脚本是最完整的答案:

<html>
<head>
  <style>
        .loading {
          display: flex;
          flex-flow: column;
          justify-content: center;
          align-items: center;
          margin: 0;
          position: absolute;
          top: 50%;
          left: 50%;
          -ms-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
        }

        .loader {
          border: 8px solid #f3f3f3;
          border-radius: 50%;
          border-top: 8px solid #00AD87;
          border-right: 8px solid #C30E48;
          border-bottom: 8px solid #00AD87;
          border-left: 8px solid #C30E48;
          width: 60px !important;
          height: 60px !important;
          -webkit-animation: spin 2s linear infinite;
          animation: spin 2s linear infinite;
        }

        @-webkit-keyframes spin {
          0% {
            -webkit-transform: rotate(0deg);
          }
          100% {
            -webkit-transform: rotate(360deg);
          }
        }

        @keyframes spin {
          0% {
            transform: rotate(0deg);
          }
          100% {
            transform: rotate(360deg);
          }
        }
  </style>
</head>

<body>

  <!-- First time loading -->
  <div class="loading">
      <div class="loader"></div>
  </div>

  <!-- Ensure first time loading progress is gone after app loads -->
  <script>
      window.addEventListener("flutter-first-frame", function() {
          var element = document.getElementsByClassName("loading");
          element[0].parentNode.removeChild(element[0]);
      });
  </script>

<script defer src="main.dart.js" type="application/javascript"</script>

</body>
</html>