Declarative 2D Canvas & Data Visualization
Rendering massive datasets (thousands of points, heatmaps, or fluid charts) overwhelms DOM node trees. Hozo's 2D Canvas delivers a declarative JSX API that compiles to optimized batched Canvas operations on Web and native Skia draw calls on mobile.
Choosing Between SVG and Canvas
Hozo provides first-class support for both vector systems. Rather than forcing one paradigm across all use cases, library authors choose based on data density and interaction model:
- UI icons, vector logos, and design elements
- Small to medium charts (< 500 data points)
- When individual nodes need CSS hover transitions and DOM events
- Zero runtime overhead on Web (emits native
<svg>)
- High-frequency real-time time-series and candlestick charts
- Large datasets (> 5,000 data points) and heatmaps
- Custom particle animations, drawing pads, and filters
- Single GPU surface with zero DOM node creation overhead
Solving the Platform Asymmetry
Imperative vs Declarative
Web Canvas is strictly imperative (ctx.fillRect), while React Native Skia is declarative. Hozo compiles declarative JSX into draw instructions, reconciling the asymmetry without runtime bloat.
Spatial Hit-Testing
Hozo deliberately does not create a fake DOM over Canvas. Hit-testing is implemented via spatial math, allowing precise gestures and tooltips on both mouse pointers and touch screens.
Accessible Sibling Tables
Canvas graphics are often invisible to screen readers. Hozo automatically pairs canvas visualizations with accessible semantic sibling tables so screen reader users can navigate the underlying data.
Declarative 2D Authoring
Write declarative components that compile to optimized draw loops on Web and Skia commands on Native.
import { Canvas, Rect, Path } from '@hozo/canvas'
export function DataBarChart({ points }) {
return (
<Canvas width={600} height={300} accessibilityLabel="Quarterly Revenue Trends">
{points.map((p, i) => (
<Rect
key={i}
x={i * 60 + 10}
y={300 - p.value}
width={40}
height={p.value}
fill="#c8a882"
/>
))}
</Canvas>
)
}