Search...Search plugins and themes...
⌘K
Sign in
  • Get started
  • Download
  • Pricing
  • Enterprise
  • Account
  • Obsidian
  • Overview
  • Sync
  • Publish
  • Canvas
  • Mobile
  • Web Clipper
  • CLI
  • Learn
  • Help
  • Developers
  • Changelog
  • About
  • Roadmap
  • Blog
  • Resources
  • System status
  • License overview
  • Terms of service
  • Privacy policy
  • Security
  • Community
  • Plugins
  • Themes
  • Discord
  • Forum / 中文论坛
  • Merch store
  • Brand guidelines
Follow us
DiscordTwitterBlueskyThreadsMastodonYouTubeGitHub
© 2026 Obsidian

Canvas Image LOD

Ilia GorbunovIlia Gorbunov178 downloads

Swaps large canvas images for downscaled proxies based on zoom level, removing zoom lag on image-heavy boards. Originals are never modified.

Add to Obsidian
  • Overview
  • Scorecard
  • Updates4

Removes zoom lag in Obsidian Canvas on boards with many large images. Your image files are never modified.

The problem

Obsidian Canvas is plain DOM. Every time the zoom level changes, Chromium re-rasterizes each image from its source resolution. A 4800×3000 photo drawn 150 px wide on screen is still recomputed from 14 megapixels — on every zoom step, for every image in view.

Measured on one real board:

Images 104
On disk 372 MB
Total 307 megapixels
Decoded as RGBA ~1.2 GB

That gigabyte is re-rasterized as you zoom. It is the whole reason the board stutters.

What the plugin does

It builds downscaled proxies of each image and feeds every <img> the one that matches its real on-screen size. Zoom out and a 128 px copy is drawn; zoom in and the original comes back.

Simulated against the same board (tiers 128/320/768/1600, headroom 1.15):

Zoom Megapixels before After Gain
10% 307 14.8 20.8×
25% 307 18.7 16.4×
50% 307 22.5 13.6×
100% 307 51.2 6.0×
150% 307 122.0 2.5×

Numbers come from one vault. Yours will differ with image sizes and board layout.

Design notes

Zoom is read from the transform matrix (getComputedStyle().transform) rather than from canvas internals, so Obsidian updates do not break it.

Each image is fully decoded exactly once. Tiers are then built as a chain — 1600 from the original, 768 from 1600, 320 from 768 — which is both faster and sharper than jumping straight from 4800 to 128.

Upgrades are deferred until the gesture ends. Downgrades apply immediately because the proxies are already in memory; originals are only reloaded 200 ms after you stop moving, so heavy files never load mid-zoom.

DOM reads and writes are split into phases. All sizes are measured first, then all swaps applied — otherwise the browser would recompute layout once per image.

Node widths are cached in a WeakMap and refreshed through a ResizeObserver, so offsetWidth is never touched during a frame.

Prewarm walks the board's JSON, not the DOM. Obsidian unmounts distant nodes, so they are not in the DOM to be found; this way proxies are ready for images you have not scrolled to yet.

Files are read through vault.readBinary, falling back to fetch for external URLs.

Storage

Proxies live in IndexedDB inside your Obsidian profile — not in your vault.

This matters: on a large vault the proxy set runs to roughly 100 MB. Kept under .obsidian, all of it would be pushed through Obsidian Sync, count against your storage quota, and — because cache keys include each file's mtime — quite possibly arrive useless on the other machine anyway. It is derived data, and it is cheaper to rebuild than to carry.

Memory is bounded separately. Every object URL keeps its blob alive, so entries are evicted least-recently-used once the RAM budget is exceeded; anything currently on screen is pinned and never revoked. Evicted proxies are reloaded from IndexedDB without re-decoding.

Both budgets are configurable, and cache keys invalidate themselves when you edit an image.

Install

Copy main.js, manifest.json and styles.css into <vault>/.obsidian/plugins/canvas-image-lod/, then enable the plugin under Settings → Community plugins.

Commands

  • Toggle proxy swapping
  • Build proxies for the current canvas
  • Restore original images on the current canvas
  • Clear proxy cache

Limitations

  • Desktop only. WebKit cannot encode WebP from a canvas and silently returns PNG, OffscreenCanvas needs Safari 16.4+, and decoding large images on a phone risks the OS killing the WebView. Mobile support needs its own work.
  • SVG and video nodes are left alone.
  • Text and markdown cards are untouched. This plugin fixes raster cost, not DOM cost — a board of 500 text cards will be exactly as slow as before.
  • Exporting a canvas to an image restores originals first and waits for them to load, but it hooks the export command by name pattern. If that command is renamed upstream, use Restore original images on the current canvas manually before exporting.

Development

No build step — main.js is plain CommonJS, edit and reload.

cd test && npm install && npm test

Three suites:

  • loadtest.js — the module loads, onload/onunload survive
  • bindtest.js — deliberately broken canvas leaves never break plugin loading
  • cachetest.js — IndexedDB round trip and pruning, memory eviction and pinning, the export wrapper, legacy cache removal, settings rendering

simulate.js measures the level-of-detail win against a real board; edit the vault path at the top before running it.

License

MIT

HealthExcellent
ReviewPassed
About
Reduce zoom lag in Obsidian Canvas boards by serving size-appropriate downscaled image proxies instead of full-resolution files. Keep original images unchanged and automatically swap back to full resolution when zooming in to prevent stutter and excessive rasterization.
CanvasImages
Details
Current version
1.0.3
Last updated
2 months ago
Created
2 months ago
Updates
4 releases
Downloads
178
Compatible with
Obsidian 1.4.0+
Platforms
Desktop only
License
MIT
Report bugRequest featureReport plugin
Author
Ilia GorbunovIlia Gorbunovseadhe
GitHubseadhe
  1. Community
  2. Plugins
  3. Canvas
  4. Canvas Image LOD

Related plugins

Advanced Canvas

Supercharge your canvas experience. Create presentations, flowcharts and more.

Image Captions

Add captions to images with inline Markdown and link support. The caption format is compatible with the Commonmark spec and other Markdown applications.

Ink

Handwriting and drawing directly between paragraphs using a digital pen, stylus, or Apple pencil.

ZettelFlow

Turn your Obsidian vault into a visual thinking space for connecting ideas, exploring knowledge, and building your own thinking system.

TTRPG Tools - Maps

A toolbox for interactive fantasy maps.

Featured Image

Automatically set a featured image property in your notes based on the first image.

Imagine

A comprehensive image management plugin for managing, inserting, resizing, viewing, and batch processing images.

Pretty Properties

Makes note properties look more fun: adds side image, banners, list property colors and allows to hide specific properties.

Local Images Plus

A reincarnation of Local Images to download images in Markdown notes to local storage.

PlantUML

Generate PlantUML diagrams.