Configure measurements in a PDF using JavaScript
Use Nutrient Web SDK 2022.5 or later to measure distance and area in a PDF. To use measurement tools in your app, contact the Sales team to add the Measurement Tools component to your license. You can also run the SDK in trial mode; refer to the getting started guide for setup.
This guide covers two tasks:
- Enable measurement tools to show measurement tools in the user interface (UI).
- Configure scale and precision. Scale defines a page length relative to a real-world length. For example, one centimeter on a floor plan can represent two meters in a house. Precision defines the decimal places or fractions shown in the measured value.
Display measurements as a secondary unit or as a compound mixed-unit value, such as 6 ft 3 in.
Nutrient Web SDK stores measurement scale and precision configurations in the document. These configurations persist when you close and reopen the document on any device. The active scale — the scale applied to new measurements — isn’t stored in the document.
Enabling measurement tools
By default, Nutrient Web SDK doesn’t show measurement tools in the main toolbar. To use them, your license must include the Measurement Tools component, and you must add the measurement toolbar item explicitly.
Add the measurement tools item to the toolbar configuration:
NutrientViewer.load({ // Other options. toolbarItems: [...NutrientViewer.defaultToolbarItems, { type: "measure" }]});Configuring scale and precision
Configure scale and precision with the built-in UI or with code:
Preserve the last-used scale across measurement tools.
Configuring scale and precision using the built-in UI
Use the built-in UI to configure scale and precision in one of two ways:
- Specify how a page length corresponds to a real-world length.
- Draw a line on the page and specify its real-world length.
To configure a scale by specifying the page length and real-world length, follow these steps:
- Click the measurement tools icon in the toolbar.
- For your first scale, click Set Scale.
- To create another scale, click the scales dropdown.
- Click Edit or add new scale.
- Click Add Scale.
- Rename the scale.
- Specify how a page length corresponds to a real-world length.
- In Precision, specify the decimal places or fractions to display.
- Use up to four decimal places or fractions up to one sixteenth.
- Click Done.
When you delete a scale, Nutrient Web SDK asks for confirmation and then deletes all measurements associated with that scale.
To configure a scale by drawing a line on the page, follow these steps:
- Click the measurement tools icon in the toolbar.
- Click the scales dropdown on the right.
- Click Use calibration tool or the calibration icon.
- Draw a line on the page.
- In Calibrate length, specify the line’s real-world length.
- Rename the scale.
- In Precision, specify the decimal places or fractions to display.
- Use up to four decimal places or fractions up to one sixteenth.
- Click Done.
Examples
The following example creates a scale where one centimeter in a floor plan represents one meter in a house.
The following example calibrates a scale where the distance measurement represents 24 meters in the real world.
The following example configures precision so the scale shows four decimal places.
Precision only affects the visible value label. The unrounded measurement value remains available through the API.
Selecting the scale for a measurement
Use the scales dropdown to change the scale for a selected measurement.
- Click a measurement.
- In the toolbar, click the scales dropdown.
- Select the scale for the measurement.
Configuring scales programmatically
To configure the scale of a measurement with code, use the measurementValueConfiguration property. The following example adds a custom scale where one centimeter in the document represents two meters in the real world. Nutrient Web SDK sets the new measurement as the default scale when the document loads.
const customScales = [ { name: "myScale", scale: { unitFrom: NutrientViewer.MeasurementScaleUnitFrom.CENTIMETERS, unitTo: NutrientViewer.MeasurementScaleUnitTo.METERS, fromValue: 1, toValue: 2 }, precision: NutrientViewer.MeasurementPrecision.FOUR, selected: true }];
NutrientViewer.load({ // Other options. measurementValueConfiguration: (documentScales) => { return [...customScales, ...documentScales]; }});The documentScales argument contains the scale configurations stored in the document. These configurations differ from the active scale, which Nutrient Web SDK applies to new measurements.
Nutrient Web SDK initializes the active scale from the returned array and uses the configuration marked with selected: true. If no configuration is selected, it uses the first configuration.
When you select a different scale while a measurement annotation is selected, Nutrient Web SDK updates that annotation. It also makes the selected scale the active scale. New measurements use the active scale. Existing annotations keep their own measurementScale values unless you select and change them.
Preserving the last-used scale
The built-in UI keeps the selected scale as the active scale for new measurements. If you create measurement annotations programmatically, capture the created annotation’s measurementScale. You can also use this approach to force the active scale to follow each newly created measurement. Then pass the scale to instance.setMeasurementScale().
This requires Nutrient Web SDK 1.14.0 or later. Earlier versions don’t apply the scale set with setMeasurementScale() to new measurements:
NutrientViewer.load({ // Other options.}).then((instance) => { instance.addEventListener("annotations.create", (annotations) => { const measurementAnnotation = annotations.find( (annotation) => annotation.measurementScale );
if (measurementAnnotation) { instance.setMeasurementScale(measurementAnnotation.measurementScale); } });});This listener makes the created annotation’s scale the new active scale. Nutrient Web SDK applies that scale the next time you select a measurement tool. If the scale matches an existing scale configuration, nothing else changes; otherwise, Nutrient Web SDK adds the scale to the document’s scale configurations.
The annotations.create event also fires for annotations created with code, and in collaborative setups, it fires for annotations created by other users.
setMeasurementScale() returns a promise that resolves after Nutrient Web SDK applies the scale. It accepts an optional second argument to name the scale and attach a compound unit chain. The chain must fit the scale’s unit. This example assumes a scale measured in feet:
await instance.setMeasurementScale(feetScale, { name: "Feet & Inches", compoundUnits: [ { unitTo: NutrientViewer.MeasurementScaleUnitTo.INCHES, precision: NutrientViewer.MeasurementPrecision.WHOLE } ]});Displaying a secondary unit of measurement
Display the measurement value in a secondary unit. The secondary unit appears in parentheses after the primary unit.
To display the measurement value in a secondary unit, follow these steps:
- Click the measurement tools icon in the toolbar.
- Click the scales dropdown on the right.
- Click Edit or add new scale.
- Enable Display Secondary Unit.
- Select the unit and precision for the secondary unit.
- Click Done.
Displaying compound (mixed-unit) measurements
A compound measurement shows one length as a chain of smaller units instead of a single decimal. For example, it shows 6 ft 3 in rather than 6.25 ft, which matches the “Feet & Inches” format used in construction. Compound measurements require Nutrient Web SDK 1.21 or later.
Nutrient Web SDK supports compound mixed-unit measurements only in standalone mode in the browser. Document Engine ignores compound units in server-backed mode, so measurements fall back to a single unit. For more information, refer to the operational mode guide.
Configure compound units per scale. The UI doesn’t include a control for them.
Add a compoundUnits array to a scale in measurementValueConfiguration. Each entry names the unit to append and the precision used to format it:
NutrientViewer.load({ // Other options. toolbarItems: [...NutrientViewer.defaultToolbarItems, { type: "measure" }], measurementValueConfiguration: (documentScales) => [ { name: "Feet & Inches", scale: { unitFrom: NutrientViewer.MeasurementScaleUnitFrom.INCHES, unitTo: NutrientViewer.MeasurementScaleUnitTo.FEET, fromValue: 1, toValue: 3 }, precision: NutrientViewer.MeasurementPrecision.TWO, compoundUnits: [ { unitTo: NutrientViewer.MeasurementScaleUnitTo.INCHES, precision: NutrientViewer.MeasurementPrecision.WHOLE } ], selected: true }, { name: "Meters", scale: { unitFrom: NutrientViewer.MeasurementScaleUnitFrom.CENTIMETERS, unitTo: NutrientViewer.MeasurementScaleUnitTo.METERS, fromValue: 1, toValue: 1 }, precision: NutrientViewer.MeasurementPrecision.TWO, compoundUnits: [ { unitTo: NutrientViewer.MeasurementScaleUnitTo.CENTIMETERS, precision: NutrientViewer.MeasurementPrecision.WHOLE }, { unitTo: NutrientViewer.MeasurementScaleUnitTo.MILLIMETERS, precision: NutrientViewer.MeasurementPrecision.WHOLE } ] }, ...documentScales ]});The Feet & Inches scale now reads 6 ft 3 in. The Meters scale reads 5 m 29 cm 2 mm. Both labels appear while users draw and after they commit the measurement.
Rules for compound unit chains
Follow these rules when you define a compound unit chain:
- Order units largest to smallest. Each unit must be smaller than the previous unit, starting from the scale’s
unitTo. - Keep one unit system. Don’t mix metric units (
mm,cm,m,km) and imperial units (in,ft,yd,mi). Points (pt) have no smaller unit and can’t compound. - Use precision on the last entry only. Earlier units render as whole numbers. The last unit uses its configured precision, including fractions such as
1/16.
Invalid chains already stored on annotations fall back to single-unit labels. Invalid chains passed to measurementValueConfiguration or instance.setMeasurementScale() are rejected during validation.
Compound units support distance and perimeter measurements only. Area measurements ignore compoundUnits and render a single unit.
Persisting a compound scale in the document
Nutrient Web SDK stores the chain on each annotation as a PDF number format array. ISO 32000-2 §12.9 defines this array. Labels survive saving, reloading, and export. Compound measurements authored elsewhere, such as in Acrobat, also load correctly.
A measurement with a chain keeps that chain. Nutrient Web SDK reads the annotation chain before the configured scales. When a user resizes the measurement or switches its scale, Nutrient Web SDK recomputes the label against that chain. This doesn’t require measurementValueConfiguration.
Measurements drawn before you configure compound units don’t have a stored chain. Nutrient Web SDK matches their scale against the configured scales instead, using exact values for unitFrom, unitTo, fromValue, and toValue. A calibrated scale with slightly different values keeps its single-unit label.
These measurements display compound labels immediately. Because the label comes from your configuration instead of the file, they export as single-unit measurements until a user edits each one.
The primary unit stays the first entry in the array, and a viewer that reads only that entry shows a correct single-unit label. This includes earlier Nutrient Web SDK versions, another Nutrient platform, or a third-party reader. Nutrient Web SDK writes single-unit measurements exactly as before.
To store a scale and its chain in the document, pass it to instance.setMeasurementScale():
await instance.setMeasurementScale( new NutrientViewer.MeasurementScale({ unitFrom: NutrientViewer.MeasurementScaleUnitFrom.INCHES, unitTo: NutrientViewer.MeasurementScaleUnitTo.FEET, fromValue: 1, toValue: 3 }), { name: "Feet & Inches", compoundUnits: [ { unitTo: NutrientViewer.MeasurementScaleUnitTo.INCHES, precision: NutrientViewer.MeasurementPrecision.WHOLE } ] });Nutrient Web SDK then offers the scale in the scales dropdown after the document reopens. The chain stays intact without measurementValueConfiguration, so users can draw new compound measurements with no further setup.
Reading the unit chain from an annotation
Each shape annotation exposes its persisted chain as measurementCompoundUnits. This property also appears in the annotation’s Instant JSON. Refer to the Instant JSON guide for import and export details:
const annotations = await instance.getAnnotations(0);const measurement = annotations.find((annotation) => annotation.measurementScale);
console.log(measurement.measurementCompoundUnits);// => [{ unitTo: "in", precision: "whole" }]measurementCompoundUnits is null for single-unit measurements. Nutrient Web SDK omits it from exported Instant JSON in that case, so older JSON needs no migration.
Snapping measurement points
When users draw with measurement tools, the cursor can snap to the nearest snapping point. Snapping points include endpoints, midpoints, and intersections in the document. Snapping is enabled by default. You can disable it at load time with measurementSnapping: false or toggle it later with instance.setMeasurementSnapping(false). Snapping helps users place measurement points precisely.
Nutrient Web SDK supports snapping measurement points to document geometry only in standalone mode in the browser. Snapping isn’t available with Document Engine in server-backed mode. For more information, refer to the operational mode guide.