2

I have the following PNG image with transparency:

Button image

I would like to make a button in HTML & CSS that uses the alpha channel as a mask, so that it only works if the users clicks in the pink area.

Is that possible? How can it be implemented?

Danziger
  • 19,628
  • 4
  • 53
  • 83
Andrew w
  • 21
  • 3
  • 1
    that's one way of making things awkward for the user - to have to click on a specific area of a button in order for it to work.... brush up on user friendliness! – Rachel Gallen May 09 '17 at 07:45
  • it's for an interactive website, that has a web app running a small game, the image is just an extreme example! – Andrew w May 09 '17 at 16:11
  • @Andreww Did anyone solve your problem? If so, could you please accept the best answer (click the checkmark under the points). That will help other users that come across your question quickly spot the accepted answer and it also gives 15 rep. points to the author (: – Danziger Jan 31 '18 at 06:05

2 Answers2

0

You might want to check out image-map HTML map Tag

Hash
  • 7,726
  • 9
  • 34
  • 53
  • That will work for simple and static use cases, but I don't think it is the right solution for an arbitrary shape/image, specially if it may change in the future. Moreover, that will not take into account the alpha channel of the image and will have to be defined manually. – Danziger May 09 '17 at 08:59
0

You need to draw your image into a canvas to get the pixel values and check the alpha channel value:

const messageBox = document.getElementById('messageBox');
const imageButton = document.getElementById('imageButton');
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const width = imageButton.width;
const height = imageButton.height;

canvas.width = width;
canvas.height = height;

context.drawImage(imageButton, 0, 0, width, height);

imageButton.onclick = function(e) {
  const alpha = context.getImageData(e.offsetX, e.offsetY, 1, 1).data[3];
  
  switch (alpha) {
    case 255:
      messageBox.innerText = "Inside clicked";
      
      break;
      
    case 0:
      messageBox.innerText = "Outside clicked";
      
      // Here you could do e.preventDefault(); if this is a form submit event or something like that.
      
      break;
      
    default:
      messageBox.innerText = "Border clicked.";
      
      // Decide how to handle clicks in the border or change the switch for an if and define a range of valid and invalid values for the alpha channel.
      
      break;
  }
};
#imageButton {
  box-shadow: inset 0 0 0 1px rgba(255, 0, 0, .5);
  cursor: pointer;
  width: 100px;
}
<img id="imageButton" src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" />

<div id="messageBox"></div>

Note I'm using a small data URI instead of your image to avoid Cross-Origin issues or an answer that is larger than allowed.

Danziger
  • 19,628
  • 4
  • 53
  • 83
  • 1
    Thank you for the reply, the javascript code comments are so helpful! I come from a c# programming background making the switch to front end, Wonderful! – Andrew w May 09 '17 at 16:31
  • 1
    @Andreww If this answer addressed your issue, it would be great if you could accept/upvote it (: – Danziger May 08 '20 at 21:30