Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>So, this is an old question but it is a problem that I encountered myself this week and couldn't find any helpful answers for. The answer above doesn't quite directly address the issue of making a droppable from an area element on an html image map - it posits an answer but that answer doesn't actually work because making an 'area' droppable makes the entire image map into the droppable so you can't determine which area is active when the item is dropped. </p> <p>Here is the solution that I ended up implementing for my problem (which uses poly areas):</p> <pre><code>&lt;div id="content"&gt; &lt;div id="targetImage"&gt;&lt;img src="images/interactive_bg_triColored.png" usemap="#targetOverlay" alt="Strategic Action Chart"/&gt; &lt;map id="targetOverlay" name="targetOverlay"&gt; &lt;area id="slice_0" shape="poly" coords="47, 294, 82, 178, 236, 267, 224, 293" /&gt; &lt;area id="slice_1" shape="poly" coords="87, 171, 168, 89, 258, 235, 240, 254" /&gt; &lt;area id="slice_2" shape="poly" coords="177, 82, 295, 48, 297, 228, 265, 234" /&gt; &lt;area id="slice_3" shape="poly" coords="302, 49, 419, 81, 334, 232, 303, 227" /&gt; &lt;area id="slice_4" shape="poly" coords="428, 84, 514, 170, 360, 258, 338, 239" /&gt; &lt;area id="slice_5" shape="poly" coords="364, 266, 516, 186, 546, 292, 373, 294" /&gt; &lt;area id="slice_6" shape="poly" coords="546, 307, 518, 412, 363, 333, 373, 305" /&gt; &lt;area id="slice_7" shape="poly" coords="512, 427, 428, 508, 340, 361, 360, 343" /&gt; &lt;area id="slice_8" shape="poly" coords="421, 515, 304, 549, 302, 375, 334, 365" /&gt; &lt;area id="slice_9" shape="poly" coords="295, 550, 180, 517, 266, 366, 295, 371" /&gt; &lt;area id="slice_10" shape="poly" coords="170, 512, 86, 431, 240, 340, 259, 360" /&gt; &lt;area id="slice_11" shape="poly" coords="80, 422, 51, 304, 228, 305, 235, 332" /&gt; &lt;/map&gt; &lt;/div&gt; &lt;div id="word_list"&gt; &lt;div id="instructions"&gt;Drag these action words into the appropriate category on the left.&lt;/div&gt; &lt;div id="word_6" class="draggable_word answer_o"&gt;Adjust&lt;/div&gt; &lt;div id="word_7" class="draggable_word answer_m"&gt;Infer&lt;/div&gt; &lt;div id="word_8" class="draggable_word answer_m"&gt;Synthesize&lt;/div&gt; &lt;div id="word_4" class="draggable_word answer_o"&gt;Summarize&lt;/div&gt; &lt;div id="word_5" class="draggable_word answer_o"&gt;Maintain&lt;br /&gt; Fluency&lt;/div&gt; &lt;div id="word_9" class="draggable_word answer_m"&gt;Make&lt;br /&gt;Connections&lt;/div&gt; &lt;div id="word_11" class="draggable_word answer_p"&gt;Critique&lt;/div&gt; &lt;div id="word_10" class="draggable_word answer_m"&gt;Predict&lt;/div&gt; &lt;div id="word_2" class="draggable_word answer_o"&gt;Monitor &lt;br /&gt;and Correct&lt;/div&gt; &lt;div id="word_3" class="draggable_word answer_o"&gt;Search &amp; Use&lt;br /&gt; Information&lt;/div&gt; &lt;div id="word_0" class="draggable_word answer_p"&gt;Analyze&lt;/div&gt; &lt;div id="word_1" class="draggable_word answer_o"&gt;Solve Words&lt;/div&gt; &lt;/div&gt; </code></pre> <p></p> <p>The CSS: </p> <pre><code> .draggable_word { font-weight: bold; padding: 5px; width: 100px; display: inline-block } .draggable_word:hover { cursor: pointer; } </code></pre> <p>Note, you have to have a width set on your .draggable class (you can name it whatever, but it needs to be applied to the item you are going to make draggable, in my case a div that has a small amount of text inside it)</p> <pre><code>var x1, y1 = 0; var area = []; //set of area objects var myDropTarget = 'invalid'; $(document).ready(function () { for (i = 0; i &lt; 12; i++) { $('#word_' + i).draggable({ cursor: "move", revert: function (socketObj) { //if false then no droppable target was found if (socketObj === false) { //revert the draggable by returning true return true; } else { //the drop location was a droppable zone, now test it for answer validity var offset = $(this).offset(); //gets the x,y position of the dragged object when it stops x1 = offset.left + ($(this).width() / 2); //establishes the center of the object to use for testing x,y y1 = offset.top + ($(this).height() / 2); var result = dropTarget(x1, y1); //returns id of area or 'invalid' //logic to validate answers if (result === 'invalid') { return true; } else { //evaluate for answer correctness var testSlice = result.split('_'); if ((testSlice[1] &gt; -1) &amp;&amp; testSlice[1] &lt; 6) { //first 6 slices are 'orange' if ($(this).hasClass('answer_o')) { //correct answer return false; //slice matches word answer class so do NOT revert } } else if ((testSlice[1] &gt; 5) &amp;&amp; testSlice[1] &lt; 10) { //next 4 slices are 'maroon' if ($(this).hasClass('answer_m')) { //correct answer return false; //slice matches word answer class so do NOT revert } } else if ((testSlice[1] &gt; 9 ) &amp;&amp; testSlice[1] &lt; 12) { //last 2 slices are 'purple' if ($(this).hasClass('answer_p')) { //correct answer return false; //slice matches word answer class so do NOT revert } } else return true; } console.log('drop ' + x1 + ', ' + y1); console.log(result); //if no correct answer was found then it will still need to revert; return true; } } }); } $('map area').each(function (i) { //this creates an array of area polygon objects so that we can test when an item has been dropped inside of one area[i] = {}; // creates a new object which will have properties for id, x coordinates, and y coordinates area[i].id = $(this).attr("id"); area[i].x = []; area[i].y = []; var coords = JSON.parse('[' + $(this).attr("coords") + ']'); var totalPairs = coords.length / 2; var coordCounter = 0; //variable to double iterate for (ix = 0; ix &lt; totalPairs; ix++) { //fill arrays of x/y coordinates for pnpoly area[i].x[ix] = coords[coordCounter]; area[i].y[ix] = coords[coordCounter + 1]; coordCounter += 2; } }); $('#targetImage').droppable({ // maps or areas don't work well as droppable targets so we make image's container div into the droppable tolerance: 'pointer' }); }); function dropTarget(dropX, dropY) { var target = 'invalid'; for (i = 0; i &lt; area.length; i++) { //iterate through all of our area objects if (pnpoly(area[i].x.length, area[i].x, area[i].y, dropX, dropY)) { for (ix = 0; ix &lt; area[i].x.length; ix++) { console.log(area[i].x[ix] + ', ' + area[i].y[ix]); } target = area[i].id; break; } } return target; } function pnpoly(nvert, vertx, verty, testx, testy) { //Point in Poly Test http://www.ecse.rpi.edu/~wrf/Research/Short_Notes/pnpoly.html var i, j, c = false; for (i = 0, j = nvert - 1; i &lt; nvert; j = i++) { if (((verty[i] &gt; testy) != (verty[j] &gt; testy)) &amp;&amp; (testx &lt; (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i])) { c = !c; } } return c; } </code></pre> <p>Basically what it does it is generates an array of objects to represent each 'area' element. These objects have a property for ID, an array of X points and an array of Y points. The draggable items report their center point which is then tested to see if it falls within a certain poly with the point-in-poly function (pnpoly). If a match is found then it returns the ID of the of the area, allowing us to apply logic in the draggable's revert function definition. In this case, I applied a dummy class to represent different acceptable answer types. </p> <p>Anyway, hopefully that helps someone in the future...</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload