{"id":10608,"library":"canvas-color-tracker","title":"Canvas Color-Based Object Tracking Utility","description":"canvas-color-tracker is a utility library (current stable version 1.3.2) designed to facilitate interaction with dynamically rendered objects on an HTML5 canvas, where native object-specific mouse events are not available. It provides a system for tracking canvas elements by assigning each a unique, invisible color key on a 'shadow' or off-screen canvas. Developers render their objects on this shadow canvas with these unique colors, then use `mousemove` events on the main canvas to sample the pixel color under the mouse pointer. This color is then used to look up the associated object in the `canvas-color-tracker` registry. A key feature is its checksum encoding mechanism for color keys, which enhances lookup reliability by accounting for pixel anti-aliasing and color mutations at object boundaries. The library focuses solely on the registry aspect: generating keys, registering objects, and performing lookups. It enables effective object identification and interaction for complex canvas applications, supporting up to approximately 262,000 objects with default settings.","status":"active","version":"1.3.2","language":"javascript","source_language":"en","source_url":"https://github.com/vasturiano/canvas-color-tracker","tags":["javascript","canvas","color","tracker","interaction","hover","hidden","typescript"],"install":[{"cmd":"npm install canvas-color-tracker","lang":"bash","label":"npm"},{"cmd":"yarn add canvas-color-tracker","lang":"bash","label":"yarn"},{"cmd":"pnpm add canvas-color-tracker","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The library primarily uses ESM syntax. For CommonJS environments (Node.js versions < 12 without ESM support), direct `require` might lead to issues or require a bundler. For browser environments, a script tag is also available.","wrong":"const ColorTracker = require('canvas-color-tracker');","symbol":"ColorTracker","correct":"import ColorTracker from 'canvas-color-tracker';"},{"note":"For direct browser usage without a module bundler, the library can be loaded via a script tag, making `ColorTracker` globally available.","symbol":"ColorTracker","correct":"<script src=\"//cdn.jsdelivr.net/npm/canvas-color-tracker\"></script>"}],"quickstart":{"code":"import ColorTracker from 'canvas-color-tracker';\n\n// Assume a canvas context is available for pixel data\nconst canvas = document.createElement('canvas');\ncanvas.width = 800; canvas.height = 600;\nconst context = canvas.getContext('2d', { willReadFrequently: true });\n\nconst shadowCanvas = document.createElement('canvas');\nshadowCanvas.width = canvas.width; shadowCanvas.height = canvas.height;\nconst shadowCtx = shadowCanvas.getContext('2d', { willReadFrequently: true });\n\n// Create a new ColorTracker instance\n// Default checksum_bits (6) allows ~262k objects. Use `new ColorTracker(4)` for ~1M objects.\nconst myTracker = new ColorTracker();\n\n// Register an object and get its unique color key\nconst myObject = { id: 1, name: 'Red Square', x: 50, y: 50, size: 20 };\nconst myObjectColor = myTracker.register(myObject);\n\nif (myObjectColor) {\n  // Draw the actual object on the main canvas\n  context.fillStyle = 'red';\n  context.fillRect(myObject.x, myObject.y, myObject.size, myObject.size);\n\n  // Draw the object with its unique shadow color on the hidden shadow canvas\n  shadowCtx.fillStyle = myObjectColor;\n  shadowCtx.fillRect(myObject.x, myObject.y, myObject.size, myObject.size);\n}\n\n// Simulate a mouse hover event\nconst hoverX = 55; // Inside the red square\nconst hoverY = 55;\n\n// Get the pixel color from the shadow canvas at the hover position\nconst pixel = shadowCtx.getImageData(hoverX, hoverY, 1, 1).data; // Returns a Uint8ClampedArray: [r, g, b, a]\nconst hoverColor = [pixel[0], pixel[1], pixel[2]]; // Only RGB is used for lookup\n\n// Look up the object using the color data\nconst hoveredObject = myTracker.lookup(hoverColor);\n\nif (hoveredObject) {\n  console.log('Hovered over:', hoveredObject.name);\n  // Expected: Hovered over: Red Square\n} else {\n  console.log('No object found at this position.');\n}\n\n// Example of registry full scenario (highly simplified, usually needs many registrations)\n// For demonstration, let's assume we force it to be full or hit null return\n// myTracker.register(someObject) could return null if capacity exceeded.\n","lang":"typescript","description":"Demonstrates how to initialize ColorTracker, register an object with a unique color, draw it on both a main and a hidden shadow canvas, and then look up the object based on a sampled pixel color from the shadow canvas, simulating a hover event."},"warnings":[{"fix":"Adjust `new ColorTracker(checksum_bits)` based on your application's requirements for object count versus collision robustness. For example, `new ColorTracker(4)` allows ~1 million objects.","message":"The `checksum_bits` parameter, configurable during `ColorTracker` instantiation, directly impacts the maximum number of objects the registry can store. Higher `checksum_bits` reduce the chance of anti-aliasing-induced color collisions but decrease the total capacity. The maximum objects are `2^(24 - checksum_bits) - 1`. The default of 6 bits supports approximately 262,000 objects.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always check the return value of `myTracker.register(obj)`. If `null` is returned, the object was not added, and you should consider increasing the registry capacity by reducing `checksum_bits` if feasible, or implementing a strategy to manage object registration.","message":"The `register()` method returns `null` if the object registry is full and cannot store any more unique objects. This can lead to silent failures if not handled.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure your shadow canvas rendering is as consistent as possible. If issues persist, consider disabling anti-aliasing for the shadow canvas context if your canvas library supports it, or carefully choosing your `checksum_bits` value. The built-in checksum mechanism is designed to handle common anti-aliasing scenarios.","message":"Canvas anti-aliasing on object boundaries can produce blended pixel colors, which might not precisely match the unique color key assigned by the tracker. `canvas-color-tracker` mitigates this with checksum encoding, but extreme anti-aliasing or certain rendering contexts could still lead to lookup failures.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure the color passed to `lookup` is either a hex string (e.g., `'#RRGGBB'`) or an `[r, g, b]` array (e.g., `ImageData.data` sliced to the first three values). Verify that your shadow canvas drawing precisely matches the object's registered color. The internal checksum usually handles minor anti-aliasing discrepancies.","cause":"The sampled pixel color from the shadow canvas does not exactly match a registered object's unique key, potentially due to anti-aliasing or an incorrect color format being passed to `lookup`.","error":"Object not found for sampled color (or `lookup` returns `null`/`undefined`)"},{"fix":"Review the number of objects being tracked. If it exceeds approximately 262,000 (default `checksum_bits=6`), you may need to instantiate `ColorTracker` with a lower `checksum_bits` value (e.g., `new ColorTracker(4)` for ~1 million objects), accepting a slightly higher theoretical risk of checksum collisions.","cause":"The internal object registry has reached its maximum capacity, preventing new objects from being added.","error":"`myTracker.register(myObject)` returns `null` instead of a color string."}],"ecosystem":"npm"}