Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

More modern image maps?

With all the recent advances in JavaScript/HTML5 it would be nice to think there would be a more modern way of implementing an image map. I know you can set a map property for the tag but I don't think this supports nicely formatted tooltips on rollover (near the region). My requirement are really just tooltips, onClick/doubleClick actions on a region within an image.

Last questions on here about similar things I found were from 5 years ago.

Ideally I'd like to use pure js/html/css and not use JQuery plugins etc although I see there are a few available.

like image 417
kayakpim Avatar asked Jun 23 '15 09:06

kayakpim


People also ask

Do people still use image maps?

The bottom line is that if you want or need to use an image map, they are still a part of the standard, and they do have valid uses. Just try to make them as accessible and easy to use as you can.

Are image maps deprecated?

In short - it is part of both specs and is not deprecated.

Are HTML image maps responsive?

Image maps, however, are not natively responsive. That means that if the image scale needs adjustments due to a browser's window being resized or the page being viewed on a mobile device, the image map and its clickable area will not scale down with the screen size.

How many types of image maps are there?

Two types of image maps are client side and server side. Client side image maps provide multiple active regions through the browser and they can be made accessible relatively easily. Server side image maps require a mouse to be used and transfer click data to the server for processing.


1 Answers

Responsive SVG solution or classic image map

After taking Paulie_D's comment about SVG into account, I wrote an alternative using SVG to the classic image map. Both work fine, but the SVG version clearly wins when it comes to responsiveness. Both versions have a connection between the anchors and the respective tooltip using the href-attribute. Both solutions work with vanilla JavaScript, without an extra library.


SVG version

Advantages

  • responsive
  • tooltips can be placed easily using JavaScript

HTML

<svg id="map" version="1.1" viewBox="0 0 300 300">
    <image width="300" height="300" xlink:href="http://placehold.it/300"/>

    <a xlink:href="#t_1">
        <rect x="50" y="50" width="50" height="50" />
    </a>

    <a xlink:href="#t_2">
        <rect x="150" y="150" width="50" height="50" />
    </a>
</svg>

<div class="t" id="t_1">Tooltip 1</div>
<div class="t" id="t_2">Tooltip 2</div>

CSS

html, body {
    width: 100%;
    margin: 0;
    padding: 0;
}

svg {
    display: block;
    width: 80%;
    max-width: 300px;
    margin: 0 auto;
}

svg rect {
    fill: white;
    opacity: 0.1;
    transition: all 0.2s linear;
}

svg rect:hover {
    opacity: 0.8;
}

.t {
    opacity: 0;
    position: absolute;
    left: 0;
    top: 0;
    transition: opacity 0.4s linear;
}

.t.active {
    opacity: 1;
}

JavaScript*

var map = document.getElementById('map');
var areas = map.getElementsByTagName('a');
var offset = { left: 30, top: 70 };

for (var i = 0; i < areas.length; i++) {
    areas[i].onmouseover = function() {
        // get child element
        var c = this.firstElementChild;
        // get tooltip
        var t = document.getElementById(this.getAttribute('xlink:href').substr(1));
        // set styles
        t.style.left = (map.offsetLeft + parseInt(c.getAttribute('x')) + offset.left) + 'px';
        t.style.top = (map.offsetTop + parseInt(c.getAttribute('y')) + offset.top) + 'px';
        // show it
        t.classList.toggle('active');
    }
    areas[i].onmouseout = function() {
        // get tooltip
        var t = document.getElementById(this.getAttribute('xlink:href').substr(1));
        // hide it
        t.classList.toggle('active');
    }
}

Notes

  • the positioning could be improved, it's just to show a direction

Demo

Try before buy


Classic image map version

HTML

<img src="http://placehold.it/300" alt="" usemap="#map">
<map id="map" name="map">
    <area shape="rect" coords="0,0,50,50" href="#t_1" alt="Tip 1" data-left="80px" data-top="80px" />
    <area shape="rect" coords="100,100,150,150" href="#t_2" alt="Tip 2" data-left="180px" data-top="180px" />
</map>

<div class="t" id="t_1">Tooltip 1</div>
<div class="t" id="t_2">Tooltip 2</div>

CSS

.t {
    opacity: 0;
    position: absolute;
    left: 0;
    top: 0;
    transition: opacity 0.4s linear;
}

.t.active {
    opacity: 1;
}

JavaScript*

var areas = document.getElementById('map').children;

for (var i = 0; i < areas.length; i++) {
    areas[i].onmouseover = function() {
        var t = document.getElementById(this.hash.substr(1));
        t.style.left = this.dataset.left;
        t.style.top = this.dataset.top;
        t.classList.toggle('active');
    }
    areas[i].onmouseout = function() {
        var t = document.getElementById(this.hash.substr(1));
        t.classList.toggle('active');
    }
}

Notes

  • attaching the position using the data-*-attributes, decouples the JavaScript (unfortunately you can't use offsetLeft/Top and determine the position based on the area-element) - you could however calculate it by using the coords-attribute
  • the JavaScript code could be improved (for example store tooltips instead of re-query them all the time)

Demo

Try before buy


* In both examples the JavaScript could be improved, e.g. store tooltip elements in a variable instead of re-query them all the time.

like image 71
insertusernamehere Avatar answered Sep 29 '22 11:09

insertusernamehere