diff --git a/demo/content.ts b/demo/content.ts
index 9360ef3..ed9003d 100644
--- a/demo/content.ts
+++ b/demo/content.ts
@@ -219,7 +219,7 @@ addCanvas(
const b = wobbleHandle(
frameTime,
period / 2 + (rb * period) / 2,
- point(width * 0.8, height * 0.5, -90, 150, 90, 150),
+ point(width * 0.8, height * 0.5, -90, 100, 90, 100),
true,
);
const c = wobbleHandle(
@@ -231,7 +231,7 @@ addCanvas(
const d = wobbleHandle(
frameTime,
period / 2 + (rd * period) / 2,
- point(width * 0.2, height * 0.5, 90, 150, -90, 150),
+ point(width * 0.2, height * 0.5, 90, 100, -90, 100),
true,
);
@@ -288,7 +288,7 @@ addCanvas(2, (ctx, width, height, animate) => {
drawOpen(ctx, start, end, false);
});
- return `Curves are drawn by the rendering software using the four input points. By connecting
+ return `Curves are rendered using the four input points (ends + handles). By connecting
points a0-a3 with a line and then splitting each line by the same percentage, we've reduced
the number of points by one. Repeating the same process with the new set of points until
there is only one point remaining (d0) produces a single point on the line. Repeating this
@@ -440,8 +440,8 @@ addCanvas(
});
return `The angle of the handles for each point is parallel with the imaginary line
- stretching between its neighbors. Technically, a polygon's points have zero
- length handles, but the angle can still be calculated.`;
+ stretching between its neighbors. Even when they have length zero, the angle of the
+ handles can still be calculated.`;
},
(ctx, width, height, animate) => {
const period = Math.PI * 1500;
@@ -483,7 +483,7 @@ addCanvas(
drawClosed(ctx, animatedBlob, true);
});
- return `The blob is then made smooth by extending the handles. The exact length becomes
+ return `The blob is then made smooth by extending the handles. The exact length
depends on the distance between the given point and it's next neighbor. This value is
multiplied by a ratio that would roughly produce a circle if the points had not been
randomly moved.`;
@@ -775,7 +775,10 @@ addCanvas(
});
return `Points can also be reversed without visually affecting the shape. Then, again can
- be shifted all around. In total there are 2 * num_points different orderings of the
+ be shifted all around. Although reversed ordering doesn't change the shape, it has a
+ dramatic effect on the animation as it makes the loop flip over itself.
+
+ In total there are 2 * num_points different orderings of the
points that can work for transition purposes.`;
},
);
@@ -845,8 +848,8 @@ addCanvas(
(ctx.canvas as any).animationID = animationID;
return `The added points can be removed at the end of a transition when the target shape has
- been reached. However if the animation is interrupted during interpolation there is no
- opportunity to clean up the extra points.`;
+ been reached. However, if the animation is interrupted during interpolation there is no
+ opportunity to clean up the extra points.`;
},
(ctx, width, height, animate) => {
const center: Coord = {x: width * 0.5, y: height * 0.5};
@@ -916,38 +919,80 @@ addCanvas(
});
return `Putting all these pieces together, the blob transition library can also be used to
- tween between non-blob shapes. The more detail a shape has, the more unconvincing the
- animation will look. In these cases, manually creating in-between frames can be a helpful
- tool.`;
+ tween between non-blob shapes. The more detail a shape has, the more unconvincing the
+ animation will look. In these cases, manually creating in-between frames can be a
+ helpful tool.`;
},
);
-addCanvas(1.8, (ctx, width, height, animate) => {
- const size = Math.min(width, height) * 0.8;
- const center: Coord = {x: width * 0.5, y: height * 0.5};
+addTitle(4, "Gooeyness");
- const animation = canvasPath();
+addCanvas(
+ 1.3,
+ (ctx, width, height, animate) => {
+ const size = Math.min(width, height) * 0.8;
+ const center: Coord = {x: (width - size) * 0.5, y: (height - size) * 0.5};
- wigglePreset(
- animation,
- {
- extraPoints: 2,
- randomness: 2,
- seed: Math.random(),
- size,
- },
- {
- offsetX: center.x - size / 2,
- offsetY: center.y - size / 2,
- },
- {
- speed: 2,
- },
- );
+ const animation = canvasPath();
- animate(() => {
- drawClosed(ctx, animation.renderPoints(), true);
- });
+ const genFrame = (duration: number) => {
+ animation.transition({
+ duration: duration,
+ blobOptions: {
+ extraPoints: 2,
+ randomness: 3,
+ seed: Math.random(),
+ size,
+ },
+ callback: () => genFrame(3000),
+ timingFunction: "ease",
+ canvasOptions: {offsetX: center.x, offsetY: center.y},
+ });
+ };
+ genFrame(0);
- return `TODO`;
-});
+ animate(() => {
+ drawClosed(ctx, animation.renderPoints(), true);
+ });
+
+ return `This library uses the keyframe model to define animations. This is a flexible
+ approach, but it does not lend itself well to the kind of gooey blob shapes invite.
+
+ When looking at this animation, you may be able to notice the rhythm of the
+ keyframes where the points start moving and stop moving at the same time.`;
+ },
+ (ctx, width, height, animate) => {
+ const size = Math.min(width, height) * 0.8;
+ const center: Coord = {x: width * 0.5, y: height * 0.5};
+
+ const animation = canvasPath();
+
+ wigglePreset(
+ animation,
+ {
+ extraPoints: 2,
+ randomness: 3,
+ seed: Math.random(),
+ size,
+ },
+ {
+ offsetX: center.x - size / 2,
+ offsetY: center.y - size / 2,
+ },
+ {
+ speed: 2,
+ },
+ );
+
+ animate(() => {
+ drawClosed(ctx, animation.renderPoints(), true);
+ });
+
+ return `In addition to the keyframe API, there is now also pre-built preset which produces a
+ gooey animation without much effort and much prettier results.
+
+ This approach uses a noise field instead of random numbers to move individual points
+ around continuously and independently. Repeated calls to a noise-field-powered random
+ number generator will produce self-similar results.`;
+ },
+);
diff --git a/index.html b/index.html
index 7d4b600..e03acec 100644
--- a/index.html
+++ b/index.html
@@ -1,4 +1,4 @@
-
\n In total there are 2 * num_points different orderings of the\n points that can work for transition purposes."}),(0,e.addCanvas)(1.3,function(e,a,o){var r=Math.random(),s=function(){return e.canvas.animationID!==r},c=1e3*Math.PI,h=.5*a,u=.5*o,f=.8*Math.min(a,o),p=(0,l.statefulAnimationGenerator)(function(e){return(0,t.mapPoints)((0,i.genFromOptions)(e.blobOptions),function(e){var n=e.curr;return n.x+=h-f/2,n.y+=u-f/2,n})},function(t){return(0,n.drawClosed)(e,t,!0)},function(){})(Date.now);requestAnimationFrame(function n(){s()||(e.clearRect(0,0,a,o),p.renderFrame(),requestAnimationFrame(n))});var m=function(){s()||p.transition(g())},b=-1,g=function(e){return void 0===e&&(e={}),b++,d({duration:c,timingFunction:"ease",callback:m,blobOptions:{extraPoints:Math.max(0,(0,t.mod)(b,4)-1),randomness:4,seed:Math.random(),size:f}},e)};return p.transition(g({duration:0})),e.canvas.onclick=function(){s()||p.playPause()},e.canvas.animationID=r,"The added points can be removed at the end of a transition when the target shape has\n been reached. However, if the animation is interrupted during interpolation there is no\n opportunity to clean up the extra points."},function(e,t,a,o){var r=.5*t,s=.5*a,l=.8*Math.min(t,a),d=function(e,n,t){for(var a=2*e,o=2*Math.PI/a,i=[],l=0;l
\n When looking at this animation, you may be able to notice the rhythm of the\n keyframes where the points start moving and stop moving at the same time."},function(e,t,a,o){var i=.8*Math.min(t,a),r=.5*t,s=.5*a,l=(0,c.canvasPath)();return(0,c.wigglePreset)(l,{extraPoints:2,randomness:3,seed:Math.random(),size:i},{offsetX:r-i/2,offsetY:s-i/2},{speed:2}),o(function(){(0,n.drawClosed)(e,l.renderPoints(),!0)}),"In addition to the keyframe API, there is now also pre-built preset which produces a\n gooey animation without much effort and much prettier results.\n
\n This approach uses a noise field instead of random numbers to move individual points\n around continuously and independently. Repeated calls to a noise-field-powered random\n number generator will produce self-similar results."});
+},{"./internal/layout":"rSMP","./internal/canvas":"PBVq","../internal/util":"NSCe","../internal/animate/timing":"SjCR","../internal/rand":"BWRk","../internal/gen":"BJ3L","../internal/animate/interpolate":"/Sl0","../internal/animate/prepare":"F/j+","../internal/animate/state":"+LE9","../public/animate":"+HZB"}]},{},["hNRT"], null)
+//# sourceMappingURL=/content.a90eb1ee.js.map