alpha-mask-events
v1.0.1
Published
Enable click‑through on transparent regions of images (PNG, WebP, AVIF, GIF, SVG) using alpha masks.
Downloads
26
Maintainers
Readme
Alpha Mask Events
Enable click-through on transparent parts of images (PNG, WebP, AVIF, etc.) and background-images, making irregularly shaped UI elements behave naturally.

Why use Alpha Mask Events?
Ever been frustrated when:
- You had to use CSS clip-paths or complex SVG masks to make irregularly shaped elements clickable only on their visible parts?
- You wanted to stack elements and have clicks "fall through" the transparent regions?
- You want greater control over pointer events and transparent images?
This lightweight library solves these problems with minimal setup and supports all modern image formats with transparency.
Supported Image Formats
✅ Full Transparency Support
- PNG - Universal browser support, full alpha channel
- WebP - Modern browsers (Chrome 23+, Firefox 65+, Safari 14+), full alpha channel
- AVIF - Latest browsers (Chrome 85+, Firefox 93+, Safari 16.4+), full alpha channel
- SVG - Modern browsers, transparency via CSS/opacity
⚠️ Limited Transparency Support
- GIF - Universal support, binary transparency only
- TIFF - Limited browser support, some transparency capability
- ICO - Limited browser support, basic transparency
❌ No Transparency (processed with warnings)
- JPEG/JPG - Universal support, no transparency
- BMP - Limited support, no transparency
Table of Contents
- Installation
- Quick Start
- Use Cases
- API Reference
- CLI Usage
- Advanced Examples
- Browser Compatibility
- Performance Tips
- Development
- Testing
- Contributing
- License
Installation
npm install alpha-mask-events
# or
yarn add alpha-mask-eventsQuick Start
Method 1: Auto-detect images (recommended)
Add .alpha-mask-events class to any image or element with background-image:
<img src="logo.png" class="alpha-mask-events" />
<img src="hero.webp" class="alpha-mask-events" />
<img src="avatar.avif" class="alpha-mask-events" />
<div class="alpha-mask-events" style="background-image: url('shape.png')"></div>
<div class="alpha-mask-events" style="background-image: url('icon.webp')"></div>Initialize the library:
import AME from 'alpha-mask-events';
// Initialize and auto-detect all elements with .alpha-mask-events class
AME.init();Method 2: Manual Registration
import AME from 'alpha-mask-events';
// Initialize without auto-detection
const manager = AME.init({ autoScan: false });
// Register specific elements
AME.register('#logo');
AME.register(document.querySelector('.irregular-button'));CDN via JsDelivr
Grab the <script> code here: https://www.jsdelivr.com/package/npm/alpha-mask-events
JS:
AlphaMaskEvents.init(); // Scan and activate all .alpha-mask-events
AlphaMaskEvents.register(document.querySelector('#myImg'), { threshold: 0.95 });HTML:
<img src="sprite.png" class="alpha-mask-events">Use Cases
Interactive Maps with Irregularly Shaped Regions
<div class="map-container">
<img src="map-background.jpg" style="width: 100%; height: auto;" />
<img src="region1.png" class="alpha-mask-events region" data-region="north" />
<img src="region2.png" class="alpha-mask-events region" data-region="south" />
</div>
<script>
import AME from 'alpha-mask-events';
// Initialize click-through behavior
AME.init();
// Add click handlers to regions
document.querySelectorAll('.region').forEach(region => {
region.addEventListener('click', () => {
alert(`You clicked the ${region.dataset.region} region!`);
});
});
</script>Dynamic UI with Overlapping Elements
// Create a layered UI where clicks pass through transparent areas
const layers = document.querySelectorAll('.ui-layer');
layers.forEach(layer => AME.register(layer));
// Dynamically adjust threshold based on user interaction
document.getElementById('sensitivity-slider').addEventListener('change', (e) => {
AME.setThreshold(e.target.value / 100);
});Shape-Conforming Buttons
Make clickable areas match the actual visible shape of buttons:
<button class="shaped-button alpha-mask-events">
<img src="button-shape.png" alt="Custom Button" />
<span class="button-text">Click Me</span>
</button>
<style>
.shaped-button {
position: relative;
background: transparent;
border: none;
padding: 0;
}
.button-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
pointer-events: none; /* Let clicks go through to the image */
}
</style>API Reference
init(options)
Initialize click-through manager on the page.
- options (object)
- threshold (number, optional): Transparency cutoff (0–1). Pixels with alpha ≤ threshold are click-through. Default:
0.999 - autoScan (boolean, optional): Auto-detect elements with
.alpha-mask-eventsclass. Default:true - log (boolean, optional): Enable console logs for debugging. Default:
false
- threshold (number, optional): Transparency cutoff (0–1). Pixels with alpha ≤ threshold are click-through. Default:
Returns the manager instance.
register(target, opts)
Register an element or selector for click-through.
- target (HTMLElement|string): Element or CSS selector
- opts (object, optional)
- threshold (number, optional): Per-element transparency cutoff. Default: global threshold
unregister(target)
Stop hit-testing and restore normal pointer behavior on the element.
- target (HTMLElement|string): Element or CSS selector
setThreshold(value)
Adjust global transparency threshold.
- value (number): New threshold (0–1), where lower values make more pixels click-through
Custom Events
Alpha Mask Events dispatches custom events when the mouse cursor transitions between opaque and transparent regions of registered elements.
alpha-mask-over
Fired when the cursor moves from a transparent region to an opaque region (or enters an opaque region from outside the element).
alpha-mask-out
Fired when the cursor moves from an opaque region to a transparent region (or leaves an opaque region by exiting the element).
Event Object Properties
Both events include a detail object with the following properties:
- element (HTMLElement): The element that triggered the event
- alpha (number): The alpha value (0-1) at the cursor position
- coordinates (object): Canvas coordinates
{ x: number, y: number }where the event occurred - threshold (number): The threshold value used for this element
Usage Example
import AME from 'alpha-mask-events';
// Initialize and register an element
AME.init();
const element = document.querySelector('.my-image');
// Listen for opacity transition events
element.addEventListener('alpha-mask-over', (event) => {
console.log('Mouse entered opaque region');
console.log('Alpha value:', event.detail.alpha);
console.log('Coordinates:', event.detail.coordinates);
console.log('Threshold:', event.detail.threshold);
// Add visual feedback
element.classList.add('hover-opaque');
});
element.addEventListener('alpha-mask-out', (event) => {
console.log('Mouse left opaque region');
// Remove visual feedback
element.classList.remove('hover-opaque');
});TypeScript Support
import AME, { AlphaMaskEvent } from 'alpha-mask-events';
const element = document.querySelector('.my-image') as HTMLElement;
element.addEventListener('alpha-mask-over', (event: AlphaMaskEvent) => {
// TypeScript knows about event.detail properties
const { alpha, coordinates, threshold, element } = event.detail;
console.log(`Alpha: ${alpha}, Coords: ${coordinates.x},${coordinates.y}`);
});CLI Usage
Generate compact masks for opaque regions in transparent images (useful for server-side optimizations).
npx ame-generate-masks <images...> --out <file> [options]Supported formats: PNG, WebP, AVIF, GIF, BMP, TIFF
Examples:
# Process multiple PNG files
npx ame-generate-masks sprites/*.png --out masks.json
# Process mixed formats with custom threshold
npx ame-generate-masks logo.png hero.webp avatar.avif --out masks.json --threshold 0.2
# Process with blur for smoother edges
npx ame-generate-masks button.png --out button-mask.json --blur 2Options:
- <images...>: One or more image paths or glob patterns
- --out (string, required): Path to output JSON file
- --threshold (number, default:
0.1): Alpha threshold (0–1). Pixels with alpha > threshold are included in the opaque mask - --blur (number, default:
1): Box blur radius in pixels applied to alpha channel before thresholding
Output format:
{
"logo.png": {
"width": 256,
"height": 256,
"rects": [
{ "x": 10, "y": 10, "w": 50, "h": 1 },
{ "x": 8, "y": 11, "w": 54, "h": 1 }
]
},
"hero.webp": {
"width": 800,
"height": 600,
"rects": [...]
}
}Advanced Examples
React Integration
import React, { useEffect, useRef } from 'react';
import AME from 'alpha-mask-events';
function TransparentButton({ imageUrl, onClick, threshold = 0.8 }) {
const buttonRef = useRef(null);
useEffect(() => {
if (buttonRef.current) {
// Register the element when component mounts
AME.register(buttonRef.current, { threshold });
// Clean up when component unmounts
return () => {
AME.unregister(buttonRef.current);
};
}
}, [threshold]);
return (
<button
ref={buttonRef}
onClick={onClick}
style={{
backgroundImage: `url(${imageUrl})`,
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
border: 'none',
padding: '20px'
}}
/>
);
}
// Usage
function App() {
useEffect(() => {
AME.init({ log: process.env.NODE_ENV === 'development' });
}, []);
return (
<div>
<TransparentButton
imageUrl="/irregular-button.png"
onClick={() => console.log('Button clicked!')}
threshold={0.5}
/>
</div>
);
}Vue Integration
<template>
<button
ref="transparentBtn"
class="transparent-btn"
@click="handleClick"
:style="{ backgroundImage: `url(${imageUrl})` }"
>
<slot></slot>
</button>
</template>
<script>
import AME from 'alpha-mask-events';
export default {
props: {
imageUrl: String,
threshold: {
type: Number,
default: 0.8
}
},
mounted() {
// Initialize AME if this is the first component
if (!this.$AME) {
this.$AME = AME.init({ log: process.env.NODE_ENV === 'development' });
}
// Register this button
AME.register(this.$refs.transparentBtn, { threshold: this.threshold });
},
beforeDestroy() {
AME.unregister(this.$refs.transparentBtn);
},
methods: {
handleClick() {
this.$emit('click');
}
}
}
</script>
<style scoped>
.transparent-btn {
background-size: contain;
background-repeat: no-repeat;
border: none;
padding: 20px;
cursor: pointer;
}
</style>Dynamic Content and Intersection Observer
For dynamic content or long pages, combine with IntersectionObserver for better performance:
import AME from 'alpha-mask-events';
// Initialize
AME.init({ threshold: 0.8 });
// Setup IntersectionObserver to only process visible elements
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
const el = entry.target;
if (entry.isIntersecting) {
// Element is visible, register it
AME.register(el);
} else {
// Element is off-screen, unregister to save resources
AME.unregister(el);
}
});
}, { rootMargin: '100px' });
// Observe all transparency-enabled elements
document.querySelectorAll('.alpha-mask-events').forEach(el => {
observer.observe(el);
});Browser Compatibility
- Chrome 50+
- Firefox 50+
- Safari 11+
- Edge 18+
- iOS Safari 11+
- Android Browser 76+
Polyfill required for:
ResizeObserver(for older browsers)PointerEvent(falls back totouchevents on older mobile browsers)
Performance Tips
Automatic Image Caching:
- The library automatically caches loaded images to avoid redundant network requests
- Multiple elements using the same image source share a single cached
Imageobject - Cache persists for the entire page session, providing instant registration for repeated images
- Memory efficient: images are cached by URL, not duplicated per element
Use appropriate threshold values:
- Higher values (closer to 1.0) make fewer pixels click-through
- Lower values (closer to 0.0) make more pixels click-through
Optimize image sizes:
- Large images take longer to process
- Consider resizing images to actual displayed dimensions
Unregister elements when not needed:
- Use
AME.unregister()for elements being removed from DOM
- Use
Use the CLI tool for static masks:
- For static images, pre-generate mask data
- Load JSON masks instead of analyzing images at runtime
How to Create a Mask Using the CLI
To generate a mask for an image using the CLI tool, use the npx ame-generate-masks command. This will analyze the transparency of your image and output a JSON mask file describing the opaque regions.
Example: Generate a Mask for a PNG Image
npx ame-generate-masks logo.png --out logo-mask.jsonThis command processes logo.png and writes the mask data to logo-mask.json.
Example: Custom Threshold and Blur
npx ame-generate-masks hero.webp --out hero-mask.json --threshold 0.2 --blur 2--threshold 0.2: Pixels with alpha > 0.2 are considered opaque (included in mask).--blur 2: Applies a box blur of radius 2 pixels to the alpha channel before thresholding.
Example: Multiple Images
npx ame-generate-masks sprites/*.png --out masks.jsonProcesses all PNG files in the sprites directory and outputs a combined mask file.
Output Format
The output JSON contains the dimensions and rectangles for each image's opaque regions:
{
"logo.png": {
"width": 256,
"height": 256,
"rects": [
{ "x": 10, "y": 10, "w": 50, "h": 1 },
{ "x": 8, "y": 11, "w": 54, "h": 1 }
]
}
}Tip: Use the generated mask file for server-side hit-testing or to optimize client-side performance by loading precomputed mask data.
Development
- Build:
npm run build(uses Rollup) - Test:
npm test(Jest) - Lint:
npm run lint
Testing
The library includes comprehensive tests to ensure reliability:
Browser Library Tests (manager.test.js)
- Element Registration: Verifies elements can be added to and removed from the registry
- Threshold Management: Tests that
setThresholdupdates all registered elements - Auto-scanning: Confirms that
.alpha-mask-eventselements are automatically detected - Event Handling: Validates pointer event handling infrastructure
CLI Tool Tests (generate-masks.test.js)
- Mask Generation: Tests creation of JSON-based rectangle masks from PNG transparency
- Output Validation: Ensures generated masks contain proper width, height and rectangle data
- Error Handling: Verifies appropriate error when no images are provided
- User Feedback: Confirms proper success messages are displayed
Run all tests with npm test.
Contributing
Contributions welcome! Please open an issue or pull request on GitHub.
License
MIT
