Skip to content

Instantly share code, notes, and snippets.

@rydmike
Created May 21, 2020 16:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rydmike/093461f7c8998aa03b70af4ee71622bc to your computer and use it in GitHub Desktop.
Save rydmike/093461f7c8998aa03b70af4ee71622bc to your computer and use it in GitHub Desktop.
Flutter CustomPaint with Shader with SweepGradient crashes on web
import 'dart:math' as math;
import 'package:flutter/material.dart';
void main() {
runApp(WebCrashDemo());
}
class WebCrashDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.indigo,
scaffoldBackgroundColor: Colors.grey[100],
buttonTheme: ButtonThemeData(
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.indigo),
textTheme: ButtonTextTheme.primary,
),
),
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _HomePageState();
}
}
class _HomePageState extends State<HomePage> {
bool _crashMe = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Circle Gradient Crash on Web'),
centerTitle: true,
elevation: 0,
),
body: Column(
children: [
// And then some gap space too
const SizedBox(height: 20),
const Text('Shader createShader crashes on WEB'),
const SizedBox(height: 20),
Center(
child: SizedBox(
width: 170,
height: 170,
child: ColorCircle(crashMe: _crashMe),
),
),
const SizedBox(height: 10),
Center(
child: SizedBox(
width: 450,
child: SwitchListTile(
title: const Text('Crash me on WEB'),
subtitle:
const Text('This option crashes on web, but only on WEB! '
'Turn on only on none WEB! If you run this code '
'on an emulator or desktop it works fine.'),
value: _crashMe,
onChanged: (value) {
setState(() {
_crashMe = value;
});
},
),
),
),
const SizedBox(height: 10),
],
),
);
}
}
// *****************************************************************************
class ColorCircle extends StatelessWidget {
const ColorCircle({
Key key,
this.crashMe = false,
}) : super(key: key);
/// Set to true to make the shader that crashes on web!
final bool crashMe;
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: _WheelPainter(crashMe: crashMe),
);
}
}
class _WheelPainter extends CustomPainter {
_WheelPainter({this.crashMe = false});
final bool crashMe;
static double radius(Size size) =>
math.min(size.width, size.height).toDouble() / 2 - 8;
@override
void paint(Canvas canvas, Size size) {
final Offset center = Offset(size.width / 2, size.height / 2);
final double radius = _WheelPainter.radius(size);
const SweepGradient colorWheelGradient =
SweepGradient(center: Alignment.bottomRight, colors: [
Color.fromARGB(255, 255, 0, 0),
Color.fromARGB(255, 255, 255, 0),
Color.fromARGB(255, 0, 255, 0),
Color.fromARGB(255, 0, 255, 255),
Color.fromARGB(255, 0, 0, 255),
Color.fromARGB(255, 255, 0, 255),
Color.fromARGB(255, 255, 0, 0),
]);
// If we create a shader from the above SweepGraident, we get
// a crash on web, but only on web.
final Shader sweepShader = crashMe
? colorWheelGradient.createShader(Rect.fromLTWH(0, 0, radius, radius))
: null;
canvas.drawCircle(
center,
radius,
Paint()
..style = PaintingStyle.stroke
..strokeWidth = 16
..shader = sweepShader);
}
@override
bool shouldRepaint(_WheelPainter other) => true;
}
@rydmike
Copy link
Author

rydmike commented May 21, 2020

If you run the above Flutter example with a CustomPainter using a Shader based on a SweepGradient on Flutter Web, it will crash. The same code works fine on a device or desktop. The web crash occurs both on Flutter Web DomCanvas and CanvasKit.

You can try it in DartPad here: https://dartpad.dartlang.org/093461f7c8998aa03b70af4ee71622bc

To see the actual error messages you have to build it for Flutter Web, and to see it working you have to build it for a device or desktop.

This is what it looks on a device before you turn on the part that cashes on Web:

image

And this is is how it looks when you turn it on, on a device:

image

On Web you get the following error/crash:

The following JSNoSuchMethodError was thrown during paint():
NoSuchMethodError: invalid member on null: '_get'

The relevant error-causing widget was:
  CustomPaint file:///C:/Users/mryds/OneDrive/code/flutter/_mr/scroll_pan/lib/main.dart:98:12

When the exception was thrown, this was the stack:
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine.dart 239:26         toMatrix32
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/ui/src/ui/painting.dart 1186:71    sweep
packages/flutter/src/painting/gradient.dart 920:24                                                  createShader       
packages/scroll_pan/main.dart 130:29                                                                paint
packages/flutter/src/rendering/custom_paint.dart 531:12                                             [_paintWithPainter]
packages/flutter/src/rendering/custom_paint.dart 572:7                                              paint
packages/flutter/src/rendering/object.dart 2264:7                                                   [_paintWithContext]
packages/flutter/src/rendering/object.dart 184:12                                                   paintChild
packages/flutter/src/rendering/proxy_box.dart 131:14                                                paint
packages/flutter/src/rendering/object.dart 2264:7                                                   [_paintWithContext]
packages/flutter/src/rendering/object.dart 184:12                                                   paintChild
packages/flutter/src/rendering/shifted_box.dart 70:14                                               paint
packages/flutter/src/rendering/object.dart 2264:7                                                   [_paintWithContext]
packages/flutter/src/rendering/object.dart 184:12                                                   paintChild
packages/flutter/src/rendering/box.dart 2515:14                                                     defaultPaint       
packages/flutter/src/rendering/flex.dart 950:7                                                      paint
packages/flutter/src/rendering/object.dart 2264:7                                                   [_paintWithContext]
packages/flutter/src/rendering/object.dart 184:12                                                   paintChild
packages/flutter/src/rendering/box.dart 2515:14                                                     defaultPaint       
packages/flutter/src/rendering/custom_layout.dart 404:5                                             paint
packages/flutter/src/rendering/object.dart 2264:7                                                   [_paintWithContext]
packages/flutter/src/rendering/object.dart 184:12                                                   paintChild
packages/flutter/src/rendering/proxy_box.dart 131:14                                                paint
packages/flutter/src/material/material.dart 531:11                                                  paint
packages/flutter/src/rendering/object.dart 2264:7                                                   [_paintWithContext]    
packages/flutter/src/rendering/object.dart 184:12                                                   paintChild
packages/flutter/src/rendering/proxy_box.dart 131:14                                                paint
packages/flutter/src/rendering/object.dart 391:12                                                   pushLayer
packages/flutter/src/rendering/proxy_box.dart 1819:14                                               paint
packages/flutter/src/rendering/object.dart 2264:7                                                   [_paintWithContext]    
packages/flutter/src/rendering/object.dart 184:12                                                   paintChild
packages/flutter/src/rendering/proxy_box.dart 131:14                                                paint
packages/flutter/src/rendering/object.dart 2264:7                                                   [_paintWithContext]    
packages/flutter/src/rendering/object.dart 184:12                                                   paintChild
packages/flutter/src/rendering/proxy_box.dart 131:14                                                paint
packages/flutter/src/rendering/object.dart 2264:7                                                   [_paintWithContext]    
packages/flutter/src/rendering/object.dart 135:10                                                   _repaintCompositedChild
packages/flutter/src/rendering/object.dart 95:5                                                     repaintCompositedChild 
packages/flutter/src/rendering/object.dart 980:29                                                   flushPaint
packages/flutter/src/rendering/binding.dart 404:19                                                  drawFrame
packages/flutter/src/widgets/binding.dart 865:13                                                    drawFrame
packages/flutter/src/rendering/binding.dart 284:5
[_handlePersistentFrameCallback]
packages/flutter/src/scheduler/binding.dart 1113:15                                                 [_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1052:9                                                  handleDrawFrame       
packages/flutter/src/scheduler/binding.dart 968:5                                                   [_handleDrawFrame]    
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/window.dart 715:13  _invoke
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine/window.dart 338:5   invokeOnDrawFrame     
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/_engine/engine.dart 211:18         <fn>

The following RenderObject was being processed when the exception was fired: RenderCustomPaint#a5326:
  creator: CustomPaint ← ColorCircle ← SizedBox ← Center ← Column ← _BodyBuilder ← MediaQuery ←
    LayoutId-[<_ScaffoldSlot.body>] ← CustomMultiChildLayout ← AnimatedBuilder ← DefaultTextStyle ←
    AnimatedDefaultTextStyle ← ⋯
  parentData: <none> (can use size)
  constraints: BoxConstraints(w=170.0, h=170.0)
  size: Size(170.0, 170.0)
This RenderObject has no descendants.
════════════════════════════════════════════════════════════════════════════════════════════════════
Another exception was thrown: Assertion failed:
org-dartlang-sdk:///flutter_web_sdk/lib/_engine/engine/bitmap_canvas.dart:788:12
Another exception was thrown: NoSuchMethodError: invalid member on null: '_get'
Another exception was thrown: PersistedScene: is in an unexpected state.
Another exception was thrown: PersistedOffset: is in an unexpected state.
Another exception was thrown: NoSuchMethodError: invalid member on null: '_get'
Another exception was thrown: PersistedScene: is in an unexpected state.       
Another exception was thrown: NoSuchMethodError: invalid member on null: '_get'
Another exception was thrown: PersistedScene: is in an unexpected state.
Another exception was thrown: NoSuchMethodError: invalid member on null: '_get'
Another exception was thrown: PersistedScene: is in an unexpected state.       

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment