Skip to main content

Β· 3 min read
Jacob

New features πŸŽ‰β€‹

  • aarthificial's avatarA brand-new Code node with dedicated code signals, customizable syntax highlighting, and more expressive animation system (Including automatic diff-based transitions).#946
    Press play to preview the animation
    import ...

    export default makeScene2D(function* (view) {
    const code = createRef<Code>();

    view.add(
    <Code
    ref={code}
    fontSize={28}
    fontFamily={'JetBrains Mono, monospace'}
    offsetX={-1}
    x={-400}
    code={'const number = 7;'}
    />,
    );

    yield* waitFor(0.6);
    yield* all(
    code().code.replace(code().findFirstRange('number'), 'variable', 0.6),
    code().code.prepend(0.6)`function example() {\n `,
    code().code.append(0.6)`\n}`,
    );

    yield* waitFor(0.6);
    yield* code().selection(code().findFirstRange('variable'), 0.6);

    yield* waitFor(0.6);
    yield* all(
    code().code('const number = 7;', 0.6),
    code().selection(DEFAULT, 0.6),
    );
    });

  • aarthificial's avatarNew withDefaults helper function lets you quickly extend nodes with your own defaults.#982
    import {Txt, withDefaults} from '@motion-canvas/2d';

    export const MyTxt = withDefaults(Txt, {
    fill: 'rgba(255, 255, 255, 0.6)',
    fontFamily: 'JetBrains Mono',
    fontSize: 28,
    });
  • aarthificial's avatarWhen using loop, the iteration count can be omitted to create an infinite loop:#952
    // These two are equivalent:
    yield* loop(() => { /* animation */ });
    yield* loop(Infinity, () => { /* animation */ });
  • aarthificial's avatarNew spawn function lets you run animations in the background, from any place, without needing to yield them.#951
  • aarthificial's avatarPolygon now extendsCurve giving it access to all curve-related properties like startArrow and radius.#961
  • jmaen's avatarColor fields in the editor now come with a visual color picker.#962
  • aarthificial's avatarNew Vector2 methods: #985
  • aarthificial's avatarNew cardinalPoint method lets you mapOrigins and Directions to their corresponding cardinal points of the node.#988
  • aarthificial's avatarNew waitTransition lets you animate transitions using nodes.#983
  • aarthificial's avatarWhen passed to OpenGL, Matrix2D is now converted to a 3x3 square matrix (as opposed to a 3x2 matrix)#984
  • aarthificial's avatarThe view's cachePadding is now respected when calculating the cache size of individual nodes.#986
  • Niikelion's avatarPresentation Mode now supports PowerPoint shortcuts (Page Up, Page Down, etc.)#993
  • nvborisenko's avatarParts of the motion-canvas-player shadow root are now exposed using part and can be customized with CSS.#956
  • aarthificial's avatarFiddles on this website now play automatically when scrolled into view.#1001

Fixed bugs πŸ›β€‹

  • CactusPuppy's avatarAccount for italic fonts in cache.#968
  • rogerpinho's avatarFix typo in the Quickstart Guide.#974
  • aarthificial's avatarProperly handle offset when retrieving the absolute position of a node.#987
  • aarthificial's avatarFix the spline warning for reactive points.#981
Check out the Update Guide for information on how to update your existing projects.

Β· One min read
Jacob

New features πŸŽ‰β€‹

  • aarthificial's avatarShaders let you create custom visual effects using WebGL.#929#920
    Press play to preview the animation
    import ...

    // Original shader created by ufffd
    // https://www.shadertoy.com/view/lcfXD8
    const Shader = `\
    #version 300 es
    precision highp float;

    in vec2 screenUV;
    out vec4 outColor;

    uniform float time;
    uniform vec2 resolution;

    #define g(p) dot(sin(p),cos(p.zxy)) //

    float m(vec3 p){
    return (1.0 + 0.2 * sin(p.y * 6e2))
    * g(0.8 * g(8.0 * p) + 10.0 * p)
    * (1.0 + sin(time + length(p.xy) / 0.1))
    + 0.3 * sin(time * 0.15 + p.z * 5.0 + p.y)
    * (2.0 + g((sin(time * 0.2 + p.z * 3.0) * 350.0 + 250.0) * p));
    }

    void main() {
    vec3 r = normalize(vec3((screenUV - 0.5) * resolution, resolution.y));
    vec3 p;
    vec3 f;
    float e = 50.0;
    float d;
    float i;

    for (p.z = time / 4.0; i++ < 90.0 && e > 0.05; e = m(p += r * d)) {
    d += 0.02 * e;
    }

    f.x = 0.06 + 0.06 * sin(p.z);
    outColor = vec4(2.0 * m(p) - m(p - f) - m(p - f.yxy))
    * smoothstep(0.75, 1.05, 1.0 / d);
    }
    `;

    export default makeScene2D(function* (view) {
    view.add(<Rect shaders={Shader} size={view.size} />);

    yield* waitFor(10);
    });

  • aarthificial's avatarThe node inspector can be toggled on and off.#921
  • jmaen's avatarNumber inputs can be edited by dragging left and right.#917
Check out the Update Guide for information on how to update your existing projects.

Β· One min read
Jacob

New features πŸŽ‰β€‹

  • aarthificial's avatarA new scene graph tab lets you peek into the contents of the scene.#909#914Scene Graph Tab
  • jmaen's avatarHolding Shift + Ctrl lets you drag over the timeline to select the range. B and N can be used to snap the beginning and end of the range to the playhead.#907
  • aarthificial's avatarEditor plugins can now register custom inspectors that display information on the right side of the editor.#913

Fixed bugs πŸ›β€‹

  • aarthificial's avatarThe mouse is tracked correctly when dragging time events.#912
Check out the Update Guide for information on how to update your existing projects.

Β· 4 min read
Jacob

New features πŸŽ‰β€‹

  • aarthificial's avatarThe points of a Line can now be tweened.#853
    Press play to preview the animation
    import ...

    export default makeScene2D(function* (view) {
    const line = createRef<Line>();
    view.add(
    <Line
    ref={line}
    points={[
    [-150, 70],
    [150, 70],
    [0, -70],
    ]}
    stroke={'lightseagreen'}
    lineWidth={8}
    radius={20}
    closed
    />,
    );

    yield* line()
    .points(
    [
    [-150, 0],
    [0, 100],
    [150, 0],
    [150, -70],
    [-150, -70],
    ],
    2,
    )
    .back(2);
    });

  • aarthificial's avatarTxt nodes can now be nested inside each other.#861
    Press play to preview the animation
    import {Txt, makeScene2D} from '@motion-canvas/2d';

    export default makeScene2D(function* (view) {
    view.fill('#141414');
    view.add(
    <Txt fill={'white'} fontSize={32} width={720} textWrap>
    Whereas recognition of the inherent dignity and of the{' '}
    <Txt.i>equal</Txt.i> and inalienable rights of all members of
    the human family is the foundation of <Txt.b>freedom</Txt.b>,
    justice and <Txt fill="#25C281">peace</Txt> in the world.
    </Txt>,
    );
    });
  • aarthificial's avatarNew querying helpers let you find nodes in the scene.#852
  • rmhartog's avatarTransitions can now control which scene is drawn on top.#832
  • rmhartog's avatarA new Video.playbackRate property lets you control the speed of a video.#831
  • aarthificial's avatarThis version introduces the concept of experimental features. Marked with , these features are meant mostly for testing and gathering feedback. Find out more about them in this dedicated section.#876
  • aarthificial's avatarNew Editor Plugins allow you to extend the editor's interface. With them, you can define custom tabs in the sidebar and draw overlays on top of the animation preview or the presenter.#884
  • aarthificial's avatarThe timeline can now be scrubbed by holding down LMB and dragging left or right.#862
    For complex animation, dragging to the left may lag a bit since the entire generator must be re-run each time.
  • jmaen's avatarHovering over the audio icon now reveals a volume slider that lets you adjust the volume.#872
  • Vija02's avatarThe ArrowUp and ArrowDown keys allow you to control the volume.#856
  • aarthificial's avatarThe animation range is no longer editable by default. Just like with the audio track, hold SHIFT before dragging to edit it.#862
  • Vaibhavi-Sita's avatarWhen looping is disabled, the editor will seek back to the start of the animation and stop there instead of pausing at the end.#823
  • CactusPuppy's avatarVector2 now includes static properties representing each type of origin.#855
  • aarthificial's avatarapplyState can now be used to tween to the new state and not just immediately apply it.#859
  • aarthificial's avatarThe spawner has been deprecated in favor of the children property.#858
    view.add(
    // before
    <Node spawner={() => range(count()).map(() => <Node />)} />,
    );

    view.add(
    // after
    <Node>{() => range(count()).map(() => <Node />)}</Node>,
    );
  • rmhartog's avatarProject configuration now supports glob patterns#834
    import motionCanvas from '@motion-canvas/vite-plugin';
    import {defineConfig} from 'vite';

    export default defineConfig({
    plugins: [
    motionCanvas({
    project: './src/projects/*.ts',
    }),
    ],
    });
  • rmhartog's avatarOpacity is clamped between 0 and 1.#835
  • aarthificial's avatarErrors that occur when loading an image are now properly reported in the editor.#847

Fixed bugs πŸ›β€‹

  • aarthificial's avatarAdded a missing middle property to the LayoutProps interface.#891
  • aarthificial's avatarCardinal points now correctly account for the Node's offset.#883
  • aarthificial's avatar"Go to source" actions should work again.#895
  • shaikan's avatarUnusual characters in file names are now properly handled.#821
  • SleeklyCoding's avatarWhen opening the output directory, it will be automatically created if it doesn't exist.#787
  • aarthificial's avatarFixed line jitter under certain conditions.#863
  • rmhartog's avatarCorrectly calculate bounding boxes of Txt nodes.#836
  • aarthificial's avatarFixed tweening cardinal points.#829
Check out the Update Guide for information on how to update your existing projects.

Β· 2 min read
Jacob

New features πŸŽ‰β€‹

  • aarthificial's avatarNodes can now be skewed:#803
    Press play to preview the animation
    import ...

    export default makeScene2D(function* (view) {
    const ref = createRef<Img>();
    yield view.add(
    <Img
    ref={ref}
    skew={[-24, -12]}
    src="https://images.unsplash.com/photo-1696931073577-5638a6891e1e"
    width={240}
    radius={20}
    />,
    );

    yield* ref().skew([24, 12], 1, easeOutElastic).back(1);
    });

  • levirs565's avatarNew SVG node lets you display and tween SVG graphics.#763
    (The amount of supported SVG features is still limited, the node was designed mainly to support LaTeX tweening in the future update)
  • SleeklyCoding's avatarA new lineCount property lets you retrieve the number of lines in a code block.#802
  • aarthificial's avatarslideTransition now allows for diagonal movement defined using Origin.#801
  • aarthificial's avatarAny external changes made to the audio file are now picked up and automatically reflected in the editor.#793
  • aarthificial's avatarWhen rendering, an estimated remaining time is displayed in the bottom right.#795
  • me-nkr's avatarNew playback controls for seeking to the very beginning and end of the animation.#814
  • alsongarbuja's avatarWhen dragging time events, a line indicator is displayed to help precisely align the event with the audio.#808
  • aarthificial's avatarHolding MMB allows you to drag the timeline left and right.#794
  • aarthificial's avatarA new error warns about a missing image source.#817

Fixed bugs πŸ›β€‹

  • aarthificial's avatarSpecific event names, such as constructor no longer cause the editor to crash.#819
  • aarthificial's avatarAdded missing Curve properties to Circle.#805
  • aarthificial's avatarArrow heads now always point in the correct direction.#792
Check out the Update Guide for information on how to update your existing projects.

Β· 2 min read
Jacob

New features πŸŽ‰β€‹

  • aarthificial's avatarThe Rect and Circle nodes now extend Curvegiving them access to all its properties and methods:#771#759
    Press play to preview the animation
    import ...

    export default makeScene2D(function* (view) {
    const ref = createRef<Circle>();
    view.add(
    <Circle
    ref={ref}
    size={160}
    stroke={'lightseagreen'}
    lineWidth={8}
    endAngle={270}
    endArrow
    />,
    );

    yield* all(ref().start(1, 1), ref().rotation(180, 1, easeInCubic));
    ref().start(0).end(0);
    yield* all(ref().end(1, 1), ref().rotation(360, 1, easeOutCubic));
    });

  • levirs565's avatarNew SVG Path component:#700
    Press play to preview the animation
    import ...

    export default makeScene2D(function* (view) {
    view.add(
    <Path
    scale={8}
    position={-96}
    fill={'lightseagreen'}
    data={
    'M4 6.47L5.76 10H20v8H4V6.47M22 4h-4l2 4h-3l-2-4h-2l2 4h-3l-2-4H8l2 4H7L5 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4z'
    }
    />,
    );
    });

  • ksassnowski's avatarNew start and end signals for animating the Grid node.#761
  • aarthificial's avatarNew helper methods for managing references: #775
  • aarthificial's avatarImg and Video nodes with radius are automatically clipped.#773
  • ksassnowski's avatarBBox transformation methods accept PossibleMatrix2D.#770
  • aarthificial's avatarNew middle cardinal point.#758
  • ksassnowski's avatarNew rotate and polarLerp methods for Vector2.#756
  • Logon27's avatarThe editor now lets you copy the mouse coordinates by pressing P#737
  • aarthificial's avatarrestore() can be called without duration to restore the state immediately.#736

Fixed bugs πŸ›β€‹

  • aarthificial's avatarFixed the "Last updated by" information on documentation pages.#776
  • Caesarovich's avatarTimeline correctly displays small time ranges.#739
  • aarthificial's avatarIt's no longer possible to spawn multiple color pickers.#747
Check out the Update Guide for information on how to update your existing projects.

Β· 2 min read
Jacob

New features πŸŽ‰β€‹

  • aarthificial's avatarAll entities are now imported from the main entry point of each package. The only exception is the CodeBlock node which still requires the full import path:
    import {all, createRef} from '@motion-canvas/core';
    import {makeScene2D, Circle} from '@motion-canvas/2d';
    // the only exception:
    import {CodeBlock, insert} from '@motion-canvas/2d/lib/components/CodeBlock';
    Importing from subdirectories will continue to work until version 4.#721#710
  • aarthificial's avatarNew presenter and renderer plugin hooks.
    You can learn how to create your own plugins in the new Authoring Plugins guide.#723
  • ajs1998's avatarNew Random.gauss() method lets you generate random numbers using a gaussian (normal) distribution.#709
  • aarthificial's avatarUpdated sidebar design lets you hide the timeline and collapse panels by dragging.#692
  • aarthificial's avatarApplication-wide settings let you configure the project defaults and change the editor appearance. You can edit them in the settings tab on the left.#697
  • aarthificial's avatarYou can use a new eye dropper tool to pick colors from the canvas
    (see browser compatibility)#691
  • aarthificial's avatarError stack traces now include function names.#693
  • aarthificial's avatarOverall improvements to the Fiddle editor.#706#712#713

Fixed bugs πŸ›β€‹

  • aarthificial's avatarFix package.json entry.#720
  • aarthificial's avatarFix collapsable sections.#698
  • rtkid-nt's avatarUse project variables when rendering/presenting.#690
Check out the Update Guide for information on how to update your existing projects.

Β· 2 min read
Jacob

New features πŸŽ‰β€‹

  • aarthificial's avatarThe brand new Video (FFmpeg) exporter lets you render your animations directly to a video file. It's included by default (with the option to opt out) in all new projects created with npm init @motion-canvas. Check out the docs to learn how to install it in your existing projects.#673#660
  • aarthificial's avatarAn improved rendering button provides visual feedback about the rendering process.#662#681
  • aarthificial's avatarA new OUTPUT DIRECTORY button lets you reveal the current output directory in your file explorer. You can find it directly below the RENDER button.#663
  • aarthificial's avatarCollapsible panels are now animated.#671
  • aarthificial's avatarArray values, such as points of a Line, are now displayed in the inspector.#670
  • aarthificial's avatarThe create package now supports command-line arguments for providing answers without having to go through the interactive prompt:#668
    npm init @motion-canvas@latest -- --name Hello --path ./hello --language ts
  • aarthificial's avatarMeta fields can declare descriptions. When hovering over the field in the editor, the description will be displayed in a form of a tooltip.#664
  • aarthificial's avatarNew hooks let plugins extend the behavior of the player (The plugin documentation will be available soon).#679

Fixed bugs πŸ›β€‹

  • aarthificial's avatarCorrectly support URLs to external images.#678
  • aarthificial's avatarRemove the yellow dependency pre-bundling warning.#676
  • aarthificial's avatarFix editing the audio offset by dragging the waveform.#674
  • aarthificial's avatarIgnore children with disabled layout.#669
  • aarthificial's avatarPrevent Color tree shaking.#666
Check out the Update Guide for information on how to update your existing projects.

Β· 2 min read
Jacob

New features πŸŽ‰β€‹

  • aarthificial's avatarCardinal points let you position nodes relative to their corners and edges#636
    Press play to preview the animation
    import ...

    export default makeScene2D(function* (view) {
    const rect = createRef<Rect>();

    view.add(
    <>
    <Rect
    ref={rect}
    width={200}
    height={100}
    rotation={-10}
    fill={'#333333'}
    />
    <Rect
    size={50}
    fill={'#e6a700'}
    rotation={rect().rotation}
    // Try changing "right" to "top"
    right={rect().left}
    />
    <Rect
    size={100}
    fill={'#e13238'}
    rotation={10}
    bottomLeft={rect().bottomRight}
    />
    </>,
    );

    yield* rect().rotation(10, 1).to(-10, 1);
    });

  • aarthificial's avatarNew Ray node lets you easily define simple lines between two points.#628
  • aarthificial's avatarNew methods for chaining animations together:#651
    yield* circle().scale(0.5, 0.2)
    // tween to another value
    .to(2, 0.2)
    // wait for one second
    .wait(1)
    // tween back to the initial value
    .back(0.2)
    // execute a callback
    .do(() => circle().fill('red'))
    // run the given generator
    .run(circle().position.y(100, 2));
  • squigglesdev's avatarNew loopFor and loopUntil flow functions.#650#624
  • aarthificial's avatarExternal changes to images are now automatically reflected in the preview.#641
  • ksassnowski's avatarNew fromDegrees, createArcLerp and mod Vector2 methods.#640#622
  • aarthificial's avatarNew completion and arcLengthproperties for curves.#627#635
  • aarthificial's avatarNew DEG2RAD and RAD2DEG constants for converting between degrees and radians.#630
  • aarthificial's avatarYou can now toggle fiddles between the code , editor and preview mode (You can try it out in the example above).#642

Fixed bugs πŸ›β€‹

  • someguythatcodes's avatarClear DependencyContext promises once resolved.#617
  • aarthificial's avatarFix fiddle accessibility.#647
  • aarthificial's avatarFix cyclic dependency in cardinal points.#645
  • aarthificial's avatarCorrectly append Txt nodes to view.#644
  • aarthificial's avatarFix taking snapshots.#638#643
  • gmile's avatarFix a typo in a viewport ID.#620
Check out the Update Guide for information on how to update your existing projects.

Β· 2 min read
Jacob

New features πŸŽ‰β€‹

  • ksassnowski's avatarNew BΓ©zier nodes let you easily create splines consisting of only one segment: #603
    Press play to preview the animation
    import ...

    export default makeScene2D(function* (view) {
    const bezier = createRef<CubicBezier>();

    view.add(
    <CubicBezier
    ref={bezier}
    lineWidth={6}
    stroke={'lightseagreen'}
    p0={[-200, 0]}
    p1={[50, -200]}
    p2={[-50, 200]}
    p3={[200, 0]}
    />,
    );

    yield* bezier().start(1, 1);
    yield* bezier().start(0).end(0).end(1, 1);
    });

  • aarthificial's avatarNew Video properties: #601
    • play automatically plays the video
    • loop restarts the video upon reaching the end
  • aarthificial's avatarFiddles now support multiple examples. You can switch between them using the dropdown on the right side.

Fixed bugs πŸ›β€‹

  • aarthificial's avatarUPDATE AVAILABLE now links to the GitHub release page.#608
  • aarthificial's avatarVideos play smoothly when in presentation mode.#600
  • aarthificial's avatarReused async resources are now correctly awaited.#599
  • ksassnowski's avatarArrow orientations for splines are correctly calculated.#597
  • aarthificial's avatarThe showcase editor has been fixed.#589
Check out the Update Guide for information on how to update your existing projects.