Whiteboard
Advanced · 11 min read · Updated Nov 10, 2026
Whiteboard Features: Build Drawing Tools, Lasso Selection, and Interactive Canvas Experiences
Whiteboard applications provide a flexible space where users can sketch ideas, draw shapes, annotate diagrams, and organize information visually. From brainstorming platforms to collaborative workflow editors, these tools make it easier to communicate complex ideas through visual interaction.
React Flow is primarily designed for building node-based user interfaces, including workflow editors, flowcharts, and interactive diagrams. However, developers can extend its canvas with whiteboard-style features such as freehand drawing, lasso selection, erasing, and rectangle creation.
By combining React Flow's node-based architecture with custom drawing interactions, you can build applications that support both structured diagrams and freeform visual content.
In this guide, we will explore how to add whiteboard features to React Flow, implement drawing and selection tools, handle erasing, create shapes, and choose the right libraries for building a complete online whiteboard.
What Are Whiteboard Features in React Flow?
Whiteboard features are interactive tools that allow users to draw, select, annotate, and manipulate visual elements on a canvas.
A traditional React Flow editor focuses on nodes and edges. A whiteboard-style editor extends that experience by allowing users to create freeform content alongside connected diagram elements.
For example, users might want to:
- Draw arrows or sketches around workflow nodes.
- Highlight important sections of a diagram.
- Select multiple nodes and annotations together.
- Erase unwanted drawings or visual elements.
- Create rectangles to group related content.
- Add visual notes during brainstorming sessions.
These capabilities are useful when building workflow editors, diagramming applications, brainstorming tools, visual planning systems, and interactive sketchboards.
1. Freehand Drawing: Create Sketches on the React Flow Canvas
Freehand drawing allows users to create custom paths by moving a mouse, stylus, or finger across the canvas.
It is useful for adding annotations, highlighting workflow sections, and sketching ideas around existing nodes.
React Flow's whiteboard examples include a freehand drawing feature available as a Pro example.
Key freehand drawing features
- Mouse and touch drawing.
- Adjustable brush size.
- Custom brush colors.
- Smooth drawing paths.
- Conversion of drawn paths into custom nodes.
Converting drawn paths into custom nodes is particularly useful because the drawings can become part of the React Flow graph rather than remaining separate visual elements.
For example, a user can draw a circle around an important workflow node or sketch an arrow to explain how information should move through a process.
How to implement freehand drawing
A common approach is to capture pointer coordinates and convert them into an SVG path.
The perfect-freehand library can help transform pointer input into smooth stroke geometry.
Install the dependency:
npm install perfect-freehand
Import the library:
import getStroke from 'perfect-freehand';
Define drawing options:
export const pathOptions = {
size: 7,
thinning: 0.5,
smoothing: 0.5,
streamline: 0.5,
easing: (t: number) => t,
start: {
taper: 0,
cap: true,
},
end: {
taper: 0.1,
cap: true,
},
};
Convert pointer coordinates into a smooth SVG path:
export function getSvgPathFromStroke(
stroke: number[][]
) {
if (!stroke.length) return '';
const d = stroke.reduce(
(acc, [x0, y0], i, arr) => {
const [x1, y1] = arr[(i + 1) % arr.length];
acc.push(
x0,
y0,
',',
(x0 + x1) / 2,
(y0 + y1) / 2
);
return acc;
},
['M', ...stroke[0], 'Q'] as (string | number)[]
);
d.push('Z');
return d.join(' ');
}
Generate the drawing path:
export function pointsToPath(
points: [number, number, number][],
zoom = 1
) {
const stroke = getStroke(points, {
...pathOptions,
size: pathOptions.size * zoom,
});
return getSvgPathFromStroke(stroke);
}
Each pointer point contains an X coordinate, Y coordinate, and pressure value. The resulting stroke can be rendered as an SVG path.
For a production drawing tool, you should also manage pointer events, coordinate conversion, stroke persistence, and cleanup when the user finishes drawing.
Important: Account for canvas zoom
Drawing interactions must account for React Flow's viewport transformations.
If pointer coordinates are collected in screen space but drawings are stored in flow coordinates, the resulting path can appear in the wrong position when the canvas is zoomed or panned.
Use the React Flow instance's screenToFlowPosition() method to convert screen coordinates into canvas coordinates.
This keeps drawings aligned with nodes and edges.
2. Lasso Selection: Select Multiple Nodes and Drawings
Lasso selection allows users to select multiple elements by drawing a freeform boundary around them.
Unlike ordinary click selection, users can select several nodes, annotations, and other canvas elements in one action.
This is especially useful in complex diagrams where elements are distributed across different areas.
How lasso selection works
A typical lasso selection interaction follows these steps:
- The user activates the lasso tool.
- The user clicks and drags across the canvas.
- The application records the pointer coordinates.
- The coordinates form a freeform selection boundary.
- The application checks which elements intersect the boundary.
- Matching elements are selected.
React Flow's whiteboard examples also demonstrate partial selection, allowing elements to be selected even when only part of them falls inside the selection area.
Implementing lasso selection logic
You can represent a lasso boundary as an array of points:
type Point = {
x: number;
y: number;
};
const lassoPoints: Point[] = [
{ x: 100, y: 100 },
{ x: 180, y: 90 },
{ x: 220, y: 150 },
{ x: 170, y: 220 },
{ x: 100, y: 180 },
];
For each node, you can test whether its position falls inside the lasso boundary.
A common geometric approach is the ray-casting algorithm:
function isPointInsidePolygon(
point: Point,
polygon: Point[]
) {
const { x, y } = point;
let inside = false;
for (
let i = 0, j = polygon.length - 1;
i < polygon.length;
j = i++
) {
const xi = polygon[i].x;
const yi = polygon[i].y;
const xj = polygon[j].x;
const yj = polygon[j].y;
const intersects =
yi > y !== yj > y &&
x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
if (intersects) {
inside = !inside;
}
}
return inside;
}
This function checks whether a point is inside a polygon.
For actual node selection, checking only the node's center is not enough when partial selection is required. You should test the node's bounding rectangle against the lasso polygon.
Common uses of lasso selection
- Selecting multiple workflow nodes.
- Moving groups of annotations.
- Selecting drawings and shapes together.
- Organizing large diagrams.
- Creating group operations in visual editors.
3. Eraser Tool: Remove Drawings and Canvas Elements
An eraser tool allows users to remove unwanted content by moving a cursor across the canvas.
Unlike a traditional delete button, an eraser uses spatial collision detection to determine which elements should be removed.
For example, a user might draw several annotations around a workflow and then erase only one unwanted section.
How an eraser works
A typical eraser interaction includes:
- Capture the eraser's current position.
- Define its collision area.
- Detect intersections with drawings or other elements.
- Identify the elements that should be removed.
- Update the canvas state.
An eraser can work with different types of visual content:
- Freehand paths.
- Rectangles and shapes.
- Annotations.
- Custom drawing nodes.
Detecting intersections between paths and shapes
For example, you can determine whether a point lies inside a rectangle:
type Point = [number, number];
type Rectangle = {
x: number;
y: number;
width: number;
height: number;
};
function pointInRectangle(
point: Point,
rect: Rectangle
) {
const [x, y] = point;
return (
x >= rect.x &&
x <= rect.x + rect.width &&
y >= rect.y &&
y <= rect.y + rect.height
);
}
You can also detect whether two line segments intersect:
function lineSegmentsIntersect(
p1: Point,
p2: Point,
p3: Point,
p4: Point
) {
const [x1, y1] = p1;
const [x2, y2] = p2;
const [x3, y3] = p3;
const [x4, y4] = p4;
const denom =
(x1 - x2) * (y3 - y4) -
(y1 - y2) * (x3 - x4);
if (Math.abs(denom) < 1e-10) {
return false;
}
const t =
((x1 - x3) * (y3 - y4) -
(y1 - y3) * (x3 - x4)) / denom;
const u =
-((x1 - x2) * (y1 - y3) -
(y1 - y2) * (x1 - x3)) / denom;
return (
t >= 0 &&
t <= 1 &&
u >= 0 &&
u <= 1
);
}
These utilities can form part of a larger collision detection system.
For more advanced erasing, you may need to account for stroke thickness, proximity thresholds, partial path removal, and multiple intersecting segments.
Common uses of the eraser tool
- Removing unwanted sketches.
- Cleaning up annotations.
- Editing freehand drawings.
- Removing visual elements from a diagram.
- Refining a brainstorming canvas.
4. Rectangle Drawing: Create Shapes and Visual Groups
Rectangle drawing allows users to create rectangular shapes by clicking and dragging across the canvas.
These shapes can be used to highlight sections, create visual containers, and group related workflow elements.
For example, a user building a marketing automation diagram might draw a rectangle around all nodes related to lead qualification.
Rectangle drawing interaction
A typical rectangle drawing process works like this:
- The user selects the rectangle tool.
- The application records the starting pointer position.
- The user drags to define the opposite corner.
- The application calculates the rectangle's dimensions.
- The rectangle is rendered on the canvas.
The rectangle can store four main properties:
type RectangleNodeData = {
x: number;
y: number;
width: number;
height: number;
fill: string;
stroke: string;
};
You can render the shape using SVG:
function RectangleShape({
width,
height,
fill,
stroke,
}: {
width: number;
height: number;
fill: string;
stroke: string;
}) {
return (
<svg
width={width}
height={height}
viewBox={`0 0 ${width} ${height}`}
>
<rect
x="1"
y="1"
width={width - 2}
height={height - 2}
fill={fill}
stroke={stroke}
strokeWidth="2"
rx="6"
/>
</svg>
);
}
In a React Flow application, the rectangle can be implemented as a custom node or as a separate canvas element, depending on whether it needs to participate in node selection, movement, and graph operations.
Where rectangle drawing is useful
- Highlighting important workflow sections.
- Creating visual backgrounds.
- Grouping related nodes.
- Building architecture diagrams.
- Organizing brainstorming sessions.
5. Combine Whiteboard Tools with React Flow Nodes and Edges
The real advantage of extending React Flow with whiteboard functionality is the ability to combine freeform drawing with structured node-based content.
A traditional whiteboard is designed for flexible visual expression. A workflow editor is designed for structured relationships and connections.
Combining both approaches allows developers to create a more versatile canvas.
For example, imagine a workflow planning application that contains:
- Connected nodes representing workflow steps.
- Edges representing dependencies.
- Freehand drawings for explanations.
- Rectangles highlighting related sections.
- Lasso selection for selecting multiple elements.
- Eraser tools for removing annotations.
The user can move between structured workflow editing and freeform brainstorming without switching applications.
Suggested canvas architecture
A useful architecture separates different types of canvas content:
| Layer | Responsibility |
|---|---|
| React Flow nodes | Structured workflow elements |
| React Flow edges | Connections between nodes |
| Drawing layer | Freehand paths and annotations |
| Shape layer | Rectangles and visual elements |
| Selection layer | Lasso boundaries and selection feedback |
| Interaction layer | Pointer events and active tools |
This separation makes the application easier to maintain and allows individual tools to evolve independently.
6. Manage Drawing Coordinates and Canvas Transformations
Coordinate management is one of the most important technical considerations when building whiteboard tools in React Flow.
The canvas supports panning and zooming. Therefore, pointer coordinates from the browser do not necessarily match the positions used by React Flow.
For example, a user might draw a line while the canvas is zoomed to 150%. If the application stores raw screen coordinates, the drawing may not remain aligned with the workflow after zooming or panning.
React Flow provides coordinate conversion methods through useReactFlow().
import { useReactFlow } from '@xyflow/react';
function DrawingTool() {
const { screenToFlowPosition } = useReactFlow();
function getCanvasPosition(
event: React.PointerEvent
) {
return screenToFlowPosition({
x: event.clientX,
y: event.clientY,
});
}
return null;
}
Use this conversion when collecting drawing points.
For a reliable drawing experience, also consider:
- Pointer capture while drawing.
- Touch and stylus support.
- Brush size scaling.
- Stroke smoothing.
- Drawing performance.
- Coordinate consistency after restoring a saved workflow.
7. Choose the Right Whiteboard Library for Your Application
React Flow can be extended with whiteboard functionality, but it is not intended to replace a complete whiteboard framework.
If your application needs advanced freeform drawing, text editing, shapes, collaboration, and a comprehensive set of whiteboard interactions, a dedicated library may be more appropriate.
Two popular options are:
is designed for building infinite-canvas and whiteboard experiences. It provides drawing, shapes, text, and other visual editing capabilities.
It is worth considering when the primary purpose of your application is freeform visual creation.
Official website: tldraw
Excalidraw provides a hand-drawn visual style for diagrams, sketches, and collaborative whiteboard experiences.
It is useful for applications that need a sketch-like interface with shapes, arrows, text, and freeform drawings.
Official website: Excalidraw
React Flow vs. dedicated whiteboard libraries
| Requirement | React Flow | Dedicated whiteboard library |
|---|---|---|
| Node-based workflows | Excellent fit | Depends on library |
| Connected edges and handles | Built-in | Usually needs custom implementation |
| Custom nodes | Built-in | Requires custom architecture |
| Freehand drawing | Extend with drawing tools | Usually a core feature |
| Lasso selection | Can be implemented | Often built in |
| Shapes and annotations | Custom implementation | Usually built in |
| Workflow automation | Excellent fit | Requires additional logic |
| Freeform visual editing | Requires extension | Excellent fit |
The right technology depends on the primary purpose of your application.
If structured workflows and node connections are central, React Flow is a strong foundation. If freeform drawing is the main experience, a dedicated whiteboard library may save significant development time.
8. Best Practices for Building React Flow Whiteboard Applications
When extending React Flow with whiteboard functionality, a few architectural decisions can make a significant difference.
Separate tools into independent components
Keep freehand drawing, rectangle creation, lasso selection, and erasing in separate modules.
This makes it easier to add new tools without affecting existing interactions.
Use a clear interaction mode
Maintain an active tool state, such as:
- Select
- Pan
- Draw
- Erase
- Rectangle
- Lasso
This prevents drawing interactions from conflicting with normal node selection and dragging.
Optimize drawing performance
Freehand drawing can generate many pointer events.
Consider using request batching, point sampling, and simplified paths to avoid unnecessary rendering.
Store drawings consistently
Choose a predictable data format for strokes and shapes.
For example, store drawing points, brush settings, and shape properties so that users can save and restore their work.
Support undo and redo
Drawing applications benefit significantly from history management.
Users should be able to undo or redo drawing actions, shape creation, deletion, and other canvas operations.
Consider accessibility and device support
Provide appropriate controls for keyboard users and ensure that drawing tools work with mouse, touch, and stylus input where applicable.
9. Build an Excalidraw-Style Sketchboard with VisualFlow
A visual workspace becomes more powerful when users can combine diagrams, drawings, annotations, and freeform ideas in one interface.
VisualFlow includes an Excalidraw Sketchboard example that explores this kind of experience by combining a React Flow-based environment with a hand-drawn visual approach.
It is useful as inspiration for building:
- Visual brainstorming tools.
- Interactive diagram editors.
- Sketch-based workflow planning.
- Whiteboard-style interfaces.
- Visual note-taking applications.
- Custom node-based design tools.
Explore the VisualFlow Excalidraw Sketchboard to see how a sketchboard-style interface can complement a node-based workflow experience.
You can also explore more React Flow examples and templates for ideas when building your next visual application.
Conclusion
Whiteboard features can make React Flow applications more flexible by combining structured workflow editing with freeform visual interaction.
With freehand drawing, lasso selection, eraser tools, and rectangle creation, developers can build interfaces that support brainstorming, annotation, diagram editing, and visual planning.
React Flow provides the foundation for node-based applications, while custom tools extend the canvas beyond traditional nodes and edges.
The most important decision is choosing the right architecture for your application. Extend React Flow when structured workflows are central to the experience, or consider a dedicated whiteboard library when freeform drawing is the primary requirement.
By combining the right tools, you can create interactive visual workspaces that are both flexible and powerful.