svelte-text-path

auto-sizing text-path svelte library

NPM | GitHub

# Docs

As mentioned in the home demo, this library is a wrapper against the SVG text-path element to be reactive, and, most importantly, to auto-size the text to fit the path, similar to the likes of textFit.

Feel free to contribute or file issues on GitHub.

## Installation

svelte-text-path is an npm package.

npm install -D svelte-text-path yarn add -D svelte-text-path pnpm add -D svelte-text-path

## Reactivity

As with all Svelte components, the text-path element is reactive. The path, viewBox, and text are all reactive, and will update the text-path element when changed. In order to allow the text to be colored, the TextPath component uses slots, so that the text can be styled with tspan.

For example, you can bind the text to an input, as shown in the home demo.

Whereas recognition of the inherent dignity and of the equal and inalienable rights of all members of the human family is the foundation of freedom, justice and peace in the world, Whereas recognition of the inherent dignity and of the equal and inalienable rights of all members of the human family is the foundation of freedom, justice and peace in the world, 
<script lang="ts">
	import { Circle } from 'svelte-text-path';
	import { placeholder } from '../placeholder';
	let text = placeholder;
</script>

<input type="text" bind:value={text} />

<Circle>{@html text}</Circle>

## Auto-sizing

Auto-sizing allows the text to fit the path, without manual font-size adjustments. This uses the same algorithm present in textFit - a hidden text element is created, and the font-size is adjusted until the length of that text is the same as the length of the path with a O(log n) binary search.

If this behavior is not desired, the fontSize property can be set to a fixed value, which will be used instead of the auto-sizing algorithm.

This is some text that will autofit.This is some text that will autofit.

| font size: undefined

Note: if your users have JavaScript disabled, the text will not be auto-sized, and will instead be the default font-size. If you want to support users with JavaScript disabled, you should use the fixed fontSize property.

## Components

### TextPath

TextPath is the fundamental component of this library. It takes in the following:

  • path - the path to follow, in SVG path syntax
  • viewBox - the viewBox of the SVG, in the form of an array of four numbers, in the order [x, y, width, height]
  • fontSize - the font-size of the text, in pixels - if not specified, the text will be auto-sized
  • padding - the padding around the text, in percentage of the viewBox. Defaults to 0.1, to allow text ligatures that go past the viewBox to be visible.
Hello world! This is text in a slot. It goes in an SVG, so you can style it. Hello world! This is text in a slot. It goes in an SVG, so you can style it. 
<script lang="ts">
	import { TextPath } from 'svelte-text-path';
	const path = `M 10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80`;
</script>

<TextPath {path} viewBox={[0, 0, 200, 200]}>
	Hello world! This is text in a slot. It goes in an SVG, so you can <tspan fill="red">style</tspan>
	it.&nbsp;
</TextPath>

### Circle

For the simple use case of circular text, there is a Circle component, which takes in any slot content, and wraps it with the more versatile TextPath component.

Hello world! This is text in a slot. It goes in an SVG, so you can style it. Hello world! This is text in a slot. It goes in an SVG, so you can style it. 
<script lang="ts">
	import { Circle } from 'svelte-text-path';
</script>

<Circle>
	Hello world! This is text in a slot. It goes in an SVG, so you can <tspan fill="red">style</tspan>
	it.&nbsp;
</Circle>

A circle can also take in a range property, which is an array of two numbers between 0 and 1, which specifies the range of the circle to display.

Hello world! This is text in a slot. It goes in an SVG, so you can style it. Hello world! This is text in a slot. It goes in an SVG, so you can style it. 
<script lang="ts">
	import { Circle } from 'svelte-text-path';

	let range: [number, number] = [0, 1];
</script>

<input type="range" min="0" max={range[1]} step="0.01" bind:value={range[0]} />

<input type="range" min={range[0]} max="1" step="0.01" bind:value={range[1]} />

<Circle {range}>
	Hello world! This is text in a slot. It goes in an SVG, so you can <tspan fill="red">style</tspan>
	it.&nbsp;
</Circle>