Skip to main content
The ImageViewer component loads and displays images from various sources with automatic loading indicators.

Basic Usage

use freya::prelude::*;

fn app() -> impl IntoElement {
    let image: ImageSource = "https://example.com/image.jpg".into();
    
    ImageViewer::new(image)
}

Image Sources

Remote URL

Load images from the web (requires remote-asset feature):
let source: ImageSource = "https://example.com/image.jpg".into();
ImageViewer::new(source)

File Path

Load images from the filesystem:
use std::path::PathBuf;

let source: ImageSource = PathBuf::from("./images/photo.png").into();
ImageViewer::new(source)

Embedded Bytes

Embed images directly in the binary:
let source: ImageSource = (
    "my-image",  // Unique identifier
    include_bytes!("./assets/logo.png")
).into();

ImageViewer::new(source)

Properties

source
ImageSource
required
Image source (URL, path, or bytes)
Plus all standard layout and styling properties:
  • width(), height()
  • corner_radius()
  • a11y_alt() - Alternative text for accessibility
  • And more via LayoutExt, ImageExt, AccessibilityExt

ImageSource

The ImageSource enum supports three types:
pub enum ImageSource {
    Uri(Uri),                          // Remote (requires remote-asset feature)
    Path(PathBuf),                     // Local file
    Bytes(&'static str, Bytes),        // Embedded
}

Complete Example

use freya::prelude::*;
use std::path::PathBuf;

fn app() -> impl IntoElement {
    let remote = "https://images.example.com/photo.jpg";
    let local = PathBuf::from("./assets/logo.png");
    let embedded = ("icon", include_bytes!("./assets/icon.png"));
    
    rect()
        .horizontal()
        .spacing(16.)
        .child(
            ImageViewer::new(remote)
                .width(Size::px(200.))
                .height(Size::px(200.))
                .a11y_alt("A beautiful photo")
        )
        .child(
            ImageViewer::new(local)
                .width(Size::px(200.))
                .height(Size::px(200.))
        )
        .child(
            ImageViewer::new(embedded)
                .width(Size::px(64.))
                .height(Size::px(64.))
        )
}

Loading States

ImageViewer automatically handles loading states:
  1. Pending: Initial state
  2. Loading: Fetching/decoding the image (shows loader)
  3. Cached: Image loaded successfully (displays image)
  4. Error: Failed to load (displays error message)
// Shows CircularLoader while loading
ImageViewer::new("https://example.com/large-image.jpg")

Sizing

Control image dimensions:
// Fixed size
ImageViewer::new(source)
    .width(Size::px(300.))
    .height(Size::px(200.))

// Percentage
ImageViewer::new(source)
    .width(Size::percent(50.))
    .height(Size::percent(50.))

// Fill container
ImageViewer::new(source)
    .width(Size::fill())
    .height(Size::fill())

Corner Radius

Round the corners:
ImageViewer::new(source)
    .width(Size::px(100.))
    .height(Size::px(100.))
    .corner_radius(50.)  // Circle

Accessibility

Provide alternative text for screen readers:
ImageViewer::new(source)
    .a11y_alt("Company logo")
    .a11y_role(AccessibilityRole::Image)
Create a responsive image gallery:
let images = vec![
    "https://example.com/1.jpg",
    "https://example.com/2.jpg",
    "https://example.com/3.jpg",
];

ScrollView::new().child(
    rect()
        .direction(Direction::Horizontal)
        .spacing(12.)
        .children(
            images.into_iter().map(|url| {
                ImageViewer::new(url)
                    .width(Size::px(200.))
                    .height(Size::px(200.))
                    .corner_radius(8.)
                    .into()
            })
        )
)

Lazy Loading

Images are loaded asynchronously and cached:
// Multiple instances with same source share the cached image
rect()
    .horizontal()
    .child(ImageViewer::new("https://example.com/image.jpg"))
    .child(ImageViewer::new("https://example.com/image.jpg"))  // Uses cache

Performance

  • Images are fetched asynchronously
  • Automatic caching prevents duplicate downloads
  • Efficient image decoding with Skia
  • Loading indicators prevent layout shifts

Error Handling

If an image fails to load, the error message is displayed:
ImageViewer::new("https://invalid-url.com/missing.jpg")
// Will show: "Failed to load image: ..."

Supported Formats

Supports common image formats:
  • PNG
  • JPEG
  • GIF
  • WebP
  • BMP
  • ICO

Source

View the full implementation: image_viewer.rs

Build docs developers (and LLMs) love