How to get the pixel color from a canvas on click or mouse event with Javascript

There are many utilities that you could create if you would be able to extract the color from a single pixel of a canvas, an interactive color picker etc. This task is relatively easy to achieve using pure javascript without any kind of library.

To retrieve the color from a pixel of a specific canvas, we are going to :

  • Retrieve the location of the mouse event.
  • Use the coordinates to select the data on the canvas.
  • Use the RGBA data of the pixel.

Let's get started !

Retrieving mouse location on event

As there are many possible errors and things that the user could do, we need to be exact as possible, therefore to guarantee that the mouse coordinates are reliable, we are going to retrieve them according to the location of the canvas.

Use the following function to retrieve the location of the element (in this case the canvas) , it expects the DOM element as first parameter. However this function will be internally used by the function that is going to retrieve the location of the click.

/**
 * Return the location of the element (x,y) being relative to the document.
 * 
 * @param {Element} obj Element to be located
 */
function getElementPosition(obj) {
    var curleft = 0, curtop = 0;
    if (obj.offsetParent) {
        do {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
        return { x: curleft, y: curtop };
    }
    return undefined;
}

The previous method returns the location (an object with x and y coordinates) of the element given as first parameter (canvas in this case) in the document.

Now that we can get the location of the canvas, the following method will be the one that cares about the location of the click on the canvas (or another mouse event attached to the canvas) :

/** 
 * return the location of the click (or another mouse event) relative to the given element (to increase accuracy).
 * @param {DOM Object} element A dom element (button,canvas,input etc)
 * @param {DOM Event} event An event generate by an event listener.
 */
function getEventLocation(element,event){
    // Relies on the getElementPosition function.
    var pos = getElementPosition(element);
    
    return {
    	x: (event.pageX - pos.x),
      	y: (event.pageY - pos.y)
    };
}

The getEventLocation method return the coordinates (x,y) according to the mouse event (click, mousemove etc) even if the user zooms on the document as the use of the getElementPosition increases the accuracy of the getEventLocation function.

Draw image on a canvas (testing purpose)

This article assumes that you know how to draw an image on a canvas or you have already something drawn using paths and therefore you want to retrieve the color from a pixel etc. However, if you don't have anything you can use the following function to draw an image (from base64 or internet url) on a canvas :

var canvas = document.getElementById("canvas");

/**
 * Draw an image (from your own domain or base64)
 * @param {String} sourceurl
 */
function drawImageFromWebUrl(sourceurl){
    var img = new Image();

    img.addEventListener("load", function () {
        // The image can be drawn from any source, the canvas will be filled with the image.
        canvas.getContext("2d").drawImage(img, 0, 0, img.width,    img.height, 0, 0, canvas.width, canvas.height); 
    });

   img.setAttribute("src", sourceurl);
}

Note : you can draw any image if you want, however if the image is not providen from your own domain (yourdomain.com and the image comes from otherdomain.com), then you'll face a problem with the Tainted Canvas error, read more about this problem here. Therefore in our example we're going to use a base64 string instead of a web image.

Retrieving pixel data according to the location

Now to retrieve the color from a pixel, we are going to use the getImageData method from the context of the canvas and we are going to limit it to 1 pixel (x1,y1) according to the location of a click (or any mouse event that you want) event.

The following snippet shows how to retrieve the color from a pixel on the click event of the canvas :

Note: you can use a jQuery event listener instead if you want, only be sure to provide the event variable.

var canvas = document.getElementById("canvas");

canvas.addEventListener("click",function(event){
    // Get the coordinates of the click
    var eventLocation = getEventLocation(this,event);
    // Get the data of the pixel according to the location generate by the getEventLocation function
    var context = this.getContext('2d');
    var pixelData = context.getImageData(eventLocation.x, eventLocation.y, 1, 1).data; 

    // If transparency on the pixel , array = [0,0,0,0]
    if((pixelData[0] == 0) && (pixelData[1] == 0) && (pixelData[2] == 0) && (pixelData[3] == 0)){
        // Do something if the pixel is transparent
    }

    // Convert it to HEX if you want using the rgbToHex method.
    // var hex = "#" + ("000000" + rgbToHex(pixelData[0], pixelData[1], pixelData[2])).slice(-6);
},false);

The pixelData is an UInt8ClampedArray with 4 items ([0] => red, [1] => green, [2] => blue, [3] => alpha (transparency)).

That was , manipulate the color as you want and use it as you want. You can even convert the RGBA to HEX color using the following method if you want :

function rgbToHex(r, g, b) {
    if (r > 255 || g > 255 || b > 255)
        throw "Invalid color component";
    return ((r << 16) | (g << 8) | b).toString(16);
}

Play with the following fiddle with the above code working. The attached example will draw a base64 image on the canvas and then the listener of mousemove will be attached to it, navigate to the Result tab and test it.

Have fun

This could interest you

Become a more social person