Dynamically Adjusting Font Size in Fabric.js
This article demonstrates dynamic font size adjustment using Fabric.js's IText object. If you're unfamiliar with Fabric.js, consider reviewing "From Beginner to Expert: A Comprehensive Guide to Fabric.js" for foundational knowledge.
Before diving into implementation, examine the visual example below to understand the expected behavior.
Requirements
The goal is to support three scenarios:
- Font size can only be modified when text is selected.
- Apply a uniform font size change across all text.
- Modify the font size of only selected characters, leaving others unchanged.
Implementation Strategy
- Retrieve the currently active text object using
canvas.getActiveObject(). - Determine if only a portion of the text is selected:
- Use the
isEditingproperty to detect whether the text is in edit mode. - Apply styles selectively via
setSelectionStyles({ 'fontSize': value })when partial selection is detected.
- Use the
- Update the
fontSizeproperty directly for full-text edits. - Handle cases where individual characters already have custom
fontSizevalues by iterating through the style matrix to override them.
Code Example
<input type="range" min="5" max="150" value="40" id="size" onchange="updateFontSize(value)">
<canvas id="c" width="300" height="300" style="border: 1px solid #ccc"></canvas>
<script src="https://cdn.bootcdn.net/ajax/libs/fabric.js/521/fabric.js"></script>
<script>
const canvas = new fabric.Canvas('c');
const editableText = new fabric.IText('Hello World', {
fontSize: 40,
fill: '#333'
});
canvas.add(editableText);
function updateFontSize(newValue) {
const selectedObject = canvas.getActiveObject();
if (!selectedObject || !(selectedObject instanceof fabric.IText)) return;
if (selectedObject.isEditing) {
// Partial selection: apply style to selected range
selectedObject.setSelectionStyles({ fontSize: newValue });
} else {
// Full text modification
selectedObject.fontSize = newValue;
const charStyles = selectedObject.styles;
// Traverse each line and character to ensure consistent font size
for (const lineIndex in charStyles) {
for (const charIndex in charStyles[lineIndex]) {
charStyles[lineIndex][charIndex].fontSize = newValue;
}
}
selectedObject.dirty = true; // Mark as dirty to trigger redraw
}
canvas.renderAll();
}
</script>
The isEditing flag helps distinguish between full-text and partial-text editing states. When in edit mode, setSelectionStyles applies changes only to selected portions. For non-editing state updates, a nested loop iterates over the styles object—first by line (lineIndex) then by character (charIndex)—ensuring that even characters with individually set fontSize values are uniformly updated.
This approach also extands naturally to advanced typographic features such as superscripts and subscripts, commonly used in mathematical expressions or chemical formulas.