Mapa de imagen sensible

145

Tengo un mapa de imagen existente en un diseño html receptivo. Las imágenes se escalan de acuerdo con el tamaño del navegador, pero las coordenadas de la imagen son obviamente tamaños fijos de píxeles. ¿Qué opciones tengo para cambiar el tamaño de las coordenadas del mapa de imagen?

jdog
fuente
66
Esta pregunta no se trata de un mapa geográfico sino de la etiqueta <map> html
jdog
44
Echa un vistazo al complemento de imagen-mapa . Funciona con Javascript, Node y jQuery
Travis Clarke
2
Como alternativa, puede usar una imagen SVG. Recomiendo leer Uso de SVG como una alternativa a los
mapas de imágenes
1
Parece que lo que queremos es la capacidad de cargar un archivo JPEG o similar a una aplicación que le permite especificar ubicaciones de mapa en la imagen (como en la imagen-mapa dot net) - en el fondo, esto produce un archivo SVG que es esencialmente transparente . Luego, queremos que el mapa se aplique al SVG y que represente el SVG encima del JPG en el navegador web. A medida que el navegador cambia el tamaño del JPG, el SVG también cambia su tamaño y el SVG es siempre el que se invoca al hacer clic en el mapa de imagen. ¿Alguna sugerencia sobre alguna de las partes de esto?
youcantryreachingme
2
Sí, eso es lo que quería en 2011
jdog

Respuestas:

89

Para mapas de imagen receptivos, necesitará usar un complemento:

https://github.com/stowball/jQuery-rwdImageMaps (ya no se mantiene)

O

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


Ningún navegador importante comprende correctamente las coordenadas de porcentaje, y todas interpretan las coordenadas de porcentaje como coordenadas de píxeles.

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

Y también esta página para probar si los navegadores implementan

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

Tom
fuente
55
¿Algo de esto sigue siendo relevante? ¿podría proporcionar una actualización por favor?
Malaquías el
1
@Malachi Sí, esto sigue siendo relevante
Tom
gracias Tom, estábamos discutiendo una pregunta sobre CodeReview, ahora desearía poder recordar la pregunta ...
Malachi
@ Tom esto sólo funciona para un image..if colocamos otra imagen, entonces no es de trabajo para el segundo y tercer imagen etc ... Sólo echa un ..
User2413
1
He encontrado una herramienta en línea que utiliza generador de IVS, que todos los principales navegador entienden imagemapper.noc.io
frthjf
43

También puede usar svg en lugar de un mapa de imagen. ;)

Hay un tutorial sobre cómo hacer esto.

.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
fuente
1
El enlace del tutorial está roto. La imagen del jsfiddle también.
Cristiano Maia
Señalé que el enlace del tutorial estaba roto y actualicé los fragmentos de código y jsfiddle. Gracias por el
aviso
Esta es una solución asombrosa. Lo he usado con éxito y funciona de maravilla. ¡Gracias!
Jaume Mussons Abad el
3
Con mucho, la mejor solución en 2020. Pruebe este generador de código para hacerlo súper simple. imagemapper.noc.io/#
Brett Donald
1
Esta tiene que ser la mejor solución de respuesta en 2020.
mythicalcoder
39

Responsive Image Maps jQuery Plugin por Matt Stow

Joshua Stewardson
fuente
1
Solo y para tu información para eveyrone ... He descubierto que esto funciona bien, pero no dentro de un acordeón. Estoy usando Bootstrap 3 y si no carga la página con el acordeón abierto en la imagen, cuando abre el acordeón, el mapa de la imagen no está allí a menos que se cambie el tamaño de la ventana del navegador.
jasonflaherty
1
@jasonflaherty, ¿podría activar un evento de cambio de tamaño para forzar que se muestre el mapa? $(window).trigger('resize');
Steve Meisner
@SteveMeisner No lo he intentado ... ¿pero eso no forzaría una actualización?
jasonflaherty
@jasonflaherty no! Simplemente "activa" el evento de cambio de tamaño en el elemento que vincula (el windowen este caso). Buena suerte.
Steve Meisner
Acabo de crear el módulo Drupal súper básico pero práctico utilizando este complemento: drupal.org/project/responsive_imagemaps
Joshua Stewardson
19

Me encontré con una solución que no usa mapas de imágenes en absoluto, sino etiquetas de anclaje que están absolutamente posicionadas sobre la imagen. El único inconveniente sería que el punto de acceso tendría que ser rectangular, pero la ventaja es que esta solución no se basa en Javascript, solo en CSS. Hay un sitio web que puede usar para generar el código HTML para las anclas: http://www.zaneray.com/responsive-image-map/

Puse la imagen y las etiquetas de anclaje generadas en una etiqueta div relativamente posicionada y todo funcionó perfectamente en el cambio de tamaño de la ventana y en mi teléfono móvil.

Jeffrey Langham
fuente
2
Buen hallazgo! Gracias por contribuir a esta lista
jdog
1
¡No puedo votar lo suficiente más rápido! Un excelente tutorial; Completo y fácil de entender. Uno debería leerlo todo, pero de particular interés es tutorials.jenkov.com/svg/scripting.html
Mawg dice que reinstale a Monica
Esta es una solución realmente simple pero agradable si el área a hacer clic es rectángulo.
user2875289
Esto es genial También funcionó para mí con un sitio de DNN. Como dijo Jeffrey, acabo de soltar el <img> y el html generado dentro de un div posicionado en relación. ¡Gracias!
Ted Krapf
18

Encontré una forma no JS de abordar esto si estás de acuerdo con las áreas de golpe rectangulares.

En primer lugar, asegúrese de que su imagen esté en un div que esté relativamente posicionada. Luego ponga la imagen dentro de este div, lo que significa que ocupará todo el espacio en el div. Finalmente, agregue divs posicionados absolutamente debajo de la imagen, dentro del div principal, y use porcentajes para arriba, izquierda, ancho y alto para obtener las áreas de contacto del tamaño y la posición que desee.

Creo que es más fácil darle al div un color de fondo negro (idealmente con un desvanecimiento alfa para que pueda ver el contenido vinculado debajo) cuando trabaje por primera vez, y usar un inspector de código en su navegador para ajustar los porcentajes en tiempo real , para que puedas hacerlo bien.

Aquí está el esquema básico con el que puede trabajar. Al hacer todo con porcentajes, se asegura de que todos los elementos mantengan el mismo tamaño y posición relativa que la escala de la imagen.

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

Use este código con su inspector de código en Chrome o con su navegador de su elección, y ajuste los porcentajes (puede usar porcentajes decimales para ser más exactos) hasta que los cuadros sean correctos. También elija una background-colorde transparentcuando esté listo para usarlo, ya que desea que sus áreas de impacto sean invisibles.

Tom Bisciglia
fuente
Esta es una gran solución! Gracias
xims
Buena solución! UIkit usa la misma técnica para sus marcadores: getuikit.com/docs/marker
xela84
Solución brillante, ¡gracias por compartir! Estoy usando esto en una aplicación móvil y resuelve el problema de diferentes pantallas.
JohnGIS
11

David Bradshaw escribió una pequeña biblioteca que resuelve este problema. Se puede usar con o sin jQuery.

Disponible aquí: https://github.com/davidjbradshaw/imagemap-resizer

Grodriguez
fuente
Confirmado para trabajar en las últimas versiones de Chrome / IE / FF a partir de este comentario.
James Paterson el
1
Funcionó muy bien para mí, interfaz muy simple también
Brian
7

El siguiente método funciona perfectamente para mí, así que aquí está mi implementación completa:

<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>
quimeraha
fuente
4

Trabajando para mí (recuerde cambiar 3 cosas en el código):

  • previousWidth (tamaño original de la imagen)

  • ID_mapa (ID de su mapa de imagen)

  • img_ID (id de tu imagen)

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

Me encuentro con el mismo requisito donde, quiero mostrar un mapa de imagen sensible que puede cambiar de tamaño con cualquier tamaño de pantalla y lo importante es que quiero resaltar esas coordenadas .

Así que probé muchas bibliotecas que pueden cambiar el tamaño de las coordenadas según el tamaño de la pantalla y el evento. Y obtuve la mejor solución (jquery.imagemapster.min.js) que funciona bien con casi todos los navegadores. También lo he integrado con Summer Plgin que crea un mapa de imagen.

 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>

Espero ayudarlo a alguien.

Rahul Mahadik
fuente
2

http://home.comcast.net/~urbanjost/semaphore.html es la página principal de la discusión, y en realidad tiene enlaces a una solución del problema basada en JavaScript. He recibido un aviso de que HTML admitirá unidades porcentuales en el futuro, pero no he visto ningún progreso en esto en bastante tiempo (probablemente ha pasado más de un año desde que escuché que se recibiría soporte), así que la solución es Probablemente valga la pena mirar si te sientes cómodo con JavaScript / ECMAScript.

John Urban
fuente
2

Echa un vistazo al complemento de mapa de imagen en Github. Funciona tanto con JavaScript vainilla como con un complemento jQuery.

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

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

Mira la demo .

Travis Clarke
fuente
1

Depende, creo que puede usar jQuery para ajustar los rangos proporcionalmente. ¿Por qué usas un mapa de imagen por cierto? ¿No puedes usar divs de escala u otros elementos para ello?

Reinier Kaper
fuente
Si bien la solución exacta funcionaría con divs escalados, el mapa de imágenes está "administrado por contenido" y permite cualquier tipo de región. Gracias, revisaré jquery para esto.
jdog
1

Para aquellos que no quieren recurrir a JavaScript, aquí hay un ejemplo de división de imágenes:

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

A medida que escala la ventana, la imagen del payaso se escalará en consecuencia, y cuando lo hace, la nariz del payaso permanece hipervinculada.

Johnny Oshika
fuente
2
Gracias por las pesadillas!
jerrygarciuh
1
Los enlaces de imagen están rotos.
Tyler Forsythe
0

Similar a la respuesta de Orland aquí: https://stackoverflow.com/a/32870380/462781

Combinado con el código de Chris aquí: https://stackoverflow.com/a/12121309/462781

Si las áreas se ajustan a una cuadrícula, puede superponer las áreas con imágenes transparentes utilizando un ancho en% que mantenga su relación de aspecto.

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

Puede usar un margen en%. Además, las imágenes "espaciales" se pueden colocar una al lado de la otra dentro de un div de tercer nivel.

Pete
fuente
0

Por alguna razón, ninguna de estas soluciones funcionó para mí. He tenido el mejor éxito usando transformaciones.

transform: translateX(-5.8%) translateY(-5%) scale(0.884);
Mike Furlender
fuente
0

ancho y alto receptivo

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;
    }
Валерий Стасюк
fuente
¿Puedes agregar más contenido que muestre las diferencias entre tu código y la respuesta de Niente0 de 2015?
Michael - ¿Dónde está Clay Shirky?