Responsywna mapa obrazu

145

Mam istniejącą mapę obrazu w responsywnym układzie html. Obrazy są skalowane zgodnie z rozmiarem przeglądarki, ale współrzędne obrazu mają oczywiście stałe rozmiary w pikselach. Jakie mam opcje zmiany rozmiaru współrzędnych mapy obrazu?

jdog
źródło
6
To pytanie nie dotyczy mapy geograficznej, ale tagu <map> html
jdog
4
Wypróbuj wtyczkę mapy obrazu . Działa z Javascriptem, Node i jQuery
Travis Clarke
2
Alternatywnie możesz użyć obrazu SVG. Polecam przeczytanie Używanie SVG jako alternatywy dla map obrazów
Mawg mówi, że przywróć Monikę
1
Wygląda na to, że chcemy przesłać plik JPEG lub coś podobnego do aplikacji, która pozwala określić lokalizacje mapy na obrazie (na przykład w sieci punktów mapy obrazu) - w tle tworzy to plik SVG, który jest zasadniczo przezroczysty . Następnie chcemy, aby mapa została zastosowana do SVG i renderowała SVG na górze JPG w przeglądarce internetowej. Gdy przeglądarka zmienia rozmiar JPG, rozmiar SVG jest również zmieniany, a plik SVG jest zawsze wywoływany po kliknięciu mapy obrazu. Jakieś sugestie dotyczące którejkolwiek części tego?
youcantryreachingme
2
Tak, tego chciałem w 2011
jdog

Odpowiedzi:

89

Aby uzyskać responsywne mapy obrazu, musisz użyć wtyczki:

https://github.com/stowball/jQuery-rwdImageMaps (nie jest już obsługiwane)

Lub

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


Żadne większe przeglądarki nie rozumieją poprawnie współrzędnych procentowych i wszystkie interpretują współrzędne procentowe jako współrzędne pikseli.

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

A także ta strona do testowania, czy przeglądarki obsługują

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

Tomek
źródło
5
czy coś z tego jest nadal aktualne? czy możesz podać aktualizację?
Malachi,
1
@Malachi Tak, to jest nadal aktualne
Tom
dziękuję Tom, dyskutowaliśmy na temat pytania w CodeReview, teraz chciałbym pamiętać to pytanie ...
Malachi
@Tom to działa tylko dla jednego obrazu ... jeśli umieścimy inny obraz, to nie będzie działał dla drugiego i trzeciego obrazu itp ... po prostu to sprawdź ..
User2413
1
Znalazłem narzędzie do generowania online, które używa plików SVG, które wszystkie główne przeglądarki rozumieją imagemapper.noc.io
frthjf
43

Możesz także użyć SVG zamiast mapy obrazu. ;)

Istnieje poradnik, jak to zrobić.

.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
źródło
1
Link do samouczka jest uszkodzony. Obraz z jsfiddle również.
Cristiano Maia
Zasygnalizowałem, że link do samouczka jest uszkodzony i zaktualizowałem jsfiddle i fragmenty kodu. Dziękuję za heads up
belgac
To niesamowite rozwiązanie. Używam go z powodzeniem i działa jak urok. Dzięki!
Jaume Mussons Abad
3
Zdecydowanie najlepsze rozwiązanie w 2020 roku. Wypróbuj ten generator kodu, aby był bardzo prosty. imagemapper.noc.io/#
Brett Donald
1
To musi być najlepsze responsywne rozwiązanie w 2020 roku.
mythicalcoder
39

Responsywne mapy obrazów Wtyczka jQuery autorstwa Matt Stow

Joshua Stewardson
źródło
1
Just and FYI for eveyrone ... Odkryłem, że to działa dobrze, ale nie wewnątrz akordeonu. Używam Bootstrap 3 i jeśli nie załadujesz strony z otwartym akordeonem na obrazie, po otwarciu akordeonu mapy obrazu nie ma, chyba że okno przeglądarki zostanie zmienione.
jasonflaherty
1
@jasonflaherty czy możesz wywołać zdarzenie zmiany rozmiaru, aby wymusić wyświetlenie mapy? $(window).trigger('resize');
Steve Meisner
@SteveMeisner Nie próbowałem tego ... ale czy to nie wymusi odświeżenia?
jasonflaherty
@jasonflaherty nope! Po prostu „wyzwala” zdarzenie resize w powiązanym elemencie ( windoww tym przypadku). Powodzenia.
Steve Meisner
Właśnie stworzyłem super podstawowy, ale poręczny moduł Drupal za pomocą tej wtyczki: drupal.org/project/responsive_imagemaps
Joshua Stewardson
19

Natrafiłem na rozwiązanie, które w ogóle nie używa map obrazów, ale raczej znaczniki kotwicy, które są absolutnie umieszczone nad obrazem. Jedyną wadą byłoby to, że hotspot musiałby być prostokątny, ale plusem jest to, że to rozwiązanie nie opiera się na Javascript, tylko na CSS. Istnieje witryna internetowa, której można użyć do wygenerowania kodu HTML dla kotwic: http://www.zaneray.com/responsive-image-map/

Umieściłem obraz i wygenerowane znaczniki kotwicy we względnie umieszczonym znaczniku DIV i wszystko działało idealnie przy zmianie rozmiaru okna i na moim telefonie komórkowym.

Jeffrey Langham
źródło
2
Niezłe znalezisko! Dziękujemy za pomoc przy tworzeniu tej listy
jdog
1
Nie mogę wystarczająco pozytywnie głosować tego naswer! Doskonały poradnik; kompleksowe i łatwe do zrozumienia. Należy to wszystko przeczytać, ale szczególnie interesujące są tutorials.jenkov.com/svg/scripting.html
Mawg mówi, że przywrócimy Monikę
Jest to naprawdę proste, ale przyjemne rozwiązanie, jeśli obszar do kliknięcia jest prostokątem.
user2875289
To jest niesamowite. Pracował dla mnie również z witryną DNN. Jak stwierdził Jeffrey, właśnie porzuciłem <img> i wygenerowany kod HTML wewnątrz względnie pozycjonowanego elementu div. Dzięki!
Ted Krapf
18

Znalazłem sposób bez JS, aby rozwiązać ten problem, jeśli nie przeszkadzają ci prostokątne obszary uderzenia.

Przede wszystkim upewnij się, że obraz znajduje się w elemencie div, który jest względnie ustawiony. Następnie umieść obraz wewnątrz tego elementu div, co oznacza, że ​​zajmie on całą przestrzeń w elemencie div. Na koniec dodaj absolutnie pozycjonowane elementy div pod obrazem, w głównym div, i użyj wartości procentowych dla góry, lewej, szerokości i wysokości, aby uzyskać żądany rozmiar i pozycję obszarów kliknięcia linków.

Uważam, że najłatwiej jest nadać elementowi div koloru czarnego tła (najlepiej z pewnym zanikaniem alfa, aby można było zobaczyć połączoną zawartość pod spodem) podczas pierwszej pracy i użyć inspektora kodu w przeglądarce, aby dostosować wartości procentowe w czasie rzeczywistym , abyś mógł to zrobić dobrze.

Oto podstawowy zarys, z którym możesz pracować. Robiąc wszystko z procentami, upewniasz się, że wszystkie elementy mają ten sam względny rozmiar i położenie, co skalowanie obrazu.

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

Użyj tego kodu z inspektorem kodu w Chrome lub w wybranej przeglądarce i dostosuj wartości procentowe (możesz użyć procent dziesiętnych, aby być dokładniejszym), aż pola będą odpowiednie. Również wybrać background-colorod transparentkiedy jesteś gotowy, aby go używać, ponieważ chcesz, aby obszary obrażeń być niewidoczne.

Tom Bisciglia
źródło
To świetne rozwiązanie! Dziękuję
xims
Niezłe rozwiązanie! UIkit używa tej samej techniki do swoich znaczników: getuikit.com/docs/marker
xela84
Świetne rozwiązanie, dzięki za udostępnienie! Używam tego w aplikacji mobilnej i rozwiązuje problem różnych ekranów.
JohnGIS,
11

David Bradshaw napisał ładną małą bibliotekę, która rozwiązuje ten problem. Może być używany z jQuery lub bez niego.

Dostępne tutaj: https://github.com/davidjbradshaw/imagemap-resizer

Grodriguez
źródło
Potwierdzone do pracy w najnowszych wersjach Chrome / IE / FF od tego komentarza.
James Paterson
1
Działał dla mnie świetnie, też super prosty interfejs
Brian
7

Poniższa metoda działa idealnie dla mnie, więc oto moja pełna realizacja:

<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
źródło
4

Pracuje dla mnie (pamiętaj o zmianie 3 rzeczy w kodzie):

  • previousWidth (oryginalny rozmiar obrazu)

  • map_ID (identyfikator mapy obrazu)

  • img_ID (identyfikator Twojego obrazu)

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
źródło
3

Spotykam się z tym samym wymaganiem, w którym chcę pokazać responsywną mapę obrazu, która może zmieniać rozmiar z dowolnym rozmiarem ekranu i ważne jest, aby podkreślić te współrzędne .

Wypróbowałem więc wiele bibliotek, które mogą zmieniać rozmiar współrzędnych w zależności od rozmiaru ekranu i zdarzenia. I mam najlepsze rozwiązanie (jquery.imagemapster.min.js), które działa dobrze z prawie wszystkimi przeglądarkami. Zintegrowałem go również z Summer Plgin, która tworzy mapę obrazu.

 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>

Mam nadzieję, że komuś pomogę.

Rahul Mahadik
źródło
2

http://home.comcast.net/~urbanjost/semaphore.html to główna strona dyskusji i tak naprawdę zawiera linki do rozwiązania problemu opartego na JavaScript. Otrzymałem powiadomienie, że HTML będzie obsługiwał jednostki procentowe w przyszłości, ale nie widziałem żadnych postępów w tej sprawie od dłuższego czasu (prawdopodobnie minął ponad rok, odkąd usłyszałem, że wsparcie będzie się zbliżać), więc obejście jest takie prawdopodobnie warto się temu przyjrzeć, jeśli dobrze znasz JavaScript / ECMAScript.

John Urban
źródło
2

Sprawdź wtyczkę mapy obrazu na Github. Działa zarówno z waniliowym JavaScriptem, jak i jako wtyczka jQuery.

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

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

Sprawdź demo .

Travis Clarke
źródło
1

To zależy, myślę, że możesz użyć jQuery do proporcjonalnej regulacji zakresów. Dlaczego przy okazji korzystasz z mapy obrazu? Nie możesz użyć do tego skalujących elementów div lub innych elementów?

Reinier Kaper
źródło
podczas gdy dokładne rozwiązanie działałoby ze skalowanymi elementami DIV, mapa obrazu jest „zarządzana treścią” i pozwala na dowolny rodzaj regionu. Dzięki, sprawdzę jQuery.
jdog
1

Dla tych, którzy nie chcą uciekać się do JavaScript, oto przykład wycinania obrazu:

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

Gdy skalujesz okno, obraz klauna będzie odpowiednio skalowany, a kiedy to nastąpi, nos klauna pozostaje hiperłączem.

Johnny Oshika
źródło
2
Dzięki za koszmary!
jerrygarciuh
1
Linki do obrazów są uszkodzone.
Tyler Forsythe
0

Podobnie jak odpowiedź Orlanda tutaj: https://stackoverflow.com/a/32870380/462781

W połączeniu z kodem Chrisa tutaj: https://stackoverflow.com/a/12121309/462781

Jeśli obszary mieszczą się w siatce, można je nałożyć przezroczystymi obrazami, używając szerokości w%, które zachowują proporcje.

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

Możesz użyć marginesu w%. Dodatkowo obrazy „kosmiczne” mogą być umieszczane obok siebie wewnątrz div 3 poziomu.

Pete
źródło
0

Z jakiegoś powodu żadne z tych rozwiązań nie zadziałało. Największy sukces odniosłem, używając transformacji.

transform: translateX(-5.8%) translateY(-5%) scale(0.884);
Mike Furlender
źródło
0

responsywna szerokość i wysokość

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;
    }
Валерий Стасюк
źródło
Czy możesz dodać więcej treści pokazujących różnice między Twoim kodem a odpowiedzią Niente0 z 2015 roku?
Michael - Where's Clay Shirky