Skip to content

othorizon/clickable-img

Repository files navigation

clickable-img

npm sdk npm core TypeScript license PRs welcome Online Editor

Embed interactive clickable hotspots into PNG images.
Draw once with the Editor, render everywhere with the SDK.

English | 简体中文


How It Works

  1. Draw hotspots on an image using the visual Editor
  2. Export as a standard PNG with hotspot metadata embedded in tEXt chunks
  3. Render in your app — the SDK reads the metadata and creates clickable zones automatically

No server required. All data lives inside the PNG file itself.

Edit Image Hotspots

Use the online editor to create and manage hotspots on your images:

https://clickable-img.dev.noteloom.app

The editor lets you visually draw hotspot regions on any PNG image, add labels and custom data to each hotspot, then export the image with all hotspot metadata embedded. The exported PNG can be used directly with the SDK — no additional configuration files needed.

Quick Start

Web Browser

npm install @clickable-img/sdk
import { ClickableImg } from '@clickable-img/sdk'

const img = document.querySelector('img#hero')

const instance = await ClickableImg.attach(img, {
  onClick(hotspot) {
    console.log(hotspot.label)   // "Buy Now"
    console.log(hotspot.payload) // "product-123"
  },
  showHints: true, // optional — show hotspot borders
})

// Read custom data embedded in the image
const customData = instance.getCustomData() // string | null

// clean up when done
instance.destroy()

Cross-Platform Integration

clickable-img works on any JavaScript-based platform. The @clickable-img/sdk is a ready-to-use wrapper for the browser, but it's not required — all you need is @clickable-img/core.

  1. Read hotspot data — Call readHotspotsFromPng from the core package to parse the PNG and extract hotspot coordinates and custom data.
  2. Build your own overlay — Use the hotspot coordinates to create clickable regions on top of the image using your platform's native approach — Canvas, native Views, WebGL, etc.
  3. Handle click events — When a user taps a hotspot, read its label and payload to execute your business logic.

The core package has zero external dependencies and is pure JavaScript — it runs in Node.js, React Native, Mini Programs, Electron, and any other JS runtime.

Core Only (Custom Rendering)

For platforms without a built-in adapter (React Native, Flutter, Node.js, etc.):

npm install @clickable-img/core
import { readHotspotsFromPng, readCustomDataFromPng } from '@clickable-img/core'

const buffer = await fetch('https://example.com/image.png')
  .then(r => r.arrayBuffer())

const data = readHotspotsFromPng(buffer)

if (data) {
  data.hotspots.forEach(hotspot => {
    // hotspot.rect -> { x, y, w, h } in 0~1 range (relative to image size)
    // hotspot.label, hotspot.payload, hotspot.id
  })

  // Read custom data embedded in the image
  console.log(data.customData) // string | undefined
}

// Or read custom data directly without parsing hotspots
const customData = readCustomDataFromPng(buffer) // string | null

Use Cases

When you need interactive regions on images, clickable-img provides the lightest solution:

  • Ad Pop-ups — Buttons and product zones in pop-up ads are configured as hotspots. Swap the image to update content — zero code changes.
  • Campaign Landing Pages — Use the designer's artwork directly as the page. Hotspots handle navigation, eliminating complex CSS reproduction.
  • Interactive Maps — Scenic area guides, mall floor plans, etc. Mark points of interest on images, click to reveal details.
  • Interactive Learning — Mark knowledge points on educational images. Students click to view explanations.

Real-World Example: Hot-Updatable Ad Pop-ups

  1. Develop once — Build the image pop-up component, integrate the SDK, and configure hotspot click event handlers.
  2. Configure hotspots — Operations team uses the online editor to draw interactive hotspots on the new ad image.
  3. Deploy content — Upload the exported image to CDN / object storage, replacing the old image URL.

Result: No code changes, no redeployment — ad content is hot-updated instantly.

Key Advantages

  • Hot Update — Replace the image to ship new content, no release needed
  • Fast Delivery — No need to reproduce complex UI designs in code; a single image carries the entire visual
  • Low Dev Cost — Display-oriented pages only need click event listeners, drastically reducing frontend work

How It Works (Technical)

All hotspot data is stored inside the PNG file itself — no extra server required.

PNG tEXt Chunk Storage

The PNG specification defines tEXt auxiliary chunks for storing text metadata. The editor serializes hotspot data as JSON, writes it into a tEXt chunk with the keyword clickable-img, and inserts it before the IEND marker. Pixel data remains completely untouched.

Normalized Coordinate System

Hotspot coordinates use relative values in the 0~1 range (percentage of image width/height). This means hotspots always align precisely, regardless of the actual rendered image size on screen.

DOM Overlay Rendering

At runtime, the SDK fetches the image binary data, parses the tEXt chunk to extract the hotspot JSON, wraps the <img> element in a position: relative container, and generates an position: absolute transparent <div> for each hotspot with click event listeners.

Data Flow

Editor draws hotspots → serialize to JSON
        ↓
JSON written into PNG tEXt chunk → image exported
        ↓
SDK loads image → parses tEXt chunk
        ↓
DOM overlay generated from coordinates → interaction events bound

Packages

Package Description Platform
@clickable-img/core Type definitions & PNG metadata parser Any JS runtime
@clickable-img/sdk Browser runtime with DOM overlay Web
@clickable-img/editor Visual hotspot editor Web

API Reference

@clickable-img/sdk

ClickableImg.attach(img, options)

Parameter Type Description
img HTMLImageElement Target image element
options.onClick (hotspot: Hotspot) => void Callback when a hotspot is clicked
options.showHints boolean Show hotspot borders. Default: false

Returns Promise<ClickableImg>. The instance provides:

  • .getCustomData(): string | null — Returns custom data embedded in the image, or null if none.
  • .destroy() — Removes the overlay and cleans up.

@clickable-img/core

readHotspotsFromPng(buffer: ArrayBuffer): ClickableImgData | null

Parses PNG tEXt chunks and returns all embedded data (hotspots + custom data), or null if none found.

readCustomDataFromPng(buffer: ArrayBuffer): string | null

Convenience method to read only the custom data field from a PNG, without needing to process hotspots.

Data Types

interface ClickableImgData {
  version: string
  hotspots: Hotspot[]
  customData?: string   // arbitrary text embedded with the image
}

interface Hotspot {
  id: string
  rect: HotspotRect
  label: string
  payload: string
}

interface HotspotRect {
  x: number  // 0~1, left offset relative to image width
  y: number  // 0~1, top offset relative to image height
  w: number  // 0~1, width relative to image width
  h: number  // 0~1, height relative to image height
}

Development

pnpm install   # install dependencies
pnpm dev       # start all packages in watch mode
pnpm build     # build all packages

Contributing

Contributions are welcome! Please open an issue first to discuss what you'd like to change.

License

MIT

About

让图片变成可以点击的元素

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors