Flutter在web项目中使用iframe

需要把原来的app项目移植到web上面,在app中使用的是flutter_inappwebview这个库,推荐使用这个库,因为修复了一部分webview_flutter中存在的问题

在web项目中flutter_inappwebview这个库不支持,所以需要自己封装一个web项目中的webview也就是使用iframe

废话少说上代码

import 'dart:html';
import 'dart:js' as js;

import 'dart:ui_web';

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:myapp/app/services/screen_adapter.dart';

Widget buildWebViewWidget(String url,
    {Function(int id)? onPlatformViewCreated}) {

  /// 给js调用的函数
  void back(){
    Get.back();
  }

  var platformViewRegistry = PlatformViewRegistry();
  //注册
  platformViewRegistry.registerViewFactory('iframe-webview', (_) {
    DivElement _mainDiv = DivElement()
      ..style.width = '100%'
      ..style.height = '100%'
      ..style.position = 'relative';

    IFrameElement _iFameElement = IFrameElement()
      ..style.height = '100%'
      ..style.width = '100%'
      ..src = url
      ..style.border = 'none';

    ScriptElement scriptElement = ScriptElement();
    var script = """
          
           // 对话框js
          window.confirm = function(message, yesCallback, noCallback){
             var message = message;
             var choose = function(tag){
                return document.querySelector(tag);
             }
             choose('.dialog-message').innerHtml = message;
             choose(".wrap-dialog").className = "wrap-dialog";
             choose("#dialog").οnclick= function(e){
                if(e.target.className=="dialog-btn"){
                     choose(".wrap-dialog").className = "wrap-dialog dialog-hide";
                     yesCallback();
                 }else if (e.target.className=="dialog-btn dialog-ml50"){
                     choose(".wrap-dialog").className = "wrap-dialog dialog-hide";
                      noCallback();
                 }
             };
          }
    
           // 返回按钮功能
           var drag = document.getElementById("floatBtn");
           var gapWidth = ${ScreenAdapter.width(5)}
           var itemWidth = ${ScreenAdapter.width(80)}
           var itemHeight =  ${ScreenAdapter.width(80)}
           var clientWidth = document.documentElement.clientWidth
           var clientHeight = document.documentElement.clientHeight
           var newLeft = 0
           var newTop = 0
           
            drag.addEventListener('click',function(e){
              //e.stopPropagation();
              var r = confirm('确定返回首页吗?', function(){
                 window.back();
              }, function(){})
            })
          
            drag.addEventListener('touchstart', function(e){
              // e.preventDefault();
              //e.stopPropagation();
              drag.style.transition = 'none';
            })
          
            drag.addEventListener('touchmove', function(e){
              // e.preventDefault();
             // e.stopPropagation();
              if (e.targetTouches.length === 1) {
                   let touch = e.targetTouches[0]
                   newLeft = touch.clientX - itemWidth / 2;
                   newTop = touch.clientY - itemHeight / 2;
                   if(newLeft  < 0){
                      newLeft = 0
                   } 
                   if(newLeft > clientWidth - itemWidth - gapWidth){
                      newLeft > clientWidth - itemWidth - gapWidth
                   }
                   if(newTop < 0){
                      newTop=0;
                   }
                   if(newTop > clientHeight - itemHeight - gapWidth){
                     newTop = clientHeight - itemHeight - gapWidth
                   }
                   drag.style.left = newLeft + 'px'
                   drag.style.top = newTop + 'px'
              }
            })
            drag.addEventListener('touchend', function (e) {
                 // e.preventDefault()
                 //e.stopPropagation();
                drag.style.transition = 'all 0.3s'
                if (newLeft > clientWidth / 2) {
                    newLeft = clientWidth - itemWidth - gapWidth
                } else {
                    newLeft = gapWidth
                }
                drag.style.left = newLeft + 'px'
            })   
    """;



    scriptElement.innerHtml = script;

    /// 返回按钮div
    DivElement _div = DivElement()
      ..id = 'floatBtn'
      ..draggable = true
      ..style.width =  '${ScreenAdapter.width(80)}px'
      ..style.height =  '${ScreenAdapter.width(80)}px'
      // ..style.backgroundColor = 'red'
      ..style.backgroundImage = 'url(assets/assets/images/fanhui.png)'
      ..style.backgroundSize = 'cover'
      ..style.position = 'absolute'
      ..style.left = '${ScreenAdapter.width(5)}px'
      ..style.top = '0'
      ..style.transition = 'all 0.3s'
      ..style.zIndex = '9999';


    // 对话框样式
    StyleElement _style = StyleElement();
    _style.innerHtml = """
    html,
    body {
        margin: 0;
        padding: 0;
        font-family: "Microsoft YaHei";
    }

    .wrap-dialog {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        font-size: 16px;
        text-align: center;
        background-color: rgba(0, 0, 0, .4);
        z-index: 10000;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    .dialog {
        position: relative;
        margin: 10% auto;
        width: 300px;
        background-color: #FFFFFF;
    }

    .dialog .dialog-header {
        height: 20px;
        padding: 10px;
        background-color: #22b9ff;
    }

    .dialog .dialog-body {
        height: 30px;
        padding: 20px;
    }

    .dialog .dialog-footer {
        padding: 8px;
        background-color: #f5f5f5;
    }

    .dialog-btn {
        width: 70px;
        padding: 2px;
        cursor: pointer;
    }

    .dialog-hide {
        display: none;
    }

    .dialog-ml50 {
        margin-left: 50px;
    }
    """;
    _mainDiv.append(_style);

    // 提示信息框dom
    DivElement _dialogDiv = DivElement();
    _dialogDiv.innerHtml = """
    
提示
确定要返回首页吗?
"""
; _mainDiv.append(scriptElement); _mainDiv.append(_dialogDiv); _mainDiv.append(_div); _mainDiv.append(_iFameElement); return _mainDiv; }); /// 注册返回函数 js.context['back'] = back; return SizedBox( width: double.infinity, height: double.infinity, child: HtmlElementView( viewType: 'iframe-webview', onPlatformViewCreated: (int id) { onPlatformViewCreated?.call(id); }, ), ); }

使用方法

直接判断是否是web,GetPlatform.isWeb ,如果是则使用上面封装的,不是则调用其他平台的

if(GetPlatform.isWeb)
   buildWebViewWidgetPlatform(controller.url,
       onPlatformViewCreated: (id) {
           controller.isLoading.value = false;
   })

参考网址

https://juejin.cn/post/7294638699417042954

你可能感兴趣的:(flutter,flutter,前端)