简体   繁体   中英

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.

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, eg store tooltip elements in a variable instead of re-query them all the time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM