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?

jdog
la source
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

À M
la source
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>

belgac
la source
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

Plugin jQuery pour images réactives par Matt Stow

Joshua Stewardson
la source
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.

Jeffrey Langham
la source
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.

Tom Bisciglia
la source
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
11

David Bradshaw a écrit une jolie petite bibliothèque qui résout ce problème. Il peut être utilisé avec ou sans jQuery.

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

Grodriguez
la source
Confirmé pour travailler dans les dernières versions de Chrome / IE / FF à partir de ce commentaire.
James Paterson
1
Fonctionne très bien pour moi, interface super simple aussi
Brian
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>
chimeraha
la source
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/

Niente0
la source
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/[email protected]/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.

Rahul Mahadik
la source
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.

John Urban
la source
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 .

Travis Clarke
la source
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?

Reinier Kaper
la source
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é.

Johnny Oshika
la source
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.

Pete
la source
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);
Mike Furlender
la source
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;
    }
Валерий Стасюк
la source
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