Skip to content
Advertisement

How to use Flutter’s WebView to show graphs or charts (e.g. through D3.js or Chart.js) on Flutter Web?

This is a follow-up to this question, asking if all this was even possible.

The WebView package seems really dope. But so far it seems really obscure and dense to me.

Almost all of the examples I’ve been able to find refer to seeing other existing web pages and then altering them, but my use case was about having an empty page, in which I would use the more mature JS visual libraries to plot charts or graphs.

And it’s not clear to me, but is this package about adding views for non-web environments? If it is, what about using it on Flutter Web? Maybe this is obvious for someone with experience with that package, but to those starting with it, it’s not clear at all…

For example, I’m trying to implement this simple D3.js example, and, in the package’s documentation, there’s this simple example:

import 'dart:io';

import 'package:webview_flutter/webview_flutter.dart';

class WebViewExample extends StatefulWidget {
  @override
  WebViewExampleState createState() => WebViewExampleState();
}

class WebViewExampleState extends State<WebViewExample> {
  @override
  void initState() {
    super.initState();
    // Enable virtual display.
    if (Platform.isAndroid) WebView.platform = AndroidWebView();
  }

  @override
  Widget build(BuildContext context) {
    return WebView(
      initialUrl: 'https://flutter.dev',
    );
  }
}

I don’t know what I would do for WebView.platform in the case of Web, there’s no option for it. And, when I try it on Chrome, I get — I used Chrome on Linux, and the rest of my app does work —:

The following UnsupportedError was thrown building WebView(dirty, state: _WebViewState#2d89e):
Unsupported operation: Trying to use the default webview implementation for TargetPlatform.linux 
but there isn't a default one

I did try other variations of the code above, including trying to make it a StatelessWidget without initState, but the result was the same:

class WebViewExample extends StatelessWidget {
  const WebViewExample({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: WebView(
        initialUrl: 'https://flutter.dev',
      ),
    );
  }
}

Is anyone able to pull off the simple D3.js example I mentioned on Flutter Web (even better if you could send the data from Dart to JS…)? That would be of great help.

Advertisement

Answer

The webview_flutter plugin doesn’t support currently Web platform.

You can use the flutter_inappwebview plugin (I’m the author). Starting from version 6.x.x, it supports Web and macOS platforms!

To correctly setup Web platform support, follow the official Setup Web guide!

Here is a simple example for Flutter Web showing the D3.js Scatter plot example and the latest flutter_inappwebview version 6 currently available (6.0.0-beta.17):

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  if (!kIsWeb &&
      kDebugMode &&
      defaultTargetPlatform == TargetPlatform.android) {
    await InAppWebViewController.setWebContentsDebuggingEnabled(kDebugMode);
  }
  runApp(const MaterialApp(home: MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final GlobalKey webViewKey = GlobalKey();

  InAppWebViewController? webViewController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("InAppWebView test"),
        ),
        body: Column(children: <Widget>[
          Expanded(
            child: InAppWebView(
              key: webViewKey,
              initialData: InAppWebViewInitialData(
                data: """
<!DOCTYPE html>
<html>
<head>
  <script src="https://d3js.org/d3.v4.js"></script>
</head>
<body>
  <h2>D3.js Scatter-Plot</h2>
  <svg id="myPlot" style="width:500px;height:500px"></svg>
  <script>
    // Set Dimensions
    const xSize = 500;
    const ySize = 500;
    const margin = 40;
    const xMax = xSize - margin * 2;
    const yMax = ySize - margin * 2;

    // Create Random Points
    const numPoints = 100;
    const data = [];
    for (let i = 0; i < numPoints; i++) {
      data.push([Math.random() * xMax, Math.random() * yMax]);
    }

    // Append SVG Object to the Page
    const svg = d3.select("#myPlot")
      .append("svg")
      .append("g")
      .attr("transform", "translate(" + margin + "," + margin + ")");

    // X Axis
    const x = d3.scaleLinear()
      .domain([0, 500])
      .range([0, xMax]);

    svg.append("g")
      .attr("transform", "translate(0," + yMax + ")")
      .call(d3.axisBottom(x));

    // Y Axis
    const y = d3.scaleLinear()
      .domain([0, 500])
      .range([yMax, 0]);

    svg.append("g")
      .call(d3.axisLeft(y));

    // Dots
    svg.append('g')
      .selectAll("dot")
      .data(data).enter()
      .append("circle")
      .attr("cx", function (d) { return d[0] })
      .attr("cy", function (d) { return d[1] })
      .attr("r", 3)
      .style("fill", "Red");
  </script>
</body>
</html>
"""
              ),
              onWebViewCreated: (controller) {
                webViewController = controller;
              },
            ),
          ),
        ]));
  }
}

Flutter inappwebview web example

Advertisement