Module API
Modules are plain objects or classes that implement one or more hook methods.
Toggle dynamic shape, transparency, spread, and pattern compositing to see how module hooks alter points, per-stamp config, and stroke mix-in.
interface Module {
onChangeConfig?(config: BrushBasicConfig, pressure: number): void;
onChangePoint?(
point: PurePoint,
config: BrushBasicConfig,
): PurePoint | PurePoint[];
onMixinCanvas?(
strokeCanvas: HTMLCanvasElement,
strokeContext: CanvasRenderingContext2D,
): [HTMLCanvasElement, CanvasRenderingContext2D];
onEndStroke?(): void;
}
Built-in modules also expose config and bindConfig(config), so you can either
mutate settings directly or replace the config reference with app state.
Hooks
onChangePoint
Runs before a point becomes a rendered stamp. Return one point to transform the input, or multiple points to create extra stamps.
onChangeConfig
Runs for each stamp with a copy of the active brush config. Mutate this config to change size, angle, opacity, flow, roundness, and other per-stamp behavior.
onMixinCanvas
Runs when the current stroke is composited onto the visible canvas. Return a canvas/context pair to replace or post-process the stroke canvas.
onEndStroke
Runs after a stroke is committed. Use it to reset cached stroke-local state.
Custom Module Example
import type { BrushBasicConfig, Module } from "fuderu";
class PressureColorModule implements Module {
onChangeConfig(config: BrushBasicConfig, pressure: number): void {
config.color = pressure > 0.5 ? "#111111" : "#888888";
}
}
brush.useModule(new PressureColorModule());
Built-In Module Configs
type JitterTrigger = "none" | "pressure";
interface DynamicShapeBasicConfig {
sizeJitter: number;
sizeJitterTrigger: JitterTrigger;
minDiameter: number;
angleJitter: number;
angleJitterTrigger: JitterTrigger;
roundJitter: number;
roundJitterTrigger: JitterTrigger;
minRoundness: number;
}
interface DynamicTransparencyBasicConfig {
opacityJitter: number;
opacityJitterTrigger: "none" | "pressure";
minOpacityJitter: number;
flowJitter: number;
flowJitterTrigger: "none" | "pressure";
minFlowJitter: number;
}
interface SpreadBasicConfig {
spreadRange: number;
spreadTrigger: "none" | "pressure";
count: number;
countJitter: number;
countJitterTrigger: "none" | "pressure";
}
interface PatternBasicConfig {
scale: number;
brightness: number;
contrast: number;
blendMode: CanvasRenderingContext2D["globalCompositeOperation"];
}
PatternModule.loadPattern(resource, canvasWidth, canvasHeight, tint?) accepts an
image element, canvas element, or URL string. removePattern() clears the active
texture.