Signature Pad

A headless drawing surface for a handwritten signature. The primitive renders one canvas with no styling of its own: give it a size and a border. The ink engine runs in the browser, so C# hears one call when a stroke finishes and nothing while one is being drawn.

A Pad, a Border and a Size

The primitive applies no width, no height and no border — position it or set a class on it. OnChange fires after a stroke is finished and after ClearAsync, UndoAsync or SetStrokesAsync, and its argument is whether the pad is now empty. Nothing is reported while a stroke is being drawn, which is what keeps a Blazor Server circuit to a handful of messages per signature.

Why It Reads as Ink

Two things. The path is a cubic Bezier through the samples rather than a polyline, and the stroke thins as the pen speeds up. MinWidth and MaxWidth set the range; VelocityWeight decides how much the newest speed reading counts — lower averages over more of the stroke for an even line, higher reacts to each flick for a sharper taper and a twitchier one. Draw fast and slow in each pad below.

The Three Output Forms

Draw on the left, then export. SVG is the form to store: one path per curve rather than the thousands of dots the canvas draws, with currentColor ink so it renders dark on paper and light on a dark page. PNG is the file that leaves the application, redrawn at an explicit colour — black by default, deliberately not the theme's ink. Raw samples are the smallest form and the only replayable one, and they carry the timings a later check of how a signature was written needs.

Replaying Stored Samples

The samples are held in CSS pixels, which is also how a resize or a move between monitors redraws what is there rather than losing it. SetStrokesAsync puts a stored signature back. A pad narrower than the one the signature was drawn on will clip it rather than scale it.

Disabled

Disabled ignores drawing. Whatever is already drawn stays visible, which is the behaviour a read-back of a signed document wants.

Data Attributes

The canvas carries its configuration as data attributes, which is how the browser side reads it:

  • [data-min-width] — the thinnest the line can get, in CSS pixels
  • [data-max-width] — the thickest the line can get, in CSS pixels
  • [data-velocity-weight] — how much the newest speed reading counts towards the width
  • [data-colour] — the ink colour, or empty to follow the element's computed color
  • [data-disabled] — present while drawing is ignored

It also carries an inline touch-action: none style, so a finger draws rather than scrolls.