Skip to content

Commit 2e40949

Browse files
committedMay 21, 2020
refactor: rerwire core logic to minimize hash length
1 parent 3305edb commit 2e40949

27 files changed

+468
-271
lines changed
 

‎README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Size of the blob. It is mandatory.
4848
Blob.random(size:200),
4949
```
5050

51-
![Basic blob](https://raw.githubusercontent.com/lokesh-coder/flutter_blobs/develop/screenshots/blob_shape_2.jpg)
51+
![Basic blob](https://raw.githubusercontent.com/lokesh-coder/flutter_blobs/develop/screenshots/basic_shape_2.jpg)
5252

5353
 
5454

@@ -65,9 +65,9 @@ Blob.random(
6565
),
6666
```
6767

68-
![Basic blob](https://raw.githubusercontent.com/lokesh-coder/flutter_blobs/develop/screenshots/blob_shape_1.jpg)
69-
![Basic blob](https://raw.githubusercontent.com/lokesh-coder/flutter_blobs/develop/screenshots/blob_shape_3.jpg)
70-
![Basic blob](https://raw.githubusercontent.com/lokesh-coder/flutter_blobs/develop/screenshots/blob_shape_4.jpg)
68+
![Basic blob](https://raw.githubusercontent.com/lokesh-coder/flutter_blobs/develop/screenshots/basic_shape_1.jpg)
69+
![Basic blob](https://raw.githubusercontent.com/lokesh-coder/flutter_blobs/develop/screenshots/basic_shape_3.jpg)
70+
![Basic blob](https://raw.githubusercontent.com/lokesh-coder/flutter_blobs/develop/screenshots/basic_shape_4.jpg)
7171

7272
 
7373

‎example/android/app/src/main/res/values/styles.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<!-- Show a splash screen on the activity. Automatically removed when
66
Flutter draws its first frame -->
77
<item name="android:windowBackground">@drawable/launch_background</item>
8+
<item name="android:defaultFocusHighlightEnabled">false</item>
89
</style>
910
<!-- Theme applied to the Android Window as soon as the process has started.
1011
This theme determines the color of the Android Window while your

‎example/assets/Ropa_Sans/OFL.txt

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
Copyright 2013 The Ropa Sans Project Authors (nikoltchev@lettersoup.de), with Reserved Font Name "Ropa Sans".
2+
3+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
4+
This license is copied below, and is also available with a FAQ at:
5+
http://scripts.sil.org/OFL
6+
7+
8+
-----------------------------------------------------------
9+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10+
-----------------------------------------------------------
11+
12+
PREAMBLE
13+
The goals of the Open Font License (OFL) are to stimulate worldwide
14+
development of collaborative font projects, to support the font creation
15+
efforts of academic and linguistic communities, and to provide a free and
16+
open framework in which fonts may be shared and improved in partnership
17+
with others.
18+
19+
The OFL allows the licensed fonts to be used, studied, modified and
20+
redistributed freely as long as they are not sold by themselves. The
21+
fonts, including any derivative works, can be bundled, embedded,
22+
redistributed and/or sold with any software provided that any reserved
23+
names are not used by derivative works. The fonts and derivatives,
24+
however, cannot be released under any other type of license. The
25+
requirement for fonts to remain under this license does not apply
26+
to any document created using the fonts or their derivatives.
27+
28+
DEFINITIONS
29+
"Font Software" refers to the set of files released by the Copyright
30+
Holder(s) under this license and clearly marked as such. This may
31+
include source files, build scripts and documentation.
32+
33+
"Reserved Font Name" refers to any names specified as such after the
34+
copyright statement(s).
35+
36+
"Original Version" refers to the collection of Font Software components as
37+
distributed by the Copyright Holder(s).
38+
39+
"Modified Version" refers to any derivative made by adding to, deleting,
40+
or substituting -- in part or in whole -- any of the components of the
41+
Original Version, by changing formats or by porting the Font Software to a
42+
new environment.
43+
44+
"Author" refers to any designer, engineer, programmer, technical
45+
writer or other person who contributed to the Font Software.
46+
47+
PERMISSION & CONDITIONS
48+
Permission is hereby granted, free of charge, to any person obtaining
49+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
50+
redistribute, and sell modified and unmodified copies of the Font
51+
Software, subject to the following conditions:
52+
53+
1) Neither the Font Software nor any of its individual components,
54+
in Original or Modified Versions, may be sold by itself.
55+
56+
2) Original or Modified Versions of the Font Software may be bundled,
57+
redistributed and/or sold with any software, provided that each copy
58+
contains the above copyright notice and this license. These can be
59+
included either as stand-alone text files, human-readable headers or
60+
in the appropriate machine-readable metadata fields within text or
61+
binary files as long as those fields can be easily viewed by the user.
62+
63+
3) No Modified Version of the Font Software may use the Reserved Font
64+
Name(s) unless explicit written permission is granted by the corresponding
65+
Copyright Holder. This restriction only applies to the primary font name as
66+
presented to the users.
67+
68+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69+
Software shall not be used to promote, endorse or advertise any
70+
Modified Version, except to acknowledge the contribution(s) of the
71+
Copyright Holder(s) and the Author(s) or with their explicit written
72+
permission.
73+
74+
5) The Font Software, modified or unmodified, in part or in whole,
75+
must be distributed entirely under this license, and must not be
76+
distributed under any other license. The requirement for fonts to
77+
remain under this license does not apply to any document created
78+
using the Font Software.
79+
80+
TERMINATION
81+
This license becomes null and void if any of the above conditions are
82+
not met.
83+
84+
DISCLAIMER
85+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93+
OTHER DEALINGS IN THE FONT SOFTWARE.
55.2 KB
Binary file not shown.
53.6 KB
Binary file not shown.

‎example/lib/examples/animated/animated_basic.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ class AnimatedBasicExample extends StatelessWidget {
2424
),
2525
),
2626
Button('Randomize', onTap: () {
27-
BlobData foo = blobCtrl.change();
28-
print(foo.svgPath);
27+
BlobData blobData = blobCtrl.change();
28+
print(blobData);
2929
})
3030
],
3131
),

‎example/lib/examples/animated/animated_debug.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ class AnimatedDebugExample extends StatelessWidget {
1818
Container(
1919
child: Blob.animatedRandom(
2020
size: 300,
21-
edgesCount: 8,
22-
minGrowth: 2,
21+
edgesCount: 6,
22+
minGrowth: 3,
2323
controller: blobCtrl,
2424
debug: true,
2525
),

‎example/lib/examples/animated/animated_hash.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ class AnimatedHashExample extends StatelessWidget {
1717
children: [
1818
Container(
1919
child: Blob.animatedFromHash(
20-
hash: [
21-
'H4sIANhSwV4A/w3LsQ0AMQgEwYY24A5koBbr+2/jnY40NzdxBD7GPagXrznzKKlFbjSBJDKKs9QLE98PNkNQxj0AAAA='
22-
],
20+
hash: ['6-3-372642'],
2321
size: 400,
2422
controller: blobCtrl,
2523
),

‎example/lib/examples/animated/animated_multiple_hash.dart

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,48 +27,38 @@ class _AnimatedMultipleHashExampleState
2727
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
2828
children: [
2929
Blob.animatedFromHash(
30-
hash: [
31-
'H4sIAB5VwV4A/w3KwQ0AMQjEwIb8YNmQcLWc0n8b4WWN5N8lMgJn4jLqcZvck8URcqPaFPkFfVizd9wHDGCsqzsAAAA=',
32-
],
30+
hash: ['6-3-22556'],
3331
styles: BlobStyles(
3432
color: Color(0xff596275).withOpacity(0.5),
3533
fillType: BlobFillType.stroke,
36-
strokeWidth: 20,
34+
strokeWidth: 2,
3735
),
3836
size: 50,
3937
),
4038
Blob.animatedFromHash(
41-
hash: [
42-
'H4sIADZVwV4A/w3KsREAMQjEwIYU3IENdi2e77+NJ9hEo5cuQiLaxBXuRXrcSQer8N6jOKSCTtb8R98PT0B1nTwAAAA='
43-
],
39+
hash: ['6-3-90151'],
4440
size: 50,
4541
styles: BlobStyles(
4642
color: Color(0xff596275).withOpacity(0.5),
4743
fillType: BlobFillType.stroke,
48-
strokeWidth: 20,
44+
strokeWidth: 2,
4945
),
5046
),
5147
Blob.animatedFromHash(
52-
hash: [
53-
'H4sIAEFVwV4A/w3LsRHAQAjEwIYUHIcf+Fo87r8NE2wmvXkLS6TXEVEmq+jG55JNOIhZMXjrEc8Oo+8H5uyPHz0AAAA='
54-
],
48+
hash: ['6-3-79206'],
5549
size: 50,
5650
styles: BlobStyles(
5751
color: Color(0xff596275).withOpacity(0.5),
5852
fillType: BlobFillType.stroke,
59-
strokeWidth: 20,
53+
strokeWidth: 2,
6054
),
6155
),
6256
],
6357
),
6458
SizedBox(height: 30),
6559
Container(
6660
child: Blob.animatedFromHash(
67-
hash: [
68-
'H4sIAB5VwV4A/w3KwQ0AMQjEwIb8YNmQcLWc0n8b4WWN5N8lMgJn4jLqcZvck8URcqPaFPkFfVizd9wHDGCsqzsAAAA=',
69-
'H4sIADZVwV4A/w3KsREAMQjEwIYU3IENdi2e77+NJ9hEo5cuQiLaxBXuRXrcSQer8N6jOKSCTtb8R98PT0B1nTwAAAA=',
70-
'H4sIAEFVwV4A/w3LsRHAQAjEwIYUHIcf+Fo87r8NE2wmvXkLS6TXEVEmq+jG55JNOIhZMXjrEc8Oo+8H5uyPHz0AAAA='
71-
],
61+
hash: ['6-3-22556', '6-3-90151', '6-3-79206'],
7262
size: 400,
7363
controller: blobCtrl,
7464
styles: BlobStyles(color: Color(0xff34ace0)),

‎example/lib/examples/examples.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:example/examples/static/static_color.dart';
2+
import 'package:example/examples/static/static_multiple_hash.dart';
23
import 'package:example/examples/static/static_stroke.dart';
34
import 'package:flutter/material.dart';
45
import '../common/app_shell.dart';
@@ -17,6 +18,7 @@ import 'static/static_clipper.dart';
1718
import 'static/static_debug.dart';
1819
import 'static/static_gradient.dart';
1920
import 'static/static_hash.dart';
21+
import 'inspirations/rotate.dart';
2022

2123
class Examples extends StatelessWidget {
2224
const Examples({Key key}) : super(key: key);
@@ -28,6 +30,7 @@ class Examples extends StatelessWidget {
2830
child: Container(
2931
child: ListView(
3032
children: [
33+
Link('Insipation - rotate', RotateInpirationExample()),
3134
Link('Animated - Basic blob', AnimatedBasicExample()),
3235
Link('Animated-Basic with child', AnimatedChildExample()),
3336
Link('Animated-Debug', AnimatedDebugExample()),
@@ -43,7 +46,7 @@ class Examples extends StatelessWidget {
4346
Link('Gradient', StaticGradientExample()),
4447
Link('Outline blob', StaticStrokeExample()),
4548
Link('Fixed blob', StaticHashExample()),
46-
Link('Fixed Multiple Hash', StaticHashExample()),
49+
Link('Fixed Multiple Hash', StaticMultipleHashExample()),
4750
Link('Custom color', StaticColorExample()),
4851
Link('Clipper', StaticClipperExample()),
4952
],
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import 'package:blobs/blobs.dart';
2+
import 'package:flutter/material.dart';
3+
4+
import '../../common/app_shell.dart';
5+
import '../../common/button.dart';
6+
7+
class RotateInpirationExample extends StatefulWidget {
8+
const RotateInpirationExample({Key key}) : super(key: key);
9+
10+
@override
11+
_RotateInpirationExampleState createState() =>
12+
_RotateInpirationExampleState();
13+
}
14+
15+
class _RotateInpirationExampleState extends State<RotateInpirationExample>
16+
with SingleTickerProviderStateMixin {
17+
AnimationController _animationController;
18+
Animation animation;
19+
20+
@override
21+
void initState() {
22+
super.initState();
23+
_animationController =
24+
AnimationController(duration: Duration(seconds: 200), vsync: this);
25+
animation =
26+
Tween<double>(begin: 0.0, end: 1.0).animate(_animationController);
27+
_animationController.addListener(() {
28+
setState(() {});
29+
});
30+
_animationController.repeat();
31+
}
32+
33+
@override
34+
Widget build(BuildContext context) {
35+
return AppShell(
36+
title: 'Rotate',
37+
child: Center(
38+
child: Column(
39+
mainAxisSize: MainAxisSize.min,
40+
children: [
41+
Container(
42+
child: Stack(
43+
alignment: Alignment.center,
44+
children: [
45+
Transform.rotate(
46+
angle: (animation.value * 0.6) * 360.0,
47+
child: Blob.fromHash(
48+
size: 170,
49+
// hash: ['5-7-68346', '5-7-34659', '6-7-63530'],
50+
hash: ['5-7-34659'],
51+
styles: BlobStyles(
52+
color: Color(0xffff6b81).withOpacity(0.2),
53+
fillType: BlobFillType.fill,
54+
),
55+
),
56+
),
57+
Transform.rotate(
58+
angle: animation.value * 360.0,
59+
child: Blob.fromHash(
60+
size: 200,
61+
// hash: ['5-7-68346', '5-7-70642', '6-7-63530'],
62+
hash: ['5-7-68346'],
63+
styles: BlobStyles(
64+
color: Color(0xffFC427B),
65+
fillType: BlobFillType.stroke,
66+
),
67+
),
68+
),
69+
Transform.rotate(
70+
angle: (animation.value * 0.4) * 360.0,
71+
child: Blob.fromHash(
72+
size: 200,
73+
// hash: ['5-7-68346', '5-7-34659', '6-7-63530'],
74+
hash: ['5-7-33'],
75+
styles: BlobStyles(
76+
color: Color(0xffB33771),
77+
fillType: BlobFillType.stroke,
78+
),
79+
),
80+
),
81+
Center(
82+
child: Text(
83+
"blobs",
84+
style: TextStyle(
85+
fontFamily: 'Ropa',
86+
fontSize: 30,
87+
color: Color(0xffc44569),
88+
),
89+
)),
90+
],
91+
),
92+
),
93+
],
94+
),
95+
),
96+
);
97+
}
98+
99+
@override
100+
void dispose() {
101+
_animationController.dispose();
102+
super.dispose();
103+
}
104+
}

‎example/lib/examples/static/static_basic.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ class StaticBasicExample extends StatelessWidget {
1818
Container(
1919
child: Blob.random(
2020
size: 400,
21+
edgesCount: 5,
22+
minGrowth: 7,
2123
controller: blobCtrl,
24+
debug: true,
2225
),
2326
),
2427
Button('Randomize', onTap: () {
25-
blobCtrl.change();
28+
BlobData blobData = blobCtrl.change();
29+
print('${blobData.id}');
2630
})
2731
],
2832
),

‎example/lib/examples/static/static_hash.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ class StaticHashExample extends StatelessWidget {
1717
children: [
1818
Container(
1919
child: Blob.fromHash(
20-
hash: [
21-
'H4sIANhSwV4A/w3LsQ0AMQgEwYY24A5koBbr+2/jnY40NzdxBD7GPagXrznzKKlFbjSBJDKKs9QLE98PNkNQxj0AAAA='
22-
],
20+
hash: ['6-3-41596'],
2321
size: 400,
2422
controller: blobCtrl,
2523
),

‎example/lib/examples/static/static_multiple_hash.dart

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,41 +15,23 @@ class StaticMultipleHashExample extends StatelessWidget {
1515
child: Column(
1616
mainAxisSize: MainAxisSize.min,
1717
children: [
18+
Container(
19+
child: Blob.fromHash(
20+
hash: ['6-3-22556', '6-3-90151', '6-3-79206'],
21+
size: 300,
22+
controller: blobCtrl,
23+
),
24+
),
25+
SizedBox(height: 30),
1826
Row(
1927
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
2028
children: [
21-
Blob.fromHash(
22-
hash: [
23-
'H4sIAB5VwV4A/w3KwQ0AMQjEwIb8YNmQcLWc0n8b4WWN5N8lMgJn4jLqcZvck8URcqPaFPkFfVizd9wHDGCsqzsAAAA=',
24-
],
25-
size: 50,
26-
),
27-
Blob.fromHash(
28-
hash: [
29-
'H4sIADZVwV4A/w3KsREAMQjEwIYU3IENdi2e77+NJ9hEo5cuQiLaxBXuRXrcSQer8N6jOKSCTtb8R98PT0B1nTwAAAA='
30-
],
31-
size: 50,
32-
),
33-
Blob.fromHash(
34-
hash: [
35-
'H4sIAEFVwV4A/w3LsRHAQAjEwIYUHIcf+Fo87r8NE2wmvXkLS6TXEVEmq+jG55JNOIhZMXjrEc8Oo+8H5uyPHz0AAAA='
36-
],
37-
size: 50,
38-
),
29+
Blob.fromHash(hash: ['6-3-22556'], size: 50),
30+
Blob.fromHash(hash: ['6-3-90151'], size: 50),
31+
Blob.fromHash(hash: ['6-3-79206'], size: 50),
3932
],
4033
),
4134
SizedBox(height: 30),
42-
Container(
43-
child: Blob.fromHash(
44-
hash: [
45-
'H4sIAB5VwV4A/w3KwQ0AMQjEwIb8YNmQcLWc0n8b4WWN5N8lMgJn4jLqcZvck8URcqPaFPkFfVizd9wHDGCsqzsAAAA=',
46-
'H4sIADZVwV4A/w3KsREAMQjEwIYU3IENdi2e77+NJ9hEo5cuQiLaxBXuRXrcSQer8N6jOKSCTtb8R98PT0B1nTwAAAA=',
47-
'H4sIAEFVwV4A/w3LsRHAQAjEwIYUHIcf+Fo87r8NE2wmvXkLS6TXEVEmq+jG55JNOIhZMXjrEc8Oo+8H5uyPHz0AAAA='
48-
],
49-
size: 400,
50-
controller: blobCtrl,
51-
),
52-
),
5335
Button('Randomize', onTap: () {
5436
blobCtrl.change();
5537
})

‎example/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ packages:
2828
path: ".."
2929
relative: true
3030
source: path
31-
version: "1.0.0+2"
31+
version: "1.1.0"
3232
boolean_selector:
3333
dependency: transitive
3434
description:

‎example/pubspec.yaml

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,10 @@ flutter:
5353
# "family" key with the font family name, and a "fonts" key with a
5454
# list giving the asset and other descriptors for the font. For
5555
# example:
56-
# fonts:
57-
# - family: Schyler
58-
# fonts:
59-
# - asset: fonts/Schyler-Regular.ttf
60-
# - asset: fonts/Schyler-Italic.ttf
61-
# style: italic
62-
# - family: Trajan Pro
63-
# fonts:
64-
# - asset: fonts/TrajanPro.ttf
65-
# - asset: fonts/TrajanPro_Bold.ttf
66-
# weight: 700
56+
fonts:
57+
- family: Ropa
58+
fonts:
59+
- asset: assets/Ropa_Sans/RopaSans-Regular.ttf
6760
#
6861
# For details regarding fonts from package dependencies,
6962
# see https://flutter.dev/custom-fonts/#from-packages

‎lib/src/clipper/clipper.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class BlobClipper extends CustomClipper<Path> {
2121
minGrowth: minGrowth,
2222
size: size,
2323
).generate();
24-
return shape(blobData);
24+
return connectPoints(blobData.curves);
2525
}
2626

2727
@override

‎lib/src/models.dart

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,37 @@ class BlobDots {
44
final List<List<Offset>> dots;
55
final double innerRad;
66
final num originalSize;
7+
final num hash;
78

8-
BlobDots({this.dots, this.innerRad, this.originalSize});
9+
BlobDots({this.dots, this.innerRad, this.originalSize, this.hash});
910
}
1011

1112
class BlobData {
12-
final List<List<Offset>> dots;
13-
final double innerRad;
14-
final String svgPath;
15-
final BlobPainterCoords coords;
16-
final String hash;
17-
final int edgesCount;
18-
final int minGrowth;
19-
final Size size;
20-
final num originalSize;
13+
int growth;
14+
num size;
15+
int edges;
16+
BlobPoints points;
17+
String id;
18+
Path path;
19+
String svgPath;
20+
BlobCurves curves;
2121

2222
BlobData({
23-
this.dots,
24-
this.innerRad,
25-
this.svgPath,
26-
this.coords,
27-
this.hash,
28-
this.edgesCount,
29-
this.minGrowth,
23+
this.growth,
3024
this.size,
31-
this.originalSize,
25+
this.edges,
26+
this.points,
27+
this.id,
28+
this.path,
29+
this.svgPath,
30+
this.curves,
3231
});
3332
}
3433

35-
class BlobPainterCoords {
34+
class BlobCurves {
3635
final Offset start;
3736
final List<List<double>> curves;
38-
BlobPainterCoords(this.start, this.curves);
37+
BlobCurves(this.start, this.curves);
3938
}
4039

4140
enum BlobFillType { fill, stroke }
@@ -52,3 +51,18 @@ class BlobStyles {
5251
this.strokeWidth,
5352
});
5453
}
54+
55+
class BlobPoints {
56+
List<Offset> originPoints;
57+
List<Offset> destPoints;
58+
Offset center;
59+
double innerRad;
60+
String id;
61+
BlobPoints({
62+
this.originPoints,
63+
this.destPoints,
64+
this.center,
65+
this.id,
66+
this.innerRad,
67+
});
68+
}

‎lib/src/painter/painter.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@ class BlobPainter extends CustomPainter {
1515

1616
@override
1717
void paint(Canvas c, Size s) {
18-
path(c, blobData, styles: styles);
18+
drawBlob(c, blobData.path, styles);
1919
if (debug) {
2020
circle(c, s, (s.width / 2)); // outer circle
21-
circle(c, s, blobData.innerRad); // inner circle
21+
circle(c, s, blobData.points.innerRad); // inner circle
2222
point(c, Offset(s.width / 2, s.height / 2)); // center point
23-
blobData.dots.forEach(
24-
(dot) => drawLines(c, dot[0], dot[1]),
25-
); // line from inner circle to blob point
23+
List originPoints = blobData.points.originPoints;
24+
List destPoints = blobData.points.destPoints;
25+
originPoints.asMap().forEach(
26+
(i, p) => drawLines(c, p, destPoints[i]),
27+
); // line from inner circle to blob point
2628
}
2729
}
2830

‎lib/src/painter/tools.dart

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ point(Canvas canvas, Offset center) {
5555
canvas.drawPath(path, paint);
5656
}
5757

58-
path(Canvas canvas, BlobData data, {BlobStyles styles}) {
58+
Paint createPaint(BlobStyles styles) {
5959
Map<BlobFillType, PaintingStyle> fillType = {
6060
BlobFillType.fill: PaintingStyle.fill,
6161
BlobFillType.stroke: PaintingStyle.stroke
@@ -68,22 +68,22 @@ path(Canvas canvas, BlobData data, {BlobStyles styles}) {
6868
paint.strokeWidth = (styles.strokeWidth ?? BlobConfig.strokeWidth).toDouble();
6969
paint.style = fillType[styles.fillType ?? BlobConfig.fillType];
7070

71-
Path path = shape(data);
72-
// canvas.drawShadow(path, Colors.red.withOpacity(0.8), 10, true);
73-
if (data.originalSize != null && (data.originalSize != data.size.width)) {
74-
canvas.scale(data.size.width / data.originalSize);
75-
}
76-
77-
canvas.drawPath(path, paint);
78-
return path;
71+
return paint;
7972
}
8073

81-
Path shape(BlobData data) {
74+
Path connectPoints(BlobCurves curves) {
8275
var path = Path();
83-
path.moveTo(data.coords.start.dx, data.coords.start.dy);
84-
data.coords.curves.forEach((curve) {
76+
path.moveTo(curves.start.dx, curves.start.dy);
77+
curves.curves.forEach((curve) {
8578
path.quadraticBezierTo(curve[0], curve[1], curve[2], curve[3]);
8679
});
8780
path.close();
81+
8882
return path;
8983
}
84+
85+
void drawBlob(Canvas canvas, Path path, BlobStyles styles) {
86+
Paint paint = createPaint(styles);
87+
// canvas.drawShadow(path, Colors.red.withOpacity(0.8), 10, true);
88+
canvas.drawPath(path, paint);
89+
}

‎lib/src/services/blob_animator.dart

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import 'package:flutter/material.dart';
2+
3+
class BlobAnimator {
4+
List<Offset> pathPoints;
5+
AnimationController animationController;
6+
List<List<Tween>> tweens = [];
7+
List<List<Animation>> anims = [];
8+
9+
BlobAnimator({this.pathPoints, this.animationController});
10+
11+
init(Function(List<Offset>) callback) {
12+
Animation<double> animation = CurvedAnimation(
13+
parent: animationController,
14+
curve: Curves.easeOutBack,
15+
);
16+
pathPoints.asMap().forEach((i, p) {
17+
tweens.insert(i, []);
18+
anims.insert(i, []);
19+
20+
tweens[i].add(Tween(begin: 0, end: 0));
21+
anims[i].add(tweens[i][0].animate(animation));
22+
23+
tweens[i].add(Tween(begin: 0, end: 0));
24+
anims[i].add(tweens[i][1].animate(animation));
25+
});
26+
animationController.addListener(() {
27+
List<Offset> transitionPoints = [];
28+
anims.asMap().forEach((i, value) {
29+
transitionPoints.add(Offset(
30+
anims[i][0].value.toDouble(),
31+
anims[i][1].value.toDouble(),
32+
));
33+
});
34+
callback(transitionPoints);
35+
});
36+
morphTo(pathPoints);
37+
}
38+
39+
morphTo(List<Offset> newPathPoints) {
40+
tweens.asMap().forEach((i, tween) {
41+
tween[0].begin = tween[0].end;
42+
tween[0].end = newPathPoints[i].dx;
43+
44+
tween[1].begin = tween[1].end;
45+
tween[1].end = newPathPoints[i].dy;
46+
});
47+
animationController.reset();
48+
animationController.forward();
49+
}
50+
}

‎lib/src/services/blob_controller.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ class BlobController {
77
_listener = ex;
88
}
99

10-
change() {
11-
if (_listener == null) return;
10+
BlobData change() {
11+
if (_listener == null) return BlobData();
1212
return _listener();
1313
}
1414

‎lib/src/services/blob_converter.dart

Lines changed: 0 additions & 65 deletions
This file was deleted.

‎lib/src/services/blob_generator.dart

Lines changed: 103 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import 'dart:math';
2+
import 'package:blobs/src/painter/tools.dart';
3+
import 'package:blobs/src/services/blob_error_handler.dart';
24
import 'package:flutter/material.dart';
35

46
import 'package:blobs/src/models.dart';
5-
import 'package:blobs/src/services/blob_converter.dart';
67

7-
class BlobGenerator with BlobConverter {
8-
final int edgesCount;
9-
final int minGrowth;
8+
class BlobGenerator {
109
final Size size;
10+
int edgesCount;
11+
int minGrowth;
1112
String svgPath = '';
1213
String hash;
1314
List<List<Offset>> dots = [];
@@ -19,27 +20,43 @@ class BlobGenerator with BlobConverter {
1920
this.size,
2021
});
2122

22-
BlobData generate(
23-
[List initialDots, double initialInnerRad, int originalSize]) {
24-
List<List<Offset>> dots = initialDots;
25-
double innerRad = initialInnerRad;
26-
27-
if (dots == null) {
28-
var blobDots = hash != null ? hashToDots(hash) : _createDots();
29-
dots = blobDots.dots;
30-
innerRad = blobDots.innerRad;
31-
originalSize = blobDots.originalSize;
23+
BlobData generate() {
24+
if (hash != null) {
25+
var datum = hash.split('-');
26+
if (datum.length != 3) throw InvalidHashIDException(hash);
27+
edgesCount = int.parse(datum[0]);
28+
minGrowth = int.parse(datum[1]);
29+
hash = datum[2];
3230
}
33-
List<Offset> endDots = dots.map((d) => d[1]).toList();
34-
BlobPainterCoords coords = _createPath(endDots);
31+
if (edgesCount <= 2) throw InvalidEdgesCountException();
32+
var points = _createPoints(hash != null ? int.parse(hash) : null);
33+
BlobCurves curves = _createCurves(points.destPoints);
34+
Path path = connectPoints(curves);
3535
return BlobData(
36-
dots: dots,
37-
innerRad: innerRad,
38-
coords: coords,
36+
edges: edgesCount,
37+
growth: minGrowth,
38+
id: points.id,
39+
path: path,
40+
points: points,
41+
size: size.width,
3942
svgPath: svgPath,
40-
size: size,
41-
originalSize: originalSize,
42-
hash: hash ?? dotsToHash(dots, size.width, innerRad.toInt()),
43+
curves: curves,
44+
);
45+
}
46+
47+
BlobData generateFromPoints(List<Offset> destPoints) {
48+
BlobCurves curves = _createCurves(destPoints);
49+
Path path = connectPoints(curves);
50+
BlobPoints points = _createPointsFromDest(destPoints);
51+
return BlobData(
52+
edges: 0,
53+
growth: 0,
54+
id: '',
55+
path: path,
56+
points: points,
57+
size: 0,
58+
svgPath: null,
59+
curves: curves,
4360
);
4461
}
4562

@@ -50,8 +67,24 @@ class BlobGenerator with BlobConverter {
5067
return List.generate(count, (i) => i * deg).toList();
5168
}
5269

53-
double _magicPoint(num min, num max) {
54-
double radius = min + (Random().nextDouble() * (max - min));
70+
// https://stackoverflow.com/a/29450606/3096740
71+
double Function() _randomDoubleGenerator(int seedValue) {
72+
var mask = 0xffffffff;
73+
int mw = (123456789 + seedValue) & mask;
74+
int mz = (987654321 - seedValue) & mask;
75+
76+
return () {
77+
mz = (36969 * (mz & 65535) + ((mz & mask) >> 16)) & mask;
78+
mw = (18000 * (mw & 65535) + ((mw & mask) >> 16)) & mask;
79+
80+
num result = (((mz << 16) + (mw & 65535)) & mask) >> 0;
81+
result /= 4294967296;
82+
return result;
83+
};
84+
}
85+
86+
double _magicPoint(double value, num min, num max) {
87+
double radius = min + (value * (max - min));
5588
if (radius > max) {
5689
radius = radius - min;
5790
} else if (radius < min) {
@@ -66,23 +99,63 @@ class BlobGenerator with BlobConverter {
6699
return Offset(x.round().toDouble(), y.round().toDouble());
67100
}
68101

69-
BlobDots _createDots() {
102+
BlobPoints _createPoints(int seedValue) {
70103
num outerRad = size.width / 2;
71104
num innerRad = minGrowth * (outerRad / 10);
72105
Offset center = Offset(size.width / 2, size.height / 2);
73106

74107
List<double> slices = _divide(edgesCount);
108+
int id;
109+
if (hash != null) {
110+
seedValue = int.parse(hash);
111+
} else {
112+
int maxRandomValue = ([99, 999, 9999, 99999, 999999]..shuffle()).first;
113+
id = Random().nextInt(maxRandomValue);
114+
seedValue = id;
115+
}
116+
var randVal = _randomDoubleGenerator(seedValue);
117+
List<Offset> originPoints = [];
118+
List<Offset> destPoints = [];
75119

76120
slices.forEach((degree) {
77-
double O = _magicPoint(innerRad, outerRad);
121+
double O = _magicPoint(randVal(), innerRad, outerRad);
78122
Offset start = _point(center, innerRad, degree);
79123
Offset end = _point(center, O, degree);
80-
dots.add([start, end]);
124+
originPoints.add(start);
125+
destPoints.add(end);
126+
});
127+
return BlobPoints(
128+
originPoints: originPoints,
129+
destPoints: destPoints,
130+
center: center,
131+
id: id == null ? null : '$edgesCount-$minGrowth-$id',
132+
innerRad: innerRad.toDouble(),
133+
);
134+
}
135+
136+
BlobPoints _createPointsFromDest(List<Offset> destPoints) {
137+
num outerRad = size.width / 2;
138+
num innerRad = minGrowth * (outerRad / 10);
139+
Offset center = Offset(size.width / 2, size.height / 2);
140+
141+
List<double> slices = _divide(edgesCount);
142+
143+
List<Offset> originPoints = [];
144+
145+
slices.forEach((degree) {
146+
Offset start = _point(center, innerRad, degree);
147+
originPoints.add(start);
81148
});
82-
return BlobDots(dots: dots, innerRad: innerRad);
149+
return BlobPoints(
150+
originPoints: originPoints,
151+
destPoints: destPoints,
152+
center: center,
153+
id: null,
154+
innerRad: innerRad.toDouble(),
155+
);
83156
}
84157

85-
BlobPainterCoords _createPath(List<Offset> points) {
158+
BlobCurves _createCurves(List<Offset> points) {
86159
List<List<double>> curves = [];
87160
Offset mid = (points[0] + points[1]) / 2;
88161
svgPath += 'M${mid.dx},${mid.dy}';
@@ -96,6 +169,6 @@ class BlobGenerator with BlobConverter {
96169
curves.add([p1.dx, p1.dy, mid.dx, mid.dy]);
97170
}
98171
svgPath += 'Z';
99-
return BlobPainterCoords(mid, curves);
172+
return BlobCurves(mid, curves);
100173
}
101174
}

‎lib/src/widgets/animated_blob.dart

Lines changed: 17 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:blobs/blobs.dart';
22
import 'package:blobs/src/models.dart';
3+
import 'package:blobs/src/services/blob_animator.dart';
34
import 'package:blobs/src/services/blob_generator.dart';
45
import 'package:blobs/src/widgets/simple_blob.dart';
56
import 'package:flutter/material.dart';
@@ -33,10 +34,9 @@ class AnimatedBlob extends StatefulWidget {
3334

3435
class _AnimatedBlobState extends State<AnimatedBlob>
3536
with SingleTickerProviderStateMixin {
36-
final List<List<Animation<double>>> _animations = [];
37-
final List<List<Tween<double>>> _tweens = [];
3837
AnimationController _animationController;
39-
List<List<int>> values = [];
38+
BlobAnimator animator;
39+
BlobData data;
4040

4141
@override
4242
void didUpdateWidget(AnimatedBlob oldWidget) {
@@ -47,80 +47,38 @@ class _AnimatedBlobState extends State<AnimatedBlob>
4747
@override
4848
void initState() {
4949
super.initState();
50-
values = List.generate(widget.toBlobData.dots.length,
51-
(index) => [widget.size ~/ 2, widget.size ~/ 2]);
5250
_animationController =
53-
AnimationController(duration: widget.duration, vsync: this)
54-
..addListener(() {
55-
setState(() {});
56-
});
57-
58-
var curvAnimation = CurvedAnimation(
59-
parent: _animationController,
60-
curve: Curves.easeOutBack,
61-
);
62-
values.forEach((v) {
63-
var t = [
64-
Tween(begin: 0.0, end: widget.toBlobData.coords.start.dx),
65-
Tween(begin: 0.0, end: widget.toBlobData.coords.start.dy),
66-
Tween(begin: 0.0, end: v[0].toDouble()),
67-
Tween(begin: 0.0, end: v[1].toDouble())
68-
];
69-
_tweens.add(t);
70-
_animations.add([
71-
t[0].animate(curvAnimation),
72-
t[1].animate(curvAnimation),
73-
t[2].animate(curvAnimation),
74-
t[3].animate(curvAnimation)
75-
]);
51+
AnimationController(duration: widget.duration, vsync: this);
52+
animator = BlobAnimator(
53+
animationController: _animationController,
54+
pathPoints: widget.toBlobData.points.destPoints);
55+
animator.init((o) {
56+
setState(() {
57+
data = BlobGenerator(
58+
edgesCount: widget.toBlobData.edges,
59+
minGrowth: widget.toBlobData.growth,
60+
size: Size(widget.size, widget.size),
61+
).generateFromPoints(o);
62+
});
7663
});
7764
setNewValue();
7865
}
7966

8067
setNewValue() {
81-
_tweens.asMap().forEach((i, tween) {
82-
tween[0].begin = tween[0].end;
83-
tween[0].end = widget.toBlobData.dots[i][0].dx;
84-
85-
tween[1].begin = tween[1].end;
86-
tween[1].end = widget.toBlobData.dots[i][0].dy;
87-
88-
tween[2].begin = tween[2].end;
89-
tween[2].end = widget.toBlobData.dots[i][1].dx;
90-
91-
tween[3].begin = tween[3].end;
92-
tween[3].end = widget.toBlobData.dots[i][1].dy;
93-
});
94-
_animationController.reset();
95-
_animationController.forward();
68+
animator.morphTo(widget.toBlobData.points.destPoints);
9669
}
9770

9871
@override
9972
Widget build(BuildContext context) {
10073
return SimpleBlob(
101-
blobData: _getBlobData(),
74+
blobData: data,
10275
styles: widget.styles,
10376
debug: widget.debug,
10477
size: widget.size,
10578
child: widget.child,
10679
);
10780
}
10881

109-
BlobData _getBlobData() {
110-
List<List<Offset>> dots = [];
111-
_animations.forEach((a) {
112-
dots.add(
113-
[Offset(a[0].value, a[1].value), Offset(a[2].value, a[3].value)]);
114-
});
115-
116-
return BlobGenerator(
117-
edgesCount: widget.toBlobData.edgesCount,
118-
minGrowth: widget.toBlobData.minGrowth,
119-
size: Size(widget.size, widget.size),
120-
).generate(
121-
dots, widget.toBlobData.innerRad, widget.toBlobData.originalSize);
122-
}
123-
12482
@override
12583
void dispose() {
12684
if (widget.ctrl != null) widget.ctrl.dispose();

‎pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# See https://dart.dev/tools/pub/glossary#lockfile
33
packages:
44
archive:
5-
dependency: "direct main"
5+
dependency: transitive
66
description:
77
name: archive
88
url: "https://pub.dartlang.org"

‎pubspec.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: blobs
22
description: Create beautiful blobs - fixed/random blob generation, animations, svgs and more
3-
version: 1.0.0+2
3+
version: 1.1.0
44
homepage: https://github.com/lokesh-coder/flutter_blobs
55

66
environment:
@@ -10,7 +10,6 @@ environment:
1010
dependencies:
1111
flutter:
1212
sdk: flutter
13-
archive: ^2.0.13
1413

1514
dev_dependencies:
1615
flutter_test:

0 commit comments

Comments
 (0)
Please sign in to comment.