Nuxt module that turns any image (including SVG) into a halftone: a grid of single-color dots with even spacing. Brightness is encoded by dot size, opacity, or both.
Minimal dependencies, maximum performance.
- Halftone effects - scale (dot size), opacity, or both
- Flexible coloring - solid or gradient (2 or 3 colors); HEX, HSL, RGB(a), OKLCH
- Gradient control - direction in degrees, 2- or 3-color mode
- Dot shapes - circle, square, triangle
- Output - canvas or PNG image
- CORS - optional server proxy for external images
- Slots -
#loading,#error - Performance -
maxWidth/maxHeight, Web Worker for large images (>512×512px), optional smoothing, trim, hideMinDots
npx nuxi module add halographOr manually:
npm install halograph// nuxt.config.ts
export default defineNuxtConfig({
modules: ['halograph'],
})<template>
<HalographImage
src="https://example.com/image.jpg"
:options="halftoneOptions"
output="canvas"
/>
</template>
<script setup lang="ts">
import type { HalftoneOptions } from 'halograph'
const halftoneOptions: HalftoneOptions = {
dotType: 'circle',
effectType: 'scale',
color: '#1a1a1a',
spacing: 8,
maxWidth: 600,
}
</script>Props
| Prop | Type | Default | Description |
|---|---|---|---|
src |
string |
- | Image URL |
options |
HalftoneOptions |
- | Effect options |
output |
'canvas' | 'image' |
'canvas' |
Output format |
Slots - #loading, #error (receives error).
<script setup lang="ts">
import { useHalograph } from 'halograph'
const src = '/image.jpg'
const options = {
dotType: 'circle',
effectType: 'scale',
color: '#000000',
}
const { result, error, isLoading, toDataURL } = useHalograph(src, options)
const pngUrl = toDataURL('image/png')
</script>Returns: result, error, isLoading, toDataURL(type?).
| Option | Type | Default | Description |
|---|---|---|---|
dotType |
'circle' | 'square' | 'triangle' |
'circle' |
Dot shape |
effectType |
'scale' | 'opacity' | 'both' |
'scale' |
Brightness encoding |
color |
string |
'#000000' |
Dot color (HEX/RGB/HSL/OKLCH) |
colorMode |
'solid' | 'gradient2' | 'gradient3' |
'solid' |
Coloring mode |
gradientColors |
[string, string] or 3-tuple |
- | Gradient stops |
gradientAngle |
number |
90 |
Gradient direction (degrees) |
spacing |
number |
auto | Distance between dots (px) |
maxWidth |
number |
- | Max width for performance |
maxHeight |
number |
- | Max height for performance |
smoothing |
boolean |
false |
Supersampling for antialiasing |
trim |
boolean |
false |
Crop canvas to content bounds (brightness > threshold) |
hideMinDots |
boolean |
false |
Do not draw dots at minimum size/opacity (by effect type) |
Dark areas = larger dots. Dot size reflects brightness.
{ effectType: 'scale', color: '#000' }Dark areas = more transparent dots. Fixed size, opacity reflects brightness.
{ effectType: 'opacity', color: '#ff0000' }Size and opacity both vary with brightness.
{ effectType: 'both', color: '#0000ff' }{ color: '#1a1a1a', colorMode: 'solid' }{
colorMode: 'gradient2',
gradientColors: ['#ff0000', '#0000ff'],
gradientAngle: 45,
}{
colorMode: 'gradient3',
gradientColors: ['#ff0000', '#00ff00', '#0000ff'],
gradientAngle: 90,
}For images from other domains, enable the proxy:
// nuxt.config.ts
export default defineNuxtConfig({
halograph: { useProxy: true },
})The component will use /api/_halograph/proxy for external URLs.
const options: HalftoneOptions = {
dotType: 'circle',
effectType: 'scale',
color: '#000',
maxWidth: 800,
maxHeight: 600,
smoothing: false,
}Improves quality at the cost of speed:
{ smoothing: true }Crops canvas to the bounding box of cells with brightness above threshold:
{ trim: true }Skips drawing dots at minimum size (scale) or minimum opacity (opacity/both):
{ hideMinDots: true }import type {
HalftoneOptions,
HalftoneResult,
DotType,
EffectType,
ColorMode,
} from 'halograph'MIT © 2025
