Reaktionsschnelle Imagemap


145

Ich habe eine vorhandene Imagemap in einem ansprechenden HTML-Layout. Die Bilder werden entsprechend der Browsergröße skaliert, aber die Bildkoordinaten sind offensichtlich feste Pixelgrößen. Welche Optionen habe ich, um die Größe der Bildkartenkoordinaten zu ändern?


6
Diese Frage handelt nicht von einer geografischen Karte, sondern vom HTML-Tag <map>
jdog

4
Schauen Sie sich das Image-Map- Plugin an. Es funktioniert mit Javascript, Node und jQuery
Travis Clarke

2
Alternativ können Sie ein SVG-Bild verwenden. Ich empfehle, SVG als Alternative zu Imagemaps zu
lesen

1
Klingt nach dem, was wir wollen, ist die Möglichkeit, ein JPEG oder ähnliches zu einer App hochzuladen, mit der Sie Kartenpositionen auf dem Bild angeben können (z. B. im Bildkarten-Punktnetz). Im Hintergrund wird eine SVG-Datei erstellt, die im Wesentlichen transparent ist . Wir möchten dann, dass die Karte auf die SVG angewendet wird und die SVG über der JPG im Webbrowser gerendert wird. Wenn der Browser die Größe des JPG ändert, wird auch die Größe des SVG geändert, und das SVG wird immer aufgerufen, wenn Sie auf die Imagemap klicken. Irgendwelche Vorschläge zu irgendeinem Teil davon?
youcantryreachingme

2
Ja, das wollte ich 2011
jdog

Antworten:


89

Für reaktionsschnelle Imagemaps benötigen Sie ein Plugin:

https://github.com/stowball/jQuery-rwdImageMaps (nicht mehr gepflegt)

Oder

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


Kein großer Browser versteht Prozentkoordinaten richtig und alle interpretieren Prozentkoordinaten als Pixelkoordinaten.

http://www.howtocreate.co.uk/tutorials/html/imagemaps

Und auch diese Seite zum Testen, ob Browser implementieren

http://home.comcast.net/~urbanjost/IMG/resizeimg3.html


5
ist irgendetwas davon noch relevant? Könnten Sie bitte ein Update bereitstellen?
Malachi

1
@ Malachi Ja, das ist immer noch relevant
Tom

Danke Tom, wir hatten eine Diskussion über eine Frage auf CodeReview, jetzt wünschte ich, ich könnte mich an die Frage erinnern ...
Malachi

@ Tom dies funktioniert nur für ein Bild .. wenn wir ein anderes Bild platzieren, dann funktioniert es nicht für das zweite und dritte Bild usw. ... überprüfen Sie es einfach ..
User2413

1
Ich habe ein Online-Generator-Tool gefunden, das SVGs verwendet, die alle gängigen Browser verstehen imagemapper.noc.io
frthjf

43

Sie können auch svg anstelle einer Imagemap verwenden. ;)

Es gibt ein Tutorial dazu.

.hover_group:hover {
  opacity: 1;
}
#projectsvg {
  position: relative;
  width: 100%;
  padding-bottom: 77%;
  vertical-align: middle;
  margin: 0;
  overflow: hidden;
}
#projectsvg svg {
  display: inline-block;
  position: absolute;
  top: 0;
  left: 0;
}
<figure id="projectsvg">
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1920 1080" preserveAspectRatio="xMinYMin meet" >
<!-- set your background image -->
<image width="1920" height="1080" xlink:href="http://placehold.it/1920x1080" />
<g class="hover_group" opacity="0">
  <a xlink:href="https://example.com/link1.html">
    <text x="652" y="706.9" font-size="20">First zone</text>
    <rect x="572" y="324.1" opacity="0.2" fill="#FFFFFF" width="264.6" height="387.8"></rect>
  </a>
</g>
<g class="hover_group" opacity="0">
  <a xlink:href="https://example.com/link2.html">
    <text x="1230.7" y="952" font-size="20">Second zone</text>
    <rect x="1081.7" y="507" opacity="0.2" fill="#FFFFFF" width="390.2" height="450"></rect>
  </a>
</g>
  </svg>
</figure>


1
Tutorial Link ist defekt. Das Bild von der jsfiddle auch.
Cristiano Maia

Ich habe signalisiert, dass der Tutorial-Link unterbrochen ist, und die jsfiddle- und Code-Snippets aktualisiert. Vielen Dank für das Heads-up
belgac

Dies ist eine erstaunliche Lösung. Ich habe es erfolgreich eingesetzt und funktioniert wie ein Zauber. Vielen Dank!
Jaume Mussons Abad

3
Mit Abstand die beste Lösung im Jahr 2020. Probieren Sie diesen Codegenerator aus, um es ganz einfach zu machen. imagemapper.noc.io/#
Brett Donald

1
Dies muss die beste reaktionsschnelle Lösung im Jahr 2020 sein.
mythicalcoder

39

1
Just and FYI for eveyrone ... Ich habe festgestellt, dass dies gut funktioniert, aber nicht in einem Akkordeon. Ich verwende Bootstrap 3 und wenn Sie die Seite nicht mit geöffnetem Akkordeon auf dem Bild laden, ist die Imagemap beim Öffnen des Akkordeons nur vorhanden, wenn die Größe des Browserfensters geändert wird.
Jasonflaherty

1
@jasonflaherty Könnten Sie ein Größenänderungsereignis auslösen, um die Anzeige der Karte zu erzwingen? $(window).trigger('resize');
Steve Meisner

@SteveMeisner Ich habe das nicht versucht ... aber würde das nicht eine Aktualisierung erzwingen?
Jasonflaherty

@ Jasonflaherty nein! Es "löst" nur das Größenänderungsereignis für das Element aus, das Sie binden ( windowin diesem Fall das). Viel Glück.
Steve Meisner


19

Ich bin auf eine Lösung gestoßen, die überhaupt keine Imagemaps verwendet, sondern Ankertags, die absolut über dem Bild positioniert sind. Der einzige Nachteil wäre, dass der Hotspot rechteckig sein müsste, aber das Plus ist, dass diese Lösung nicht auf Javascript basiert, sondern nur auf CSS. Es gibt eine Website, auf der Sie den HTML-Code für die Anker generieren können: http://www.zaneray.com/responsive-image-map/

Ich habe das Bild und die generierten Ankertags in ein relativ positioniertes div-Tag eingefügt und alles funktionierte perfekt bei der Fenstergröße und auf meinem Handy.


2
Schöner Fund! Vielen Dank für
Ihren

1
Ich kann diesen Naswer nicht genug bewerten !! Ein ausgezeichnetes Tutorial; umfassend und leicht zu verstehen. Man sollte alles lesen, aber von besonderem Interesse ist tutorials.jenkov.com/svg/scripting.html
Mawg sagt, Monica

Dies ist eine wirklich einfache und dennoch nette Lösung, wenn der zu klickende Bereich ein Rechteck ist.
user2875289

Das ist so toll. Arbeitete auch für mich mit einer DNN-Site. Wie Jeffrey sagte, habe ich gerade das <img> und das generierte HTML in einem relativ positionierten div abgelegt. Vielen Dank!
Ted Krapf

17

Ich habe einen No-JS-Weg gefunden, um dies zu beheben, wenn Sie mit rechteckigen Trefferbereichen einverstanden sind.

Stellen Sie zunächst sicher, dass sich Ihr Bild in einem Div befindet, der relativ positioniert ist. Fügen Sie dann das Bild in dieses Div ein, was bedeutet, dass es den gesamten Platz im Div einnimmt. Fügen Sie schließlich absolut positionierte Divs unter dem Bild innerhalb des Hauptdivs hinzu und verwenden Sie Prozentsätze für oben, links, Breite und Höhe, um den Link-Trefferbereichen die gewünschte Größe und Position zu geben.

Ich finde es am einfachsten, dem Div eine schwarze Hintergrundfarbe zu geben (idealerweise mit etwas Alpha-Fading, damit Sie den verknüpften Inhalt darunter sehen können), wenn Sie zum ersten Mal arbeiten, und einen Code-Inspektor in Ihrem Browser zu verwenden, um die Prozentsätze in Echtzeit anzupassen , damit Sie es genau richtig machen können.

Hier ist die Grundskizze, mit der Sie arbeiten können. Indem Sie alles mit Prozentsätzen ausführen, stellen Sie sicher, dass alle Elemente dieselbe relative Größe und Position wie das Bild haben.

<div style="position: relative;">
  <img src="background-image.png" style="width: 100%; height: auto;">
  <a href="/link1"><div style="position: absolute; left: 15%; top: 20%; width: 12%; height: 8%; background-color: rgba(0, 0, 0, .25);"></div></a>
  <a href="/link2"><div style="position: absolute; left: 52%; top: 38%; width: 14%; height: 20%; background-color: rgba(0, 0, 0, .25);"></div></a>
</div>

Verwenden Sie diesen Code mit Ihrem Codeinspektor in Chrome oder einem Browser Ihrer Wahl und passen Sie die Prozentsätze an (genauer gesagt können Sie Dezimalprozentsätze verwenden), bis die Felder genau richtig sind. Wählen Sie auch background-coloraus, transparentwann Sie es verwenden möchten, da Ihre Trefferbereiche unsichtbar sein sollen.


Dies ist eine großartige Lösung! Vielen Dank
Xims

Schöne Lösung! UIkit verwendet die gleiche Technik für ihre Marker: getuikit.com/docs/marker
xela84

Geniale Lösung, danke fürs Teilen! Ich verwende dies in einer mobilen App und es löst das Problem der verschiedenen Bildschirme.
JohnGIS


7

Die folgende Methode funktioniert perfekt für mich. Hier ist meine vollständige Implementierung:

<img id="my_image" style="display: none;" src="my.png" width="924" height="330" border="0" usemap="#map" />

<map name="map" id="map">
    <area shape="poly" coords="774,49,810,21,922,130,920,222,894,212,885,156,874,146" href="#mylink" />
    <area shape="poly" coords="649,20,791,157,805,160,809,217,851,214,847,135,709,1,666,3" href="#myotherlink" />
</map>

<script>
$(function(){
    var image_is_loaded = false;
    $("#my_image").on('load',function() {
        $(this).data('width', $(this).attr('width')).data('height', $(this).attr('height'));
        $($(this).attr('usemap')+" area").each(function(){
            $(this).data('coords', $(this).attr('coords'));
        });

        $(this).css('width', '100%').css('height','auto').show();

        image_is_loaded = true;
        $(window).trigger('resize');
    });


    function ratioCoords (coords, ratio) {
        coord_arr = coords.split(",");

        for(i=0; i < coord_arr.length; i++) {
            coord_arr[i] = Math.round(ratio * coord_arr[i]);
        }

        return coord_arr.join(',');
    }
    $(window).on('resize', function(){
        if (image_is_loaded) {
            var img = $("#my_image");
            var ratio = img.width()/img.data('width');

            $(img.attr('usemap')+" area").each(function(){
                console.log('1: '+$(this).attr('coords'));
                $(this).attr('coords', ratioCoords($(this).data('coords'), ratio));
            });
        }
    });
});
</script>

4

Arbeiten für mich (denken Sie daran, 3 Dinge im Code zu ändern):

  • vorherige Breite (Originalgröße des Bildes)

  • map_ID (ID Ihrer Imagemap)

  • img_ID (ID Ihres Bildes)

HTML:

<div style="width:100%;">
    <img id="img_ID" src="http://www.gravatar.com/avatar/0865e7bad648eab23c7d4a843144de48?s=128&d=identicon&r=PG" usemap="#map" border="0" width="100%" alt="" />
</div>
<map id="map_ID" name="map">
<area shape="poly" coords="48,10,80,10,65,42" href="javascript:;" alt="Bandcamp" title="Bandcamp" />
<area shape="poly" coords="30,50,62,50,46,82" href="javascript:;" alt="Facebook" title="Facebook" />
<area shape="poly" coords="66,50,98,50,82,82" href="javascript:;" alt="Soundcloud" title="Soundcloud" />
</map>

Javascript:

window.onload = function () {
    var ImageMap = function (map, img) {
            var n,
                areas = map.getElementsByTagName('area'),
                len = areas.length,
                coords = [],
                previousWidth = 128;
            for (n = 0; n < len; n++) {
                coords[n] = areas[n].coords.split(',');
            }
            this.resize = function () {
                var n, m, clen,
                    x = img.offsetWidth / 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 = img.offsetWidth;
                return true;
            };
            window.onresize = this.resize;
        },
        imageMap = new ImageMap(document.getElementById('map_ID'), document.getElementById('img_ID'));
    imageMap.resize();
    return;
}

JSFiddle: http://jsfiddle.net/p7EyT/154/


3

Ich stoße auf die gleiche Anforderung, bei der ich eine reaktionsschnelle Imagemap anzeigen möchte, deren Größe sich mit jeder Bildschirmgröße ändern lässt. Wichtig ist, dass ich diese Koordinaten hervorheben möchte .

Also habe ich viele Bibliotheken ausprobiert, deren Größe die Koordinaten je nach Bildschirmgröße und Ereignis ändern kann. Und ich habe die beste Lösung (jquery.imagemapster.min.js), die mit fast allen Browsern gut funktioniert. Außerdem habe ich es in Summer Plgin integriert, die eine Imagemap erstellen.

 var resizeTime = 100;
 var resizeDelay = 100;    

$('img').mapster({
        areas: [
            {
                key: 'tbl',
                fillColor: 'ff0000',
                staticState: true,
                stroke: true
            }
        ],
        mapKey: 'state'
    });

    // Resize the map to fit within the boundaries provided

    function resize(maxWidth, maxHeight) {
        var image = $('img'),
            imgWidth = image.width(),
            imgHeight = image.height(),
            newWidth = 0,
            newHeight = 0;

        if (imgWidth / maxWidth > imgHeight / maxHeight) {
            newWidth = maxWidth;
        } else {
            newHeight = maxHeight;
        }
        image.mapster('resize', newWidth, newHeight, resizeTime);
    }

    function onWindowResize() {

        var curWidth = $(window).width(),
            curHeight = $(window).height(),
            checking = false;
        if (checking) {
            return;
        }
        checking = true;
        window.setTimeout(function () {
            var newWidth = $(window).width(),
                newHeight = $(window).height();
            if (newWidth === curWidth &&
                newHeight === curHeight) {
                resize(newWidth, newHeight);
            }
            checking = false;
        }, resizeDelay);
    }

    $(window).bind('resize', onWindowResize);
img[usemap] {
        border: none;
        height: auto;
        max-width: 100%;
        width: auto;
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<script src="https://cdn.jsdelivr.net/npm/jquery-imagemapster@1.2.10/dist/jquery.imagemapster.min.js"></script>

<img src="https://discover.luxury/wp-content/uploads/2016/11/Cities-With-the-Most-Michelin-Star-Restaurants-1024x581.jpg" alt="" usemap="#map" />
<map name="map">
    <area shape="poly" coords="777, 219, 707, 309, 750, 395, 847, 431, 916, 378, 923, 295, 870, 220" href="#" alt="poly" title="Polygon" data-maphilight='' state="tbl"/>
    <area shape="circle" coords="548, 317, 72" href="#" alt="circle" title="Circle" data-maphilight='' state="tbl"/>
    <area shape="rect" coords="182, 283, 398, 385" href="#" alt="rect" title="Rectangle" data-maphilight='' state="tbl"/>
</map>

Hoffe es jemandem helfen.


2

http://home.comcast.net/~urbanjost/semaphore.html ist die oberste Seite der Diskussion und enthält Links zu einer JavaScript-basierten Lösung des Problems. Ich habe eine Mitteilung erhalten, dass HTML in Zukunft prozentuale Einheiten unterstützen wird, aber ich habe seit einiger Zeit keine Fortschritte mehr gesehen (es ist wahrscheinlich über ein Jahr her, seit ich gehört habe, dass Unterstützung bevorsteht), also ist die Problemumgehung wahrscheinlich einen Blick wert, wenn Sie mit JavaScript / ECMAScript vertraut sind.


2

Schauen Sie sich das Image-Map- Plugin auf Github an. Es funktioniert sowohl mit Vanilla JavaScript als auch als jQuery-Plugin.

$('img[usemap]').imageMap();     // jQuery

ImageMap('img[usemap]')          // JavaScript

Schauen Sie sich die Demo an .


1

Es kommt darauf an, dass Sie jQuery verwenden können, um die Bereiche proportional anzupassen, denke ich. Warum benutzt du übrigens eine Imagemap? Können Sie keine skalierenden Divs oder andere Elemente dafür verwenden?


Während die genaue Lösung mit skalierten Divs funktionieren würde, ist die Imagemap "inhaltsverwaltet" und erlaubt jede Art von Region. Danke, ich werde jquery dafür überprüfen.
JDOG

1

Für diejenigen, die nicht auf JavaScript zurückgreifen möchten, ist hier ein Beispiel für das Schneiden von Bildern:

http://codepen.io/anon/pen/cbzrK

Wenn Sie das Fenster skalieren, wird das Clownbild entsprechend skaliert, und wenn dies der Fall ist, bleibt die Nase des Clowns mit einem Hyperlink verbunden.


2
Danke für die Albträume!
Jerrygarciuh

1
Bildlinks sind alle defekt.
Tyler Forsythe

0

Ähnlich wie Orland's Antwort hier: https://stackoverflow.com/a/32870380/462781

Kombiniert mit Chris 'Code hier: https://stackoverflow.com/a/12121309/462781

Wenn die Bereiche in ein Raster passen, können Sie die Bereiche mit transparenten Bildern überlagern, wobei eine Breite in% verwendet wird, die das Seitenverhältnis beibehält.

    .wrapperspace {
      width: 100%;
      display: inline-block;
      position: relative;
    }
    .mainspace {
      position: absolute;
      top: 0;
      bottom: 0;
      right: 0;
      left: 0;
    }
<div class="wrapperspace">
 <img style="float: left;" title="" src="background-image.png" width="100%" />
 <div class="mainspace">
     <div>
         <img src="space-top.png" style="margin-left:6%;width:15%;"/>
     </div>
     <div>
       <a href="http://www.example.com"><img src="space-company.png" style="margin-left:6%;width:15%;"></a>
     </div>
  <div>
   <a href="http://www.example.com"><img src="space-company.png" style="margin-left:6%;width:10%;"></a>
   <a href="http://www.example.com"><img src="space-company.png" style="width:20%;"></a>
  </div>
 </div>
</div>

Sie können eine Marge in% verwenden. Zusätzlich können "Space" -Bilder in einem Div der 3. Ebene nebeneinander platziert werden.


0

Aus irgendeinem Grund hat keine dieser Lösungen für mich funktioniert. Ich hatte den besten Erfolg mit Transformationen.

transform: translateX(-5.8%) translateY(-5%) scale(0.884);

0

Reaktionsbreite && Höhe

window.onload = function () {
        var ImageMap = function (map, img) {
                var n,
                    areas = map.getElementsByTagName('area'),
                    len = areas.length,
                    coords = [],
                    imgWidth = img.naturalWidth,
                    imgHeight = img.naturalHeight;
                for (n = 0; n < len; n++) {
                    coords[n] = areas[n].coords.split(',');
                }
            this.resize = function () {
                var n, m, clen,
                    x = img.offsetWidth / imgWidth,
                    y = img.offsetHeight / imgHeight;
                    imgWidth = img.offsetWidth;
                    imgHeight = img.offsetHeight;
                for (n = 0; n < len; n++) {
                    clen = coords[n].length;
                    for (m = 0; m < clen; m +=2) {
                        coords[n][m] *= x;
                        coords[n][m+1] *= y;
                    }
                    areas[n].coords = coords[n].join(',');
                }
                    return true;
                };
                window.onresize = this.resize;
            },
        imageMap = new ImageMap(document.getElementById('map_region'), document.getElementById('prepay_region'));
        imageMap.resize();
        return;
    }

Können Sie weitere Inhalte hinzufügen, die die Unterschiede zwischen Ihrem Code und der Antwort von Niente0 aus dem Jahr 2015 zeigen?
Michael - Wo ist Clay Shirky
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.