Created
May 21, 2020 16:57
-
-
Save rydmike/093461f7c8998aa03b70af4ee71622bc to your computer and use it in GitHub Desktop.
Flutter CustomPaint with Shader with SweepGradient crashes on web
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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:
And this is is how it looks when you turn it on, on a device:
On Web you get the following error/crash: