feat(tools): add eraser tool
This commit is contained in:
@@ -9,15 +9,16 @@ import type { AppStore } from "@editor/store";
|
||||
export type BrushSession = {
|
||||
layerId: string;
|
||||
previousPoint: Vec2D;
|
||||
mode: "brush" | "eraser";
|
||||
};
|
||||
|
||||
export function beginBrushSession(document: ImageDocument, editor: EditorState, point: Vec2D): BrushSession | undefined {
|
||||
if (editor.tools.activeTool !== "brush") return undefined;
|
||||
if (editor.tools.activeTool !== "brush" && editor.tools.activeTool !== "eraser") return undefined;
|
||||
const layerId = editor.selection.layerIds[0];
|
||||
if (!layerId) return undefined;
|
||||
const layer = findRasterLayer(document.artboards.flatMap((artboard) => artboard.layers), layerId);
|
||||
if (!layer || layer.locked || !layer.visible) return undefined;
|
||||
return { layerId, previousPoint: point };
|
||||
return { layerId, previousPoint: point, mode: editor.tools.activeTool };
|
||||
}
|
||||
|
||||
export async function updateBrushSession(options: {
|
||||
@@ -42,6 +43,7 @@ export async function updateBrushSession(options: {
|
||||
to: documentPointToAssetPoint(options.point, layer, asset.intrinsicSize.w, asset.intrinsicSize.h),
|
||||
color: options.color ?? "#111827",
|
||||
size: options.size ?? 8,
|
||||
mode: options.session.mode,
|
||||
});
|
||||
|
||||
options.store.dispatch(commandIds.documentUpdateAssetSource, { assetId: asset.id, source });
|
||||
@@ -63,6 +65,7 @@ async function drawStroke(options: {
|
||||
to: Vec2D;
|
||||
color: string;
|
||||
size: number;
|
||||
mode: "brush" | "eraser";
|
||||
}) {
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = Math.max(1, Math.round(options.width));
|
||||
@@ -72,6 +75,7 @@ async function drawStroke(options: {
|
||||
|
||||
const image = await loadImage(options.source);
|
||||
context.drawImage(image, 0, 0, canvas.width, canvas.height);
|
||||
context.globalCompositeOperation = options.mode === "eraser" ? "destination-out" : "source-over";
|
||||
context.strokeStyle = options.color;
|
||||
context.lineWidth = options.size;
|
||||
context.lineCap = "round";
|
||||
@@ -80,6 +84,7 @@ async function drawStroke(options: {
|
||||
context.moveTo(options.from.x, options.from.y);
|
||||
context.lineTo(options.to.x, options.to.y);
|
||||
context.stroke();
|
||||
context.globalCompositeOperation = "source-over";
|
||||
|
||||
return canvas.toDataURL("image/png");
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@ import type { CanvasInputState } from "./useCanvasInput";
|
||||
export function canvasCursorClass(interactionMode: InteractionMode, input: CanvasInputState) {
|
||||
if (input.isPanning) return "cursor-grabbing";
|
||||
if (isPanInteractionMode(interactionMode)) return "cursor-grab";
|
||||
if (interactionMode.type === "tool" && (interactionMode.tool === "crop" || interactionMode.tool === "brush")) return "cursor-crosshair";
|
||||
if (interactionMode.type === "tool" && (interactionMode.tool === "crop" || interactionMode.tool === "brush" || interactionMode.tool === "eraser")) return "cursor-crosshair";
|
||||
return "cursor-default";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user