@@ -219,7 +219,7 @@ addCanvas(
219
219
const b = wobbleHandle (
220
220
frameTime ,
221
221
period / 2 + ( rb * period ) / 2 ,
222
- point ( width * 0.8 , height * 0.5 , - 90 , 150 , 90 , 150 ) ,
222
+ point ( width * 0.8 , height * 0.5 , - 90 , 100 , 90 , 100 ) ,
223
223
true ,
224
224
) ;
225
225
const c = wobbleHandle (
@@ -231,7 +231,7 @@ addCanvas(
231
231
const d = wobbleHandle (
232
232
frameTime ,
233
233
period / 2 + ( rd * period ) / 2 ,
234
- point ( width * 0.2 , height * 0.5 , 90 , 150 , - 90 , 150 ) ,
234
+ point ( width * 0.2 , height * 0.5 , 90 , 100 , - 90 , 100 ) ,
235
235
true ,
236
236
) ;
237
237
@@ -288,7 +288,7 @@ addCanvas(2, (ctx, width, height, animate) => {
288
288
drawOpen ( ctx , start , end , false ) ;
289
289
} ) ;
290
290
291
- return `Curves are drawn by the rendering software using the four input points. By connecting
291
+ return `Curves are rendered using the four input points (ends + handles) . By connecting
292
292
points a0-a3 with a line and then splitting each line by the same percentage, we've reduced
293
293
the number of points by one. Repeating the same process with the new set of points until
294
294
there is only one point remaining (d0) produces a single point on the line. Repeating this
@@ -440,8 +440,8 @@ addCanvas(
440
440
} ) ;
441
441
442
442
return `The angle of the handles for each point is parallel with the imaginary line
443
- stretching between its neighbors. Technically, a polygon's points have zero
444
- length handles, but the angle can still be calculated.` ;
443
+ stretching between its neighbors. Even when they have length zero, the angle of the
444
+ handles can still be calculated.` ;
445
445
} ,
446
446
( ctx , width , height , animate ) => {
447
447
const period = Math . PI * 1500 ;
@@ -483,7 +483,7 @@ addCanvas(
483
483
drawClosed ( ctx , animatedBlob , true ) ;
484
484
} ) ;
485
485
486
- return `The blob is then made smooth by extending the handles. The exact length becomes
486
+ return `The blob is then made smooth by extending the handles. The exact length
487
487
depends on the distance between the given point and it's next neighbor. This value is
488
488
multiplied by a ratio that would roughly produce a circle if the points had not been
489
489
randomly moved.` ;
@@ -775,7 +775,10 @@ addCanvas(
775
775
} ) ;
776
776
777
777
return `Points can also be reversed without visually affecting the shape. Then, again can
778
- be shifted all around. In total there are 2 * num_points different orderings of the
778
+ be shifted all around. Although reversed ordering doesn't change the shape, it has a
779
+ dramatic effect on the animation as it makes the loop flip over itself.
780
+ <br><br>
781
+ In total there are 2 * num_points different orderings of the
779
782
points that can work for transition purposes.` ;
780
783
} ,
781
784
) ;
@@ -845,8 +848,8 @@ addCanvas(
845
848
( ctx . canvas as any ) . animationID = animationID ;
846
849
847
850
return `The added points can be removed at the end of a transition when the target shape has
848
- been reached. However if the animation is interrupted during interpolation there is no
849
- opportunity to clean up the extra points.` ;
851
+ been reached. However, if the animation is interrupted during interpolation there is no
852
+ opportunity to clean up the extra points.` ;
850
853
} ,
851
854
( ctx , width , height , animate ) => {
852
855
const center : Coord = { x : width * 0.5 , y : height * 0.5 } ;
@@ -916,38 +919,80 @@ addCanvas(
916
919
} ) ;
917
920
918
921
return `Putting all these pieces together, the blob transition library can also be used to
919
- tween between non-blob shapes. The more detail a shape has, the more unconvincing the
920
- animation will look. In these cases, manually creating in-between frames can be a helpful
921
- tool.` ;
922
+ tween between non-blob shapes. The more detail a shape has, the more unconvincing the
923
+ animation will look. In these cases, manually creating in-between frames can be a
924
+ helpful tool.` ;
922
925
} ,
923
926
) ;
924
927
925
- addCanvas ( 1.8 , ( ctx , width , height , animate ) => {
926
- const size = Math . min ( width , height ) * 0.8 ;
927
- const center : Coord = { x : width * 0.5 , y : height * 0.5 } ;
928
+ addTitle ( 4 , "Gooeyness" ) ;
928
929
929
- const animation = canvasPath ( ) ;
930
+ addCanvas (
931
+ 1.3 ,
932
+ ( ctx , width , height , animate ) => {
933
+ const size = Math . min ( width , height ) * 0.8 ;
934
+ const center : Coord = { x : ( width - size ) * 0.5 , y : ( height - size ) * 0.5 } ;
930
935
931
- wigglePreset (
932
- animation ,
933
- {
934
- extraPoints : 2 ,
935
- randomness : 2 ,
936
- seed : Math . random ( ) ,
937
- size,
938
- } ,
939
- {
940
- offsetX : center . x - size / 2 ,
941
- offsetY : center . y - size / 2 ,
942
- } ,
943
- {
944
- speed : 2 ,
945
- } ,
946
- ) ;
936
+ const animation = canvasPath ( ) ;
947
937
948
- animate ( ( ) => {
949
- drawClosed ( ctx , animation . renderPoints ( ) , true ) ;
950
- } ) ;
938
+ const genFrame = ( duration : number ) => {
939
+ animation . transition ( {
940
+ duration : duration ,
941
+ blobOptions : {
942
+ extraPoints : 2 ,
943
+ randomness : 3 ,
944
+ seed : Math . random ( ) ,
945
+ size,
946
+ } ,
947
+ callback : ( ) => genFrame ( 3000 ) ,
948
+ timingFunction : "ease" ,
949
+ canvasOptions : { offsetX : center . x , offsetY : center . y } ,
950
+ } ) ;
951
+ } ;
952
+ genFrame ( 0 ) ;
951
953
952
- return `TODO` ;
953
- } ) ;
954
+ animate ( ( ) => {
955
+ drawClosed ( ctx , animation . renderPoints ( ) , true ) ;
956
+ } ) ;
957
+
958
+ return `This library uses the keyframe model to define animations. This is a flexible
959
+ approach, but it does not lend itself well to the kind of gooey blob shapes invite.
960
+ <br><br>
961
+ When looking at this animation, you may be able to notice the rhythm of the
962
+ keyframes where the points start moving and stop moving at the same time.` ;
963
+ } ,
964
+ ( ctx , width , height , animate ) => {
965
+ const size = Math . min ( width , height ) * 0.8 ;
966
+ const center : Coord = { x : width * 0.5 , y : height * 0.5 } ;
967
+
968
+ const animation = canvasPath ( ) ;
969
+
970
+ wigglePreset (
971
+ animation ,
972
+ {
973
+ extraPoints : 2 ,
974
+ randomness : 3 ,
975
+ seed : Math . random ( ) ,
976
+ size,
977
+ } ,
978
+ {
979
+ offsetX : center . x - size / 2 ,
980
+ offsetY : center . y - size / 2 ,
981
+ } ,
982
+ {
983
+ speed : 2 ,
984
+ } ,
985
+ ) ;
986
+
987
+ animate ( ( ) => {
988
+ drawClosed ( ctx , animation . renderPoints ( ) , true ) ;
989
+ } ) ;
990
+
991
+ return `In addition to the keyframe API, there is now also pre-built preset which produces a
992
+ gooey animation without much effort and much prettier results.
993
+ <br><br>
994
+ This approach uses a noise field instead of random numbers to move individual points
995
+ around continuously and independently. Repeated calls to a noise-field-powered random
996
+ number generator will produce self-similar results.` ;
997
+ } ,
998
+ ) ;
0 commit comments