7

I'm trying to map all the numbers in the image below, which I've done. But now I want to dynamically resize the image and map according to the window's width.

enter image description here

Here's the relevant html:

    <html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1"> 
    <title>20 Keys</title> 

    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />
    <link rel="stylesheet" type="text/css" href="css/styles.css">

    <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>
    <script src="js/script.js"></script>

</head> 

<body> 
<!-- Start of first page: #home-->
<div data-role="page" id="home" data-theme="b"> 

    <div data-role="header">
        <img src="images/20keyslogo.jpg" width="100%">
    </div><!-- /header -->

    <div class="white" data-role="content" data-theme="b">  

    <img id="imageMaps" src="images/20keys.jpg" usemap="#20Keys" width="100%" alt="Select Key" border="0"/>
        <map id="20Keys" name="20Keys">
            <area shape="circle" alt="Key 1" title="" coords="41,54,31" href="" target="" />
            <area shape="circle" alt="Key 2" title="" coords="41,543,31" href="" target="" />
            <area shape="circle" alt="Key 3" title="" coords="538,543,31" href="" target="" />
            <area shape="circle" alt="Key 4" title="" coords="499,293,31" href="" target="" />
            <area shape="circle" alt="Key 5" title="" coords="484,213,31" href="" target="" />
            <area shape="circle" alt="Key 6" title="" coords="79,293,31" href="" target="" />
            <area shape="circle" alt="Key 7" title="" coords="141,145,31" href="" target="" />
            <area shape="circle" alt="Key 8" title="" coords="483,374,31" href="" target="" />
            <area shape="circle" alt="Key 9" title="" coords="209,99,31" href="" target="" />
            <area shape="circle" alt="Key 10" title="" coords="290,504,31" href="" target="" />
            <area shape="circle" alt="Key 11" title="" coords="289,83,31" href="" target="" />
            <area shape="circle" alt="Key 12" title="" coords="370,99,31" href="" target="" />
            <area shape="circle" alt="Key 13" title="" coords="370,488,31" href="" target="" />
            <area shape="circle" alt="Key 14" title="" coords="95,213,31" href="" target="" />
            <area shape="circle" alt="Key 15" title="" coords="438,442,31" href="" target="" />
            <area shape="circle" alt="Key 16" title="" coords="438,145,31" href="" target="" />
            <area shape="circle" alt="Key 17" title="" coords="95,374,31" href="" target="" />
            <area shape="circle" alt="Key 18" title="" coords="141,442,31" href="" target="" />
            <area shape="circle" alt="Key 19" title="" coords="209,488,31" href="" target="" />
            <area shape="circle" alt="Key 20" title="" coords="538,45,31" href="" target="" />
        </map>
        <p><a href="#two" data-role="button">Interactions between any two keys</a></p>  
        <p><a href="#about" data-role="button">About 20 Keys</a></p>    
        <p><a href="http://www.20keysglobal.com" data-role="button">Visit International 20 Keys Website</a></p>                 
        <p><a href="#register" data-role="button" data-rel="dialog" data-transition="pop">Register for Pro Version</a></p>
        <p><a href="mailto:christiaan.grove@odi.co.za" data-role="button">Make Suggestion for Improvement</a></p>
    </div><!-- /content -->

    <div data-role="footer" data-theme="d">

        <p class="margin">
        <a href="#home" data-rel="back" data-role="button" data-inline="true" data-icon="gear">Settings</a>
        </p>

    </div><!-- /footer -->
</div><!-- /page one -->

And here's the javascript I used from the best answer in Dynamically resizing Image-maps and images (thanks Teemo):

window.onload = function () {
    var ImageMap = function (map) {
            var n,
                areas = map.getElementsByTagName('area'),
                len = areas.length,
                coords = [],
                previousWidth = 604;
            for (n = 0; n < len; n++) {
                coords[n] = areas[n].coords.split(',');
            }
            this.resize = function () {
                var n, m, clen,
                    x = document.body.clientWidth / previousWidth;
                for (n = 0; n < len; n++) {
                    clen = coords[n].length;
                    for (m = 0; m < clen; m++) {
                        coords[n][m] *= x;
                    }
                    areas[n].coords = coords[n].join(',');
                }
                previousWidth = document.body.clientWidth;
                return true;
            };
            window.onresize = this.resize;
        },
        imageMap = new ImageMap(document.getElementById('20Keys'));
    imageMap.resize();
    return;
}

The image and map does resize on according to the window width but unfortunately not as perfectly as I'd like it to. Only the first Key actually resizes perfectly when the window resizes. For the rest, the further away from the top left the more inaccurate it is.

I've already changed the image to be a perfect square in hope that it'll fix the problem but it hasn't.

I'm not too experienced in javascript, and my math skills aren't what they used to be. All help will be appreciated. Thank you in advance.

Community
  • 1
  • 1
Barry Michael Doyle
  • 9,333
  • 30
  • 83
  • 143
  • Hmm... seems to be [quite accurate](http://jsfiddle.net/32rx6/) in the latest Chrome, FF and IE. Any particular browser causing troubles? – Teemu May 20 '14 at 08:07
  • Try using this query plugin, works perfectly for me: https://github.com/stowball/jQuery-rwdImageMaps – ChaveVrey May 20 '14 at 08:47
  • @Teemu, yeah it doesn't work in any of my browsers (but it works fine in your JFiddle example), I've added my first page of the html to the question. Would anything here affect it? – Barry Michael Doyle May 20 '14 at 11:22

2 Answers2

8

Probably the width of the image is not 100% of the body. Instead of calculating the scale (x) with document.body.clientWidth, use the offsetWidth of the image:

x = img.offsetWidth / previousWidth;
                 :
previousWidth = img.offsetWidth;

A live demo at jsFiddle.

Notice, that the aspect ratio of the image doesn't need to be 1:1, the scale is the same for both directions, as long as you keep the original ratio of the image.

(The original code is maybe too much binded to the original question, rather than being a generic multi-purpose map resizer.)

Teemu
  • 22,918
  • 7
  • 53
  • 106
  • 2
    Thanks Teemu! This is an amazing multipurpose map resizer now... It's good to use Javascript instead of going the jquery way, it'll prevent complications later. – Barry Michael Doyle May 20 '14 at 14:50
  • 2
    @BarryDoyle It'll get even better, if used with a [debouncer](http://stackoverflow.com/a/4298672/1169519). `onresize` is fired tens of times per second during resizing, if you have a large `map`, the scale might be calculated incorrectly. Calling `imageMap.resize` from a debouncer will keep the scale always correct. – Teemu May 20 '14 at 15:06
  • 1
    Thanks Teemu. Works beautifully. – Steve Jul 27 '15 at 13:43
  • Thanks @Teemu, that's a piece of art! – Techno.Shaman Aug 05 '15 at 23:30
1

You might find this little project of mine helpful, as a more generic solution, that also copes with non-fixed aspect ratios and multiple ImageMaps on the page.

https://github.com/davidjbradshaw/imagemap-resizer

David Bradshaw
  • 11,859
  • 3
  • 41
  • 70