Crate plotly_static

Source
Expand description

§Plotly Static Image Export

A Rust library for exporting Plotly plots to static images using headless browsers via WebDriver.

This library provides a interface for converting Plotly plots provided as JSON values into various static image formats (PNG, JPEG, WEBP, SVG, PDF) using WebDriver and headless browsers.

§Features

  • Async/Sync API Support: Support for both async and sync contexts
  • Multiple Formats: Support for PNG, JPEG, WEBP, SVG, and PDF export
  • Headless Rendering: Uses headless browsers for rendering
  • WebDriver Support: Supports both Chrome (chromedriver) and Firefox (geckodriver)
  • Configurable: Customizable dimensions, scale, and browser capabilities
  • Offline Mode: Can work with offline bundled JavaScript libraries
  • Automatic Management: Handles WebDriver process lifecycle and cleanup
  • Parallelism: Designed for use in parallel environments (tests, etc.)
  • Logging Support: Integrated logging with env_logger support

§Quick Start

// This example requires a WebDriver-compatible browser (Chrome/Firefox).
// It cannot be run as a doc test.
use plotly_static::{StaticExporterBuilder, ImageFormat};
use serde_json::json;
use std::path::Path;

// Create a simple plot
let plot = json!({
    "data": [{
        "type": "scatter",
        "x": [1, 2, 3, 4],
        "y": [10, 11, 12, 13]
    }],
    "layout": {
        "title": "Simple Scatter Plot"
    }
});

// Build and use StaticExporter
let mut exporter = StaticExporterBuilder::default()
    .build()
    .expect("Failed to build StaticExporter");

// Export to PNG
exporter.write_fig(
    Path::new("my_plot"),
    &plot,
    ImageFormat::PNG,
    800,
    600,
    1.0
).expect("Failed to export plot");

§Features and Dependencies

§Required Features

You must enable one of the following features:

  • chromedriver: Use Chrome/Chromium for rendering
  • geckodriver: Use Firefox for rendering

§Optional Features

  • webdriver_download: Automatically download WebDriver binaries at build time

§Example Cargo.toml

[dependencies]
plotly_static = { version = "0.1", features = ["chromedriver", "webdriver_download"] }

§Async Support

The library supports async operations. To use the async API you need to call build_async instead of build on the StaticExporterBuilder . This will return an AsyncStaticExporter instance where the write_fig and write_to_string methods are async.

use plotly_static::StaticExporterBuilder;

let exporter = StaticExporterBuilder::default()
    .build_async()
    .expect("Failed to build AsyncStaticExporter");

Never use the sync API in async contexts. The sync API wraps the async API and uses a tokio::runtime::Runtime instance internally. Using the sync API in an async context will cause runtime errors such as e.g., “Cannot drop a runtime in a context where blocking is not allowed. This happens when a runtime is dropped from within an asynchronous context.” or similar ones.

§Advanced Usage

§Custom Configuration

// This example requires a running WebDriver (chromedriver/geckodriver) and a browser.
// It cannot be run as a doc test.
use plotly_static::StaticExporterBuilder;

let exporter = StaticExporterBuilder::default()
    .webdriver_port(4444)
    .webdriver_url("http://localhost")
    .spawn_webdriver(true)
    .offline_mode(true)
    .webdriver_browser_caps(vec![
        "--headless".to_string(),
        "--no-sandbox".to_string(),
        "--disable-gpu".to_string(),
    ])
    .build()
    .expect("Failed to build StaticExporter");

§Browser Binary Configuration

You can specify custom browser binaries using environment variables:

# For Chrome/Chromium
export BROWSER_PATH="/path/to/chrome"

# For Firefox
export BROWSER_PATH="/path/to/firefox"

The library will automatically use these binaries when creating WebDriver sessions.

§String Export

// This example requires a running WebDriver (chromedriver/geckodriver) and a browser.
// It cannot be run as a doc test.
use plotly_static::{StaticExporterBuilder, ImageFormat};
use serde_json::json;

let plot = json!({
    "data": [{"type": "scatter", "x": [1,2,3], "y": [4,5,6]}],
    "layout": {}
});

let mut exporter = StaticExporterBuilder::default()
    .build()
    .expect("Failed to build StaticExporter");

let svg_data = exporter.write_to_string(
    &plot,
    ImageFormat::SVG,
    800,
    600,
    1.0
).expect("Failed to export plot");

// svg_data contains SVG markup that can be embedded in HTML

§Logging Support

The library supports logging via the log crate. Enable it with env_logger:

use plotly_static::StaticExporterBuilder;

// Initialize logging (typically done once at the start of your application)
env_logger::init();

// Set log level via environment variable
// RUST_LOG=debug cargo run

let mut exporter = StaticExporterBuilder::default()
    .build()
    .expect("Failed to build StaticExporter");

§Parallel Usage

The library is designed to work safely in parallel environments:

use plotly_static::{StaticExporterBuilder, ImageFormat};
use std::sync::atomic::{AtomicU32, Ordering};

// Generate unique ports for parallel usage
static PORT_COUNTER: AtomicU32 = AtomicU32::new(4444);

fn get_unique_port() -> u32 {
    PORT_COUNTER.fetch_add(1, Ordering::SeqCst)
}

// Each thread/process should use a unique port
let mut exporter = StaticExporterBuilder::default()
    .webdriver_port(get_unique_port())
    .build()
    .expect("Failed to build StaticExporter");

§WebDriver Management

The library automatically manages WebDriver processes:

  • Automatic Detection: Detects if WebDriver is already running on the specified port
  • Process Spawning: Automatically spawns WebDriver if not already running
  • Connection Reuse: Reuses existing WebDriver sessions when possible
  • External Sessions: Can connect to externally managed WebDriver sessions

Due to the underlying WebDriver implementation, the library cannot automatically close WebDriver processes when StaticExporter is dropped. You must call close manually to ensure proper cleanup.

§WebDriver Configuration

Set the WEBDRIVER_PATH environment variable to specify a custom WebDriver binary location (should point to the full executable path):

export WEBDRIVER_PATH=/path/to/chromedriver
cargo run

Or use the webdriver_download feature for automatic download at build time.

§Error Handling

The library uses anyhow::Result for error handling. Common errors include:

  • WebDriver not available or not running
  • Invalid Plotly JSON format
  • File system errors
  • Browser rendering errors

§Browser Support

  • Chrome/Chromium: Full support via chromedriver
  • Firefox: Full support via geckodriver
  • Safari: Not currently supported
  • Edge: Not currently supported

§Performance Considerations

  • Reuse Exporters: Reuse StaticExporter instances for multiple exports
  • Parallel Usage: Use unique ports for parallel operations
  • WebDriver Reuse: The library automatically reuses WebDriver sessions when possible

§Comparison with Kaleido

  • No custom Chromium/Chrome external dependency: Uses standard WebDriver instead of proprietary Kaleido
  • Better Browser Support: Works with any WebDriver-compatible browser: Chrome/Chromium,Firefox,Brave
  • Extensible: Easy to control browser capabilities and customize the StaticExporter instance

§Limitations

  • Requires a WebDriver-compatible browser
  • PDF export uses browser JavaScript html2pdf (not native Plotly PDF)
  • EPS is no longer supported and will be removed
  • Slightly slower than Kaleido

§License

MIT License - see LICENSE file for details.

Structs§

AsyncStaticExporter
Async StaticExporter for async contexts. Keeps the same API as the sync StaticExporter for compatibility.
StaticExporter
Synchronous exporter for exporting Plotly plots to static images.
StaticExporterBuilder
Builder for configuring and creating a StaticExporter instance.

Enums§

ImageFormat
Supported image formats for static image export.