Assume circle.png is a 400x400 px transparent background image with a circle ...">

Alpha image map

<img src="circle.png" onclick="alert('clicked')"/> 

Assume circle.png is a 400x400 px transparent background image with a circle in the middle.

Now I have that the entire image area (400x400 pixels) is clickable. What I would like is that only a circle (opaque pixels) can be clicked.

Of course, I know that in this example I could use the <map> and the circular area, but I'm looking for a general solution that will take into account the real transparency of the image and work for any images (i.e. not regular shapes).

The most difficult way I could see was to trace the outline of the image based on each pixel alpha, convert to a path (possibly simplify) and apply it as a map.

Is there a more efficient / easy way to do this?

+6
source share
3 answers

Using the canvas tag, you can determine the pixel color value at a given location. You can use these events to determine the coordinates, and then check the transparency. It remains only to upload the image to the canvas.

Firstly, we will take care of this:

  var ctx = document.getElementById('canvas').getContext('2d'); var img = new Image(); img.onload = function(){ ctx.drawImage(img,0,0); }; img.src = [YOUR_URL_HERE]; 

This first bit captures the canvas element and then creates an Image object. When the image is loaded, it is painted on the canvas. Pretty simple! In addition, if the image is not in the same domain as the code, you are against the security policy of one domain. To get our image data, we need the image to be locally placed. You can also base64 encode your image, which is beyond the scope of this answer. (see this URL for a tool for this).

Then add the click event to the canvas. When this click appears, we will check the transparency and act only for the opaque click areas:

  if (isTransparentUnderMouse(this, e)) return; // do whatever you need to do alert('will do something!'); 

The magic happens in the isTransparentUnderMouse function, which requires two arguments: the canvas target element ( this in the click handler area) and event data (for example, in this example). Now we come to the meat:

 var isTransparentUnderMouse = function (target, evnt) { var l = 0, t = 0; if (target.offsetParent) { var ele = target; do { l += ele.offsetLeft; t += ele.offsetTop; } while (ele = ele.offsetParent); } var x = evnt.page.x - l; var y = evnt.page.y - t; var imgdata = target.getContext('2d').getImageData(x, y, 1, 1).data; if ( imgdata[0] == 0 && imgdata[1] == 0 && imgdata[2] == 0 && imgdata[3] == 0 ){ return true; } return false; }; 

First, we dance a bit to get the exact position of the element in question. We are going to use this information to navigate to the canvas element. getImageData will provide us with, among other things, a data object that contains the RGBA of the location we specified.

If all these values ​​are 0, we look at transparency. If not, there is some color. -edit- as noted in the comments, the only value that we really need to consider is the last one, imgdata[3] in the above example. The values ​​are r (0) g (1) b (2) a (3), and the transparency is determined by a, alpha. You can use the same approach to search for any color with any opacity that you know for rgba data.

Try it here: http://jsfiddle.net/pJ3MD/1/

( note: in my example, I used a base64 encoded image because of the domain security I mentioned. / p>

Same example, with mouse cursor changes thrown for fun: http://jsfiddle.net/pJ3MD/2/

Documentation

+17
source

You can do this using an HTML5 canvas. Draw an image on the canvas, attach the click handler to the canvas, and in the handler check if the pixel is transparent, transparent.

+4
source

Thank you for this great answer.

I added a few lines to the canvas scaling code

so now I am creating a canvas of the exact size of the pixel on which the image is drawn. (for image 220px * 120px):

 <canvas width="220" height="120" id="mainMenu_item"></canvas> 

and scale the canvas with css:

#mainMenu_item{ width:110px; }

and the adjusted function isTransparentUnderMouse looks like this:

  var isTransparentUnderMouse = function (target, evnt) { var l = 0, t = 0; if (target.offsetParent) { var ele = target; do { l += ele.offsetLeft; t += ele.offsetTop; } while (ele = ele.offsetParent); } var x = evnt.pageX - l; var y = evnt.pageY - t; var initialWidth = $(evnt.target).attr('width'); var clientWidth = evnt.target.clientWidth; x = x * (initialWidth/clientWidth); var initialHeight = $(evnt.target).attr('height');; var clientHeight = evnt.target.clientHeight; y = y * (initialHeight/clientHeight); var imgdata = target.getContext('2d').getImageData(x, y, 1, 1).data; if ( imgdata[0] == 0 && imgdata[1] == 0 && imgdata[2] == 0 && imgdata[3] == 0 ){ return true; } return false; }; 
+1
source

Source: https://habr.com/ru/post/919141/


All Articles