mirror of
https://github.com/motion-canvas/motion-canvas.git
synced 2026-01-11 14:57:56 -05:00
feat: added useContext and useContextAfter hooks (#63)
The `useContext` hooks give direct access the the context to allow for transforming, clipping, and drawing to the canvas directly. The `useContext` hook runs before the scene is rendered, and so is most appropriate for altering the render through transforms and clipping. The `useContextAfter` hook runs after the scene is rendered, and so is most appropriate for altering the image data or drawing to the canvas. Fixes #58
This commit is contained in:
@@ -157,8 +157,12 @@ export class Project {
|
||||
);
|
||||
}
|
||||
|
||||
this.context.save();
|
||||
this.previousScene?.render(this.context, this.canvas);
|
||||
this.context.restore();
|
||||
this.context.save();
|
||||
this.currentScene.current?.render(this.context, this.canvas);
|
||||
this.context.restore();
|
||||
}
|
||||
|
||||
public reload(runners: SceneDescription[]) {
|
||||
|
||||
@@ -64,6 +64,23 @@ export abstract class GeneratorScene<T>
|
||||
}
|
||||
private readonly thread = new ValueDispatcher<Thread>(null);
|
||||
|
||||
public get onBeforeRendered() {
|
||||
return this.beforeRendered.subscribable;
|
||||
}
|
||||
protected readonly beforeRendered =
|
||||
new EventDispatcher<CanvasRenderingContext2D>();
|
||||
|
||||
public get onAfterRendered() {
|
||||
return this.afterRendered.subscribable;
|
||||
}
|
||||
protected readonly afterRendered =
|
||||
new EventDispatcher<CanvasRenderingContext2D>();
|
||||
|
||||
public get onReset() {
|
||||
return this.afterReset.subscribable;
|
||||
}
|
||||
private readonly afterReset = new EventDispatcher<void>();
|
||||
|
||||
private previousScene: Scene = null;
|
||||
private runner: ThreadGenerator;
|
||||
private state: SceneState = SceneState.Initial;
|
||||
@@ -168,7 +185,7 @@ export abstract class GeneratorScene<T>
|
||||
},
|
||||
);
|
||||
this.state = SceneState.Initial;
|
||||
setScene(this);
|
||||
this.afterReset.dispatch();
|
||||
await this.next();
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,9 @@ export class KonvaScene
|
||||
sceneCanvas.getContext()._context = context;
|
||||
}
|
||||
|
||||
this.beforeRendered.dispatch(context);
|
||||
this.view.drawScene(sceneCanvas);
|
||||
this.afterRendered.dispatch(context);
|
||||
}
|
||||
|
||||
public reset(previousScene: Scene = null) {
|
||||
|
||||
@@ -108,6 +108,27 @@ export interface Scene<T = unknown> {
|
||||
*/
|
||||
get onRecalculated(): SubscribableEvent<void>;
|
||||
|
||||
/**
|
||||
* Triggered before the scene is rendered with the Context2D.
|
||||
*
|
||||
* @event CanvasRenderingContext2D
|
||||
*/
|
||||
get onBeforeRendered(): SubscribableEvent<CanvasRenderingContext2D>;
|
||||
|
||||
/**
|
||||
* Triggered after the scene is rendered with the Context2D.
|
||||
*
|
||||
* @event CanvasRenderingContext2D
|
||||
*/
|
||||
get onAfterRendered(): SubscribableEvent<CanvasRenderingContext2D>;
|
||||
|
||||
/**
|
||||
* Triggered when the scene is reset.
|
||||
*
|
||||
* @event void
|
||||
*/
|
||||
get onReset(): SubscribableEvent<void>;
|
||||
|
||||
/**
|
||||
* Render the scene onto a canvas.
|
||||
*
|
||||
|
||||
@@ -3,3 +3,4 @@ export * from './useAnimator';
|
||||
export * from './useProject';
|
||||
export * from './useRef';
|
||||
export * from './useScene';
|
||||
export * from './useContext';
|
||||
|
||||
28
src/utils/useContext.ts
Normal file
28
src/utils/useContext.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import {useScene} from './useScene';
|
||||
import type {Scene} from '../scenes';
|
||||
|
||||
function subscribe(fn: (scene: Scene) => () => void) {
|
||||
const scene = useScene();
|
||||
if (scene == null) {
|
||||
throw new Error('no scene found from which to use the context');
|
||||
}
|
||||
const unsubScene = fn(scene);
|
||||
const unsubReset = scene.onReset.subscribe(unsubAll);
|
||||
function unsubAll() {
|
||||
unsubScene();
|
||||
unsubReset();
|
||||
}
|
||||
return unsubAll;
|
||||
}
|
||||
|
||||
export function useContext(
|
||||
callback: (ctx: CanvasRenderingContext2D) => void,
|
||||
): () => void {
|
||||
return subscribe(scene => scene.onBeforeRendered.subscribe(callback));
|
||||
}
|
||||
|
||||
export function useContextAfter(
|
||||
callback: (ctx: CanvasRenderingContext2D) => void,
|
||||
): () => void {
|
||||
return subscribe(scene => scene.onAfterRendered.subscribe(callback));
|
||||
}
|
||||
Reference in New Issue
Block a user