Carte d'image réactive


145

J'ai une image map existante dans une mise en page html réactive. Les images sont mises à l'échelle en fonction de la taille du navigateur, mais les coordonnées de l'image sont évidemment des tailles de pixels fixes. Quelles options ai-je pour redimensionner les coordonnées de la carte image?


6
Cette question ne concerne pas une carte géographique mais la balise html <map>
jdog

4
Découvrez le plugin image-map . Cela fonctionne avec Javascript, Node et jQuery
Travis Clarke

2
Comme alternative, vous pouvez utiliser une image SVG. Je recommande de lire Utiliser SVG comme alternative à Imagemaps
Mawg dit de réintégrer Monica

1
On dirait que ce que nous voulons, c'est la possibilité de télécharger un fichier JPEG ou similaire à une application qui vous permet de spécifier les emplacements de la carte sur l'image (comme à l'image-map dot net) - en arrière-plan, cela produit un fichier SVG qui est essentiellement transparent . Nous voulons ensuite que la carte s'applique au SVG et rende le SVG au-dessus du JPG dans le navigateur Web. Lorsque le navigateur redimensionne le JPG, le SVG est également redimensionné et le SVG est toujours celui qui est invoqué lorsque vous cliquez sur la carte image. Avez-vous des suggestions sur l'un ou l'autre de ces éléments?
youcantryreachingme

2
Oui c'est ce que je voulais en 2011
jdog

Réponses:


90

Pour les cartes d'images réactives, vous devrez utiliser un plugin:

https://github.com/stowball/jQuery-rwdImageMaps (n'est plus maintenu)

Ou

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


Aucun navigateur majeur ne comprend correctement les coordonnées de pourcentage, et tous interprètent les coordonnées de pourcentage comme des coordonnées de pixel.

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

Et aussi cette page pour tester si les navigateurs implémentent

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


5
est-ce que tout cela est toujours pertinent? pourriez-vous fournir une mise à jour s'il vous plaît?
Malachi

1
@Malachi Oui, c'est toujours d'actualité
Tom

merci Tom, nous avions une discussion sur une question sur CodeReview, maintenant j'aimerais pouvoir me souvenir de la question ....
Malachi

Cela ne fonctionne que @ Tom pour un image..if nous plaçons une autre image alors son ne fonctionne pas pour la deuxième et troisième image etc ... il suffit de vérifier ..
User2413

1
J'ai trouvé un outil générateur en ligne qui utilise des SVG que tous les principaux navigateurs comprennent imagemapper.noc.io
frthjf

43

Vous pouvez également utiliser svg au lieu d'une image map. ;)

Il existe un didacticiel expliquant comment procéder.

.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
Le lien du didacticiel est rompu. L'image du jsfiddle également.
Cristiano Maia

J'ai signalé que le lien du didacticiel était rompu et j'ai mis à jour les extraits de code et jsfiddle. Merci pour la mise en
garde

C'est une solution incroyable. Je l'ai utilisé avec succès et fonctionne comme un charme. Merci!
Jaume Mussons Abad

3
De loin la meilleure solution en 2020. Essayez ce générateur de code pour le rendre super simple. imagemapper.noc.io/#
Brett Donald

1
Cela doit être la meilleure solution réactive en 2020.
mythicalcoder

39

1
Juste et FYI pour eveyrone ... J'ai trouvé que cela fonctionne bien, mais pas à l'intérieur d'un accordéon. J'utilise Bootstrap 3 et si vous ne chargez pas la page avec l'accordéon ouvert sur l'image, lorsque vous ouvrez l'accordéon, l'image map n'est pas là à moins que la fenêtre du navigateur ne soit redimensionnée.
jasonflaherty

1
@jasonflaherty pourriez-vous déclencher un événement de redimensionnement pour forcer l'affichage de la carte? $(window).trigger('resize');
Steve Meisner

@SteveMeisner Je n'ai pas essayé ça ... mais cela ne forcerait-il pas un rafraîchissement?
jasonflaherty

@jasonflaherty non! Il "déclenche" simplement l'événement de redimensionnement sur l'élément que vous liez (le windowdans ce cas). Bonne chance.
Steve Meisner

Je viens de créer le module Drupal super basique mais pratique en utilisant ce plugin: drupal.org/project/responsive_imagemaps
Joshua Stewards le

19

J'ai rencontré une solution qui n'utilise pas du tout de cartes d'image, mais plutôt des balises d'ancrage qui sont absolument positionnées sur l'image. Le seul inconvénient serait que le hotspot devrait être rectangulaire, mais le plus est que cette solution ne repose pas sur Javascript, juste CSS. Il existe un site Web que vous pouvez utiliser pour générer le code HTML des ancres: http://www.zaneray.com/responsive-image-map/

J'ai mis l'image et les balises d'ancrage générées dans une balise div relativement positionnée et tout a parfaitement fonctionné sur le redimensionnement de la fenêtre et sur mon téléphone portable.


2
Bonne trouvaille! Merci d'avoir contribué à cette liste
jdog

1
Je ne peux pas assez voter pour ce naswer !! Un excellent tutoriel; complet et facile à comprendre. On devrait tout lire, mais un intérêt particulier est tutorials.jenkov.com/svg/scripting.html
Mawg dit de réintégrer Monica le

C'est une solution vraiment simple mais agréable si la zone sur laquelle cliquer est un rectangle.
user2875289

C'est tellement génial. A travaillé pour moi aussi avec un site DNN. Comme Jeffrey l'a déclaré, j'ai simplement déposé le <img> et le html généré à l'intérieur d'un div positionné relatif. Merci!
Ted Krapf

18

J'ai trouvé un moyen non-JS de résoudre ce problème si vous êtes d'accord avec les zones de frappe rectangulaires.

Tout d'abord, assurez-vous que votre image est dans un div qui est relativement positionné. Ensuite, placez l'image dans ce div, ce qui signifie qu'il occupera tout l'espace du div. Enfin, ajoutez des div positionnés de manière absolue sous l'image, dans le div principal, et utilisez des pourcentages pour le haut, la gauche, la largeur et la hauteur pour obtenir la taille et la position souhaitées des zones d'accès au lien.

Je trouve qu'il est plus facile de donner à la div une couleur d'arrière-plan noire (idéalement avec un peu de fondu alpha pour que vous puissiez voir le contenu lié en dessous) lorsque vous travaillez pour la première fois, et d'utiliser un inspecteur de code dans votre navigateur pour ajuster les pourcentages en temps réel , afin que vous puissiez faire les choses correctement.

Voici le plan de base avec lequel vous pouvez travailler. En faisant tout avec des pourcentages, vous vous assurez que tous les éléments conservent la même taille et la même position relatives que l'image est mise à l'échelle.

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

Utilisez ce code avec votre inspecteur de code dans Chrome ou le navigateur de votre choix, et ajustez les pourcentages (vous pouvez utiliser des pourcentages décimaux pour être plus précis) jusqu'à ce que les cases soient parfaites. Vous pouvez aussi choisir un background-colordes transparentlorsque vous êtes prêt à l' utiliser puisque vous voulez que vos zones touchées soient invisibles.


C'est une excellente solution! Merci
xims

Belle solution! UIkit utilise la même technique pour ses marqueurs: getuikit.com/docs/marker
xela84

Solution géniale, merci pour le partage! J'utilise cela dans une application mobile et cela résout le problème des différents écrans.
JohnGIS


7

La méthode suivante fonctionne parfaitement pour moi, voici donc ma mise en œuvre complète:

<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

Travailler pour moi (n'oubliez pas de changer 3 choses dans le code):

  • previousWidth (taille originale de l'image)

  • map_ID (identifiant de votre image map)

  • img_ID (identifiant de votre image)

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

Je rencontre la même exigence où, je veux montrer une carte d'image réactive qui peut être redimensionnée avec n'importe quelle taille d'écran et la chose importante est, je veux mettre en évidence ces coordonnées .

J'ai donc essayé de nombreuses bibliothèques qui peuvent redimensionner les coordonnées en fonction de la taille de l'écran et de l'événement. Et j'ai la meilleure solution (jquery.imagemapster.min.js) qui fonctionne très bien avec presque tous les navigateurs. Aussi je l'ai intégré avec Summer Plgin qui crée une image map.

 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>

J'espère aider quelqu'un.


2

http://home.comcast.net/~urbanjost/semaphore.html est la première page de la discussion, et contient en fait des liens vers une solution JavaScript au problème. J'ai reçu un avis indiquant que HTML prendra en charge les unités de pourcentage à l'avenir, mais je n'ai vu aucun progrès à ce sujet depuis un certain temps (cela fait probablement plus d'un an que j'ai entendu dire que le soutien serait à venir), donc la solution de contournement est Cela vaut probablement la peine de regarder si vous êtes à l'aise avec JavaScript / ECMAScript.


2

Découvrez le plugin image-map sur Github. Il fonctionne à la fois avec JavaScript vanilla et en tant que plugin jQuery.

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

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

Regardez la démo .


1

Cela dépend, vous pouvez utiliser jQuery pour ajuster les plages proportionnellement je pense. Pourquoi utilisez-vous une carte image au fait? Ne pouvez-vous pas utiliser des divs de mise à l'échelle ou d'autres éléments pour cela?


alors que la solution exacte fonctionnerait avec des div mis à l'échelle, la carte image est "gérée par le contenu" et permet tout type de région. Merci, je vais vérifier jquery pour cela.
jdog

1

Pour ceux qui ne souhaitent pas recourir à JavaScript, voici un exemple de découpage d'image:

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

Lorsque vous mettez à l'échelle la fenêtre, l'image du clown sera mise à l'échelle en conséquence, et quand c'est le cas, le nez du clown reste hyperlié.


2
Merci pour les cauchemars!
jerrygarciuh

1
Les liens d'image sont tous rompus.
Tyler Forsythe

0

Similaire à la réponse d'Orland ici: https://stackoverflow.com/a/32870380/462781

Combiné avec le code de Chris ici: https://stackoverflow.com/a/12121309/462781

Si les zones s'inscrivent dans une grille, vous pouvez superposer les zones par des images transparentes en utilisant une largeur en% qui conserve leur rapport hauteur / largeur.

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

Vous pouvez utiliser une marge en%. De plus, les images «espace» peuvent être placées les unes à côté des autres à l'intérieur d'un div de 3e niveau.


0

Pour une raison quelconque, aucune de ces solutions n'a fonctionné pour moi. J'ai eu le meilleur succès avec les transformations.

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

0

largeur et hauteur sensibles

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

Pouvez-vous ajouter plus de contenu montrant les différences entre votre code et la réponse de Niente0 de 2015?
Michael - Where's Clay Shirky
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.