/**
* ============================================================================
* = Animations Authoring =
* ============================================================================
*
* Animations are very powerful tools making your notebooks more interactive
* and engaging. In Recho Notebook, there are at least two ways to author
* animations. You can choose either one which suits you best.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Block-level Animations
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* You can author block-level animations using generators[1]. If one block
* refers a generator defined in another block, the referencing block will
* re-evaluate when the generator yields a value.
*
* For example, hereβs a generator `i` that increments once a second, defined
* directly by an immediately-invoked async generator function[2]. The
* referencing block `echo(i)` will update its value when the generator yields
* the next count.
*/
const i = (async function* () {
for (let j = 0; true; ++j) {
yield j;
await new Promise((resolve) => setTimeout(resolve, 1000));
}
})();
//β 1
echo(i);
/**
* As you can imagine, you can use such a generator to drive an animation. Here
* is a moving turtle animation.
*/
//β " π’"
{
const x = 40 - (i % 40);
const turtle = "π’".padStart(x);
echo(turtle);
}
/**
* If you are not familiar with generators or don't want to write the
* boilerplate code, you can use the `recho.interval` function to create a
* generator that yields values at a specified interval.
*
* For example, let's create a "bigger" moving animation[2].
*/
const snail = recho.interval(2000);
const turtle = recho.interval(1000);
const human = recho.interval(500);
const car = recho.interval(10);
const rocket = recho.interval(2);
//β ππ¨
//β π’π¨
//β πΆββοΈπ¨
//β ππ¨
//β ππ¨
{
const x = (count) => 40 - (count % 40);
echo("ππ¨".padStart(x(snail)));
echo("π’π¨".padStart(x(turtle)));
echo("πΆββοΈπ¨".padStart(x(human)));
echo("ππ¨".padStart(x(car)));
echo("ππ¨".padStart(x(rocket)));
}
/**
* In addition, you can use the `recho.now` function to create a generator that
* yields the current time continuously.
*/
const now = recho.now();
//β 1757422760841
echo(now);
/**
* This is a convenient way to create smoother animations.
*/
//β 1
const x = echo(Math.abs(~~(Math.sin(now / 1000) * 22)));
//β ~(ΰΉβ’Μγ
β’Μ)Ωβ§
echo("~".repeat(x) + "(ΰΉβ’Μγ
β’Μ)Ωβ§");
/**
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Browser Animation APIs
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* You can use the browser APIs to create animations, such as the `setInterval`
* or `requestAnimationFrame`. Compare to block-level animations, there are two
* differences:
*
* 1. You need to clear the output of the current block manually.
* 2. You need to register a disposal hook to clear the interval when the block
* is re-run.
*
* For example, let's create the same moving turtle animation using the
* `setInterval` function.
*/
//β " π’"
{
let i = 0;
const loop = () => {
const x = 40 - (i++ % 40);
const turtle = "π’".padStart(x);
echo.clear(); // Clear the output of the current block.
echo(turtle);
};
loop();
const interval = setInterval(() => loop(), 1000);
// Clear the interval when the block is re-run.
echo.dispose(() => clearInterval(interval));
}
/**
* Although the two approaches can achieve the same result, we highly recommend
* using block-level animations because it's more convenient, efficient and
* **declarative**!
*/
/**
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* References
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* - [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator
* - [2] https://vanjs.org/demo#hello-world
*/