Mappa immagine reattiva


145

Ho una mappa immagine esistente in un layout html reattivo. Le immagini vengono ridimensionate in base alle dimensioni del browser, ma le coordinate dell'immagine sono ovviamente di dimensioni pixel fisse. Quali opzioni devo ridimensionare le coordinate della mappa immagine?


6
Questa domanda non riguarda una mappa geografica ma il tag <map> html
jdog

4
Dai un'occhiata al plug -in della mappa immagine . Funziona con Javascript, Node e jQuery
Travis Clarke,

2
In alternativa, è possibile utilizzare un'immagine SVG. Consiglio di leggere Usare SVG come alternativa alle mappe immagine
Mawg dice di ripristinare Monica il

1
Sembra che ciò che vogliamo sia la possibilità di caricare un file JPEG o simile a un'app che ti consenta di specificare le posizioni delle mappe sull'immagine (come ad esempio nella mappa di punti immagine-mappa) - sullo sfondo, questo produce un file SVG che è essenzialmente trasparente . Vogliamo quindi applicare la mappa all'SVG e renderizzare l'SVG sopra lo JPG nel browser web. Quando il browser ridimensiona il JPG, anche l'SVG viene ridimensionato e l'SVG è sempre quello invocato quando si fa clic sulla mappa dell'immagine. Qualche suggerimento su una qualsiasi delle parti di questo?
youcantryreachingme,

2
Sì, è quello che volevo nel 2011
jdog,

Risposte:


89

Per mappe di immagini reattive dovrai usare un plugin:

https://github.com/stowball/jQuery-rwdImageMaps (Non più mantenuto)

O

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


Nessun browser principale comprende correttamente le coordinate percentuali e tutte interpretano le coordinate percentuali come coordinate pixel.

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

E anche questa pagina per verificare se i browser implementano

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


5
c'è ancora qualcosa di rilevante in questo? potresti fornire un aggiornamento per favore?
Malachi,

1
@Malachi Sì, questo è ancora rilevante
Tom

grazie Tom, stavamo discutendo su una domanda su CodeReview, ora vorrei ricordare la domanda ....
Malachi

@Tom funziona solo per un'immagine..se inseriamo un'altra immagine, quindi non funziona per la seconda e terza immagine ecc ... basta controllarla ..
User2413

1
Ho trovato uno strumento di generazione online che utilizza SVG che tutti i principali browser comprendono imagemapper.noc.io
frthjf

43

Puoi anche usare svg invece di una mappa immagine. ;)

C'è un tutorial su come farlo.

.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
Il collegamento al tutorial è rotto. L'immagine anche dal jsfiddle.
Cristiano Maia,

Ho segnalato che il collegamento al tutorial era rotto e ho aggiornato jsfiddle e i frammenti di codice. Grazie per il testa a testa
belgac

Questa è una soluzione straordinaria. L'ho usato con successo e funziona come un fascino. Grazie!
Jaume Mussons Abad,

3
Di gran lunga la migliore soluzione nel 2020. Prova questo generatore di codice per renderlo super semplice. imagemapper.noc.io/#
Brett Donald

1
Questa deve essere la migliore soluzione reattiva nel 2020.
miticalcoder il

39

1
Proprio e FYI per eveyrone ... Ho scoperto che funziona bene, ma non all'interno di una fisarmonica. Sto usando Bootstrap 3 e se non carichi la pagina con la fisarmonica aperta sull'immagine, quando apri la fisarmonica, la mappa dell'immagine non è presente a meno che la finestra del browser non venga ridimensionata.
jasonflaherty,

1
@jasonflaherty potresti attivare un evento di ridimensionamento per forzare la visualizzazione della mappa? $(window).trigger('resize');
Steve Meisner,

@SteveMeisner Non l'ho provato ... ma non forzerebbe un aggiornamento?
jasonflaherty,

@jasonflaherty no! Semplicemente "innesca" l'evento di ridimensionamento sull'elemento associato ( windowin questo caso). In bocca al lupo.
Steve Meisner,

Ho appena creato il modulo Drupal super semplice ma utile usando questo plugin: drupal.org/project/responsive_imagemaps
Joshua Stewardson,

19

Mi sono imbattuto in una soluzione che non utilizza affatto mappe di immagini ma piuttosto tag di ancoraggio che sono assolutamente posizionati sull'immagine. L'unico inconveniente sarebbe che l'hotspot avrebbe dovuto essere rettangolare, ma il vantaggio è che questa soluzione non si basa su Javascript, ma solo su CSS. Esiste un sito Web che è possibile utilizzare per generare il codice HTML per le ancore: http://www.zaneray.com/responsive-image-map/

Ho messo l'immagine e i tag di ancoraggio generati in un tag div relativamente posizionato e tutto ha funzionato perfettamente sul ridimensionamento della finestra e sul mio telefono cellulare.


2
Bella scoperta! Grazie per aver contribuito a questo elenco
jdog

1
Non posso votare abbastanza questo naswer !! Un eccellente tutorial; completo e facile da capire. Bisogna leggere tutto, ma di particolare interesse è tutorials.jenkov.com/svg/scripting.html
Mawg dice di ripristinare Monica il

Questa è una soluzione davvero semplice ma piacevole se l'area da fare clic è rettangolare.
user2875289

Questo è fantastico. Ha funzionato anche per me con un sito DNN. Come ha affermato Jeffrey, ho appena lasciato cadere <img> e l'html generato all'interno di un div posizionato relativo. Grazie!
Ted Krapf,

18

Ho trovato un modo no-JS per risolvere questo problema se stai bene con le aree dei colpi rettangolari.

Prima di tutto, assicurati che la tua immagine sia in un div che sia relativamente posizionato. Quindi metti l'immagine all'interno di questo div, il che significa che occuperà tutto lo spazio nel div. Infine, aggiungi i div assolutamente posizionati sotto l'immagine, all'interno del div principale, e usa le percentuali per la parte superiore, sinistra, larghezza e altezza per ottenere le aree colpite dal collegamento delle dimensioni e della posizione desiderate.

Trovo che sia più facile dare al div un colore di sfondo nero (idealmente con qualche dissolvenza alfa in modo da poter vedere il contenuto collegato sotto) quando stai lavorando per la prima volta, e usare un programma di ispezione del codice nel tuo browser per regolare le percentuali in tempo reale , in modo da poterlo ottenere nel modo giusto.

Ecco la struttura di base con cui puoi lavorare. Facendo tutto con le percentuali, si assicura che tutti gli elementi mantengano la stessa dimensione e posizione relativa delle scale dell'immagine.

<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>

Usa questo codice con la tua finestra di ispezione del codice in Chrome o il tuo browser preferito e regola le percentuali (puoi usare le percentuali decimali per essere più esatte) fino a quando le caselle sono giuste. Scegli anche background-colordi transparentquando sei pronto per usarlo poiché vuoi che le tue aree colpite siano invisibili.


Questa è un'ottima soluzione! Grazie
xims

Bella soluzione! UIkit utilizza la stessa tecnica per i propri marker: getuikit.com/docs/marker
xela84

Soluzione brillante, grazie per la condivisione! Lo sto usando in un'app mobile e risolve il problema di schermi diversi.
JohnGIS,


7

Il seguente metodo funziona perfettamente per me, quindi ecco la mia piena implementazione:

<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

Lavorando per me (ricordati di cambiare 3 cose nel codice):

  • previousWidth (dimensione originale dell'immagine)

  • map_ID (ID della mappa immagine)

  • img_ID (id della tua immagine)

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

Mi imbatto con lo stesso requisito in cui, voglio mostrare una mappa immagine reattiva che può ridimensionare con qualsiasi dimensione dello schermo e cosa importante è, voglio evidenziare quelle coordinate .

Quindi ho provato molte librerie che possono ridimensionare le coordinate in base alle dimensioni dello schermo e all'evento. E ho ottenuto la migliore soluzione (jquery.imagemapster.min.js) che funziona bene con quasi tutti i browser. Inoltre l'ho integrato con Summer Plgin che crea una mappa immagine.

 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>

Spero di aiutarlo a qualcuno.


2

http://home.comcast.net/~urbanjost/semaphore.html è la pagina principale per la discussione e in realtà ha collegamenti a una soluzione basata su JavaScript al problema. Ho ricevuto un avviso che HTML supporterà le unità percentuali in futuro, ma non ho visto alcun progresso su questo da un po 'di tempo (probabilmente è passato più di un anno da quando ho sentito che il supporto sarebbe imminente) quindi il work-around è probabilmente vale la pena dare un'occhiata se sei a tuo agio con JavaScript / ECMAScript.


2

Dai un'occhiata al plug -in della mappa immagine su Github. Funziona sia con JavaScript vanilla che come plugin jQuery.

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

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

Guarda la demo .


1

Dipende, puoi usare jQuery per regolare gli intervalli in modo proporzionale, penso. Perché usi una mappa immagine tra l'altro? Non puoi usare div di ridimensionamento o altri elementi per questo?


mentre la soluzione esatta funzionerebbe con div ridimensionati, la mappa immagine è "gestita dal contenuto" e consente qualsiasi tipo di regione. Grazie, controllerò jquery per questo.
jog

1

Per coloro che non vogliono ricorrere a JavaScript, ecco un esempio di suddivisione delle immagini:

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

Man mano che si ridimensiona la finestra, l'immagine del clown si ridimensiona di conseguenza e, quando lo fa, il naso del clown rimane ipertestuale.


2
Grazie per gli incubi!
jerrygarciuh,

1
I collegamenti alle immagini sono tutti rotti.
Tyler Forsythe,

0

Simile alla risposta di Orland qui: https://stackoverflow.com/a/32870380/462781

Combinato con il codice di Chris qui: https://stackoverflow.com/a/12121309/462781

Se le aree si adattano a una griglia, è possibile sovrapporre le aree con immagini trasparenti utilizzando una larghezza in% che mantenga le proporzioni.

    .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>

È possibile utilizzare un margine in%. Inoltre, le immagini "spaziali" possono essere posizionate una accanto all'altra all'interno di un div di terzo livello.


0

Per qualche motivo nessuna di queste soluzioni ha funzionato per me. Ho avuto il miglior successo usando le trasformazioni.

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

0

larghezza reattiva && altezza

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;
    }

Puoi aggiungere altri contenuti che mostrano le differenze tra il tuo codice e la risposta di Niente0 del 2015?
Michael - Dov'è Clay Shirky il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.