How to Detect Canvas Shape Clicks Using Pixel Color and Transparency

By leveraging pixel color and alpha values, this guide explains how to determine whether a user click falls inside a Canvas shape, compares it with traditional methods like crossing number and winding number, and provides a practical implementation using Create.js with sample code.

KooFE Frontend Team
KooFE Frontend Team
KooFE Frontend Team
How to Detect Canvas Shape Clicks Using Pixel Color and Transparency

In the previous article we mentioned the crossing number and winding number methods for point‑in‑polygon tests. This article introduces another pixel‑color based detection scheme and provides source code to answer a question about Create.js.

Basic principle

When a user clicks on a Canvas, the color of the pixel at the click position can be used to decide whether the click hit a shape. For example, in the figure below the rectangle area is orange while the outside is transparent; if the color at point P is orange, we infer that P lies inside the rectangle.

Canvas rectangle with orange fill and transparent background
Canvas rectangle with orange fill and transparent background

In ideal cases this works, but real situations are more complex. If all rendered shapes share the same color, the method cannot distinguish them.

Canvas with uniformly colored shapes where pixel detection fails
Canvas with uniformly colored shapes where pixel detection fails

Most Canvas libraries (e.g., Fabric.js, Create.js) store shape attributes and state in memory, allowing them to be redrawn later. By redrawing the shape onto a fresh transparent Canvas, we can reuse the same pixel‑color detection: if the sampled pixel’s alpha is 0 the point missed the shape; otherwise it hit.

Off‑screen Canvas used for hit testing
Off‑screen Canvas used for hit testing

Implementation

Create.js uses the alpha‑comparison method to test whether a point lies on a shape. Below is a snippet of the relevant code.

/**
 * Tests whether the display object intersects the specified point in local coordinates
 * (i.e., draws a pixel with alpha > 0 at the specified position). This ignores the alpha,
 * shadow, hitArea, mask, and compositeOperation of the display object.
 *
 * @method hitTest
 * @param {Number} x The x position to check in the display object's local coordinates.
 * @param {Number} y The y position to check in the display object's local coordinates.
 * @return {Boolean} A Boolean indicating whether a visible portion of the DisplayObject
 * intersect the specified local Point.
 */
p.hitTest = function(x, y) {
  // DisplayObject._hitTestContext is a new Context
  var ctx = DisplayObject._hitTestContext;

  // Transform the point to (0,0)
  ctx.setTransform(1, 0, 0, 1, -x, -y);

  // Draw the object onto the new context
  this.draw(ctx, !(this.bitmapCache && !(this.bitmapCache._cacheCanvas instanceof WebGLTexture)));

  // Get the alpha value at (0,0); if greater than 1 the point is on the shape
  var hit = ctx.getImageData(0, 0, 1, 1).data[3] > 1;

  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.clearRect(0, 0, 2, 2);
  return hit;
};

Note that if a shape’s fill is fully transparent, this method fails; Create.js works around the issue by binding an opaque shape of the same size to the transparent one and using that for hit testing. The full source can be found at the linked GitHub file.

JavaScriptCreate.jshit testingpixel detection
KooFE Frontend Team
Written by

KooFE Frontend Team

Follow the latest frontend updates

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.