feat(tools): add brush controls

This commit is contained in:
syntaxbullet
2026-07-03 17:49:00 +02:00
parent e75f8bc0a7
commit 64aebbe23a
12 changed files with 139 additions and 19 deletions

View File

@@ -25,8 +25,9 @@ export async function updateBrushSession(options: {
store: AppStore;
session: BrushSession;
point: Vec2D;
color?: string;
size?: number;
color: string;
size: number;
hardness: number;
}): Promise<BrushSession> {
const state = options.store.getState();
const layer = findRasterLayer(state.document.artboards.flatMap((artboard) => artboard.layers), options.session.layerId);
@@ -41,8 +42,9 @@ export async function updateBrushSession(options: {
height: asset.intrinsicSize.h,
from: documentPointToAssetPoint(options.session.previousPoint, layer, asset.intrinsicSize.w, asset.intrinsicSize.h),
to: documentPointToAssetPoint(options.point, layer, asset.intrinsicSize.w, asset.intrinsicSize.h),
color: options.color ?? "#111827",
size: options.size ?? 8,
color: options.color,
size: options.size,
hardness: options.hardness,
mode: options.session.mode,
});
@@ -65,6 +67,7 @@ async function drawStroke(options: {
to: Vec2D;
color: string;
size: number;
hardness: number;
mode: "brush" | "eraser";
}) {
const canvas = document.createElement("canvas");
@@ -75,8 +78,11 @@ async function drawStroke(options: {
const image = await loadImage(options.source);
context.drawImage(image, 0, 0, canvas.width, canvas.height);
const hardness = Math.max(0, Math.min(100, options.hardness)) / 100;
context.globalCompositeOperation = options.mode === "eraser" ? "destination-out" : "source-over";
context.strokeStyle = options.color;
context.shadowColor = options.mode === "eraser" ? "rgba(0,0,0,1)" : options.color;
context.shadowBlur = (1 - hardness) * options.size;
context.lineWidth = options.size;
context.lineCap = "round";
context.lineJoin = "round";

View File

@@ -103,7 +103,8 @@ export function useCanvasInput(
if (brushSession.current) {
const activeSessionId = brushSessionId.current;
const point = viewportPointToDocumentPoint(inputEvent.position, store.getState().editor.viewport);
void updateBrushSession({ store, session: brushSession.current, point }).then((nextSession) => {
const settings = store.getState().editor.tools.brush;
void updateBrushSession({ store, session: brushSession.current, point, color: settings.color, size: settings.size, hardness: settings.hardness }).then((nextSession) => {
if (brushSessionId.current === activeSessionId) brushSession.current = nextSession;
});
event.preventDefault();