4 stable releases
new 1.0.3 | Apr 10, 2025 |
---|---|
1.0.2 | Apr 6, 2025 |
#66 in Graphics APIs
486 downloads per month
97KB
519 lines
Rust Hand Drawn Path Generator
freedraw
Rust port of the perfect-freehand library for creating smooth freehand lines in SVG.
SVG Examples
This repository includes a Yew demo application that showcases various SVG examples generated with the freedraw
library.
Generating SVG Examples
The SVG examples are generated using the svg_conversion
tool:
cargo run --example svg_conversion
This will read data from the tests
directory and generate SVG files in the demo/dist
directory.
Running the Demo
To run the demo application:
cd demo
trunk serve
Then visit http://localhost:8080/freedraw/ in your browser.
Project Structure
src/
- Core library codetests/
- Test data and unit teststools/
- Utility scriptsdemo/
- Yew application for showcasing SVG examples
Overview
freedraw helps you create high-quality freehand strokes in Rust applications. It generates smooth, beautiful outlines from a series of input points, supporting pressure sensitivity and customizable styling.
Features
- Create beautiful, smooth freehand strokes
- Pressure-sensitive drawing with natural tapering
- Customizable stroke properties (size, smoothing, thinning)
- Simulate pressure based on velocity
- Generate SVG paths from strokes
- Built as a lightweight, pure Rust implementation
Installation
Add the dependency to your Cargo.toml:
[dependencies]
freedraw = "x.x.x"
Basic Usage
use freedraw::{get_stroke, InputPoint, StrokeOptions};
fn main() {
// Create some example points
let points = vec![
InputPoint::Array([100.0, 100.0], Some(0.5)),
InputPoint::Array([200.0, 150.0], Some(0.7)),
InputPoint::Array([300.0, 100.0], Some(0.5)),
];
// Create default options
let options = StrokeOptions::default();
// Generate the stroke outline
let outline = get_stroke(&points, &options);
// Use the outline points to draw a path
// (e.g., convert to SVG or render with a graphics library)
}
Converting to SVG Paths
The library includes a utility to convert stroke outlines to SVG path data:
use freedraw::{get_stroke, get_svg_path_from_stroke, InputPoint, StrokeOptions};
// Generate the stroke outline
let outline = get_stroke(&points, &options);
// Convert to SVG path data
let path_data = get_svg_path_from_stroke(&outline, true); // true = closed path
// Use in an SVG element
println!("<path d=\"{}\" fill=\"black\" />", path_data);
Options
You can customize the appearance of strokes using the StrokeOptions
struct:
let options = StrokeOptions {
size: Some(16.0), // Base size (diameter) of the stroke
thinning: Some(0.5), // Effect of pressure on stroke width
smoothing: Some(0.5), // How much to soften the stroke's edges
streamline: Some(0.5), // How much to streamline the stroke
simulate_pressure: Some(true), // Whether to simulate pressure based on velocity
start: Some(TaperOptions { // Tapering options for the start of the line
taper: Some(TaperType::Bool(true)),
..Default::default()
}),
end: Some(TaperOptions { // Tapering options for the end of the line
taper: Some(TaperType::Bool(true)),
..Default::default()
}),
..Default::default()
};
Option Details
Property | Type | Default | Description |
---|---|---|---|
size |
number | 8 | The base size (diameter) of the stroke. |
thinning |
number | .5 | The effect of pressure on the stroke's size. |
smoothing |
number | .5 | How much to soften the stroke's edges. |
streamline |
number | .5 | How much to streamline the stroke. |
simulatePressure |
boolean | true | Whether to simulate pressure based on velocity. |
last |
boolean | true | Whether the stroke is complete. |
The start
and end
options accept a TaperOptions
struct:
Property | Type | Default | Description |
---|---|---|---|
cap |
boolean | true | Whether to draw a cap. |
taper |
TaperType | None | The distance to taper. Can be a numerical value or boolean. |
easing |
EasingType | linear | An easing function for the tapering effect. |
Input Points
The library supports two formats for input points:
- Array format:
InputPoint::Array([x, y], pressure)
where pressure is optional - Struct format:
InputPoint::Struct { x, y, pressure }
where pressure is optional
If pressure is not provided, it defaults to 0.5.
Advanced Usage
For advanced usage, the library exports smaller functions that get_stroke
uses internally:
// Get detailed stroke points with pressure, vector, distance, etc.
let stroke_points = get_stroke_points(&input_points, &options);
// Generate outline points from the detailed stroke points
let outline_points = get_stroke_outline_points(&stroke_points, &options);
Examples
Check out the examples directory for more usage examples:
- SVG path generation
- Different stroke styles and parameters
- Edge cases (one point, two points)
- HTML viewer for comparing different options
License
Original JavaScript library by Steve Ruiz