5

We have a quiz that we developed in Flash years ago that used hit areas to determine whether someone clicked on the appropriate portion of an image (think 'Anatomy Quiz'). These hit areas were very tedious to outline and there is no way to reuse the outline coordinate data...

Now, we're trying to re-do the thing in HTML -- So, we have a background image of a femur and a png which sits higher in the Z-order which has a portion of it completely transparent, while the other portions have 50% grey. This is used to teach the student WHERE something is on the background femur image.

I'd love to be able to use the data from that png mask layer in a 'quizzing mode' to determine whether the student correctly clicked on a specific portion of the femur... I was thinking to set the masking png to 100% transparency (so the student doesn't see it), but if the browser knew that they were clicking in the correct area of the image (that is 100% transparent on the mask), that they clicked correctly.

Any ideas on how to accomplish this with HTML, CSS, and/or jQuery?

5 Answers 5

5
var imgData,
     width = 200,
    height = 200;

$('#mask').bind('mousemove', function(ev){
    if(!imgData){ initCanvas(); }
    var imgPos = $(this).offset(),
      mousePos = {x : ev.pageX - imgPos.left, y : ev.pageY - imgPos.top},
      pixelPos = 4*(mousePos.x + width*mousePos.y),
         alpha = imgData.data[pixelPos+3];

    $('#opacity').text('Opacity = ' + ((100*alpha/255) << 0) + '%');
});

function initCanvas(){
    var canvas = $('<canvas width="'+width+'" height="'+height+'" />')[0],
           ctx = canvas.getContext('2d');

    ctx.drawImage($('#mask')[0], 0, 0);
    imgData = ctx.getImageData(0, 0, width, height);
}

This code loads the base64 image into a canvas, and uses getImageData to obtain a 2d RGBA representation of the image. It then uses the mouse's position to find the Alpha value (opacity) at that point in the image. Canvas ImageData is stored in a 2d array in groups of 4 (RGBA). What you're after is the "A", so every fourth value in the array. You can see this reflected in the code when discovering the pixel position, it multiplies the mouse's position by 4, and then to get at the alpha value it adds 3 (adding 0 would get you R, 1 would get you G, 2 would get you B).

https://jsfiddle.net/ey1d5vgr/

As of 2011, this didn't work in IE. Also, the image has to be on the same domain as the site, so no external images which is why this example used a data URI.

Sign up to request clarification or add additional context in comments.

3 Comments

Perfect -- and it even uses an anatomical image.
On further testing of a non-square image, I had to make an adjustment -- the pixelPos calculation needed to be adjusted to 4*(mousePos.x + width*mousePos.y) (it was height) and is now available at jsfiddle.net/JKzQN
I think you mean, 'Et Voilà' ;) Thanks for the tip!
1

I think you'll need to either process that server-side, or find a javascript library that can decode the image pixel by pixel.

A click event on a transparent part of a PNG still gets captured by the PNG. This is fairly unintuitive for a semi-transparent PNG which is z-indexed above something else, but that's standard behavior.

Comments

1

Here it is done in Action Script... (I think) I don't know how or if it can be done in Javascript though

http://dougmccune.com/blog/2007/02/03/using-hittestpoint-or-hittest-on-transparent-png-images/

Comments

1

my first idea was to build image maps, that way you can control what is clicked.

Other than that I have no idea and I don't think you can do it with a straightforward click on a PNG.

2 Comments

I imagine that a HTML image map, while being the only idea I could think of as well, might defeat the purpose of the quiz. This would allow the person taking the quiz to tab through the possible choices, or hunt around by hovering the mouse, and possibly spoil part of the question.
I thaught of that, and the solution is to have image maps for all parts of the bone, and possibly with javascript control the cursor, and maybe prevent cheating. Not easy but IMO it's possible.
0

Sorry, there's no way to do that with PNGs.

You need some other type of mask, an HTML image map being the simplest way, or depending on your browser dependencies, SVG is an option.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.