Search code examples
javascriptjquerybootstrap-4tooltip

Tooltip based on pixels in an image


I have a set of images. Each image is displaying multiple objects. I want to show a tooltip whenever I hover my mouse pointer over each object in the image. I have pixel coordinates, and width and height for each object in an image.

I know a couple of different ways to implement a tooltip for an element but don't know how to handle pixel dimensions inside an image with respect to the tooltip.


Solution

  • You could use image maps for this:

    var elements = [
     { label: 'Yellow', x: 112, y: 23,  w: 112, h: 89  },
     { label: 'Pink',   x: 27,  y: 119, w: 110, h: 195 },
     { label: 'Brown',  x: 198, y: 124, w: 112, h: 90  }
    ];
    
    var img = document.querySelector('img'),
        map = document.createElement('map');
    
    map.name = 'my-map';
    img.setAttribute('usemap', '#' + map.name);
    
    elements.forEach(function(el) {
      var area = document.createElement('area');
      area.title = el.label;
      area.coords = [el.x, el.y, el.x + el.w, el.y + el.h].join(',');
      map.appendChild(area);
    });
    
    document.body.appendChild(map);
    <img src="https://image.shutterstock.com/image-photo/three-macaroons-sweet-desserts-isolated-260nw-351030134.jpg">

    If you have multiple images, you could make it into a reusable function:

    addImageMap(
      document.getElementById('image-a'),
      [
        { label: 'Yellow', x: 112, y: 23,  w: 112, h: 89  },
        { label: 'Pink',   x: 27,  y: 119, w: 110, h: 195 },
        { label: 'Brown',  x: 198, y: 124, w: 112, h: 90  }
      ]
    );
    
    addImageMap(
      document.getElementById('image-b'),
      [
        { label: 'Drink',  x: 111, y: 90,  w: 310, h: 450  },
        { label: 'Burger', x: 471, y: 100, w: 320, h: 450 },
        { label: 'Fries',  x: 891, y: 52,  w: 300, h: 450 }
      ]
    );
    
    // If you want responsive image maps (see plugin added in HTML)
    imageMapResize();
    
    function addImageMap(img, elements) {
      var map = document.createElement('map');
    
      map.name = 'my-map-' + getUniqueMapId();
      img.setAttribute('usemap', '#' + map.name);
    
      elements.forEach(function(el) {
        var area = document.createElement('area');
        area.title = el.label;
        area.coords = [el.x, el.y, el.x + el.w, el.y + el.h].join(',');
        map.appendChild(area);
      });
    
      document.body.appendChild(map);
    }
    
    function getUniqueMapId() {
      window.uniqueMapId = (window.uniqueMapId || 0) + 1;
      return window.uniqueMapId;
    }
    img { width: 200px; }
    <!-- Docs: https://github.com/davidjbradshaw/image-map-resizer -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/image-map-resizer/1.0.10/js/imageMapResizer.min.js"></script>
    
    <img id="image-a" src="https://image.shutterstock.com/image-photo/three-macaroons-sweet-desserts-isolated-260nw-351030134.jpg">
    <img id="image-b" src="https://previews.123rf.com/images/ifh/ifh1512/ifh151200179/49541375-illustration-of-set-of-three-objects-such-as-hamburger-french-fries-and-coffee.jpg">