jquery: fancybox 3, responsive image maps and zoomable content











up vote
0
down vote

favorite












I want to use image-maps inside fancybox 3. Goal is to display mountain panoramas, where the user could point on a summit and get name and data. The usual recommendation is to use a SVG based image map for this like in this pen. Due to the size of the images the fancybox zoom functionality is important.



While fancybox will display SVGs as an image like in this pen it is not possible to use the <image> tag with an external source inside the SVG file. Even worse: SVG files used as source of an <img> tag would not show the map functionality (see this question).



I tried to replace the <img> tag in fancybox with an <object> tag using the SVG file as data attribute. This shows the image with the map functionality correctly but fancybox won't zoom it any more.



So eventually the question boils down to how I can make an <object> (or an inline SVG or an iframe) zoomable just like an image in fancybox 3.



I'm open to other solutions as well. I only want to use fancybox to keep the appearance and usage the same as other image galleries on the same page. I'd even use an old style <map>, where I would change the coords using jquery to have it responsive. I tried that, attaching the map manually in developer tools as well as programmatically in afterLoad event handler, but apparently this doesn't work in fancybox 3 either.



The areas are polygons, so using positioned div's as overlays is no solution.



Edit: I just discovered that I can replace <img> with a <canvas> in fancybox without loosing the zoom and drag functionality. So in theory it would be possible to use canvas paths and isPointInPath() methode. Unfortunately I need more than one path, which requires the Path2D object, which is not available in IE...










share|improve this question
























  • Currently, zoom functionality is available for images only, therefore you either use some 3rd party script (like in this example - codepen.io/anon/pen/bvjeLZ?editors=1010) or wait for v4, where zoom api will be much more powerful
    – Janis
    Nov 22 at 12:02















up vote
0
down vote

favorite












I want to use image-maps inside fancybox 3. Goal is to display mountain panoramas, where the user could point on a summit and get name and data. The usual recommendation is to use a SVG based image map for this like in this pen. Due to the size of the images the fancybox zoom functionality is important.



While fancybox will display SVGs as an image like in this pen it is not possible to use the <image> tag with an external source inside the SVG file. Even worse: SVG files used as source of an <img> tag would not show the map functionality (see this question).



I tried to replace the <img> tag in fancybox with an <object> tag using the SVG file as data attribute. This shows the image with the map functionality correctly but fancybox won't zoom it any more.



So eventually the question boils down to how I can make an <object> (or an inline SVG or an iframe) zoomable just like an image in fancybox 3.



I'm open to other solutions as well. I only want to use fancybox to keep the appearance and usage the same as other image galleries on the same page. I'd even use an old style <map>, where I would change the coords using jquery to have it responsive. I tried that, attaching the map manually in developer tools as well as programmatically in afterLoad event handler, but apparently this doesn't work in fancybox 3 either.



The areas are polygons, so using positioned div's as overlays is no solution.



Edit: I just discovered that I can replace <img> with a <canvas> in fancybox without loosing the zoom and drag functionality. So in theory it would be possible to use canvas paths and isPointInPath() methode. Unfortunately I need more than one path, which requires the Path2D object, which is not available in IE...










share|improve this question
























  • Currently, zoom functionality is available for images only, therefore you either use some 3rd party script (like in this example - codepen.io/anon/pen/bvjeLZ?editors=1010) or wait for v4, where zoom api will be much more powerful
    – Janis
    Nov 22 at 12:02













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I want to use image-maps inside fancybox 3. Goal is to display mountain panoramas, where the user could point on a summit and get name and data. The usual recommendation is to use a SVG based image map for this like in this pen. Due to the size of the images the fancybox zoom functionality is important.



While fancybox will display SVGs as an image like in this pen it is not possible to use the <image> tag with an external source inside the SVG file. Even worse: SVG files used as source of an <img> tag would not show the map functionality (see this question).



I tried to replace the <img> tag in fancybox with an <object> tag using the SVG file as data attribute. This shows the image with the map functionality correctly but fancybox won't zoom it any more.



So eventually the question boils down to how I can make an <object> (or an inline SVG or an iframe) zoomable just like an image in fancybox 3.



I'm open to other solutions as well. I only want to use fancybox to keep the appearance and usage the same as other image galleries on the same page. I'd even use an old style <map>, where I would change the coords using jquery to have it responsive. I tried that, attaching the map manually in developer tools as well as programmatically in afterLoad event handler, but apparently this doesn't work in fancybox 3 either.



The areas are polygons, so using positioned div's as overlays is no solution.



Edit: I just discovered that I can replace <img> with a <canvas> in fancybox without loosing the zoom and drag functionality. So in theory it would be possible to use canvas paths and isPointInPath() methode. Unfortunately I need more than one path, which requires the Path2D object, which is not available in IE...










share|improve this question















I want to use image-maps inside fancybox 3. Goal is to display mountain panoramas, where the user could point on a summit and get name and data. The usual recommendation is to use a SVG based image map for this like in this pen. Due to the size of the images the fancybox zoom functionality is important.



While fancybox will display SVGs as an image like in this pen it is not possible to use the <image> tag with an external source inside the SVG file. Even worse: SVG files used as source of an <img> tag would not show the map functionality (see this question).



I tried to replace the <img> tag in fancybox with an <object> tag using the SVG file as data attribute. This shows the image with the map functionality correctly but fancybox won't zoom it any more.



So eventually the question boils down to how I can make an <object> (or an inline SVG or an iframe) zoomable just like an image in fancybox 3.



I'm open to other solutions as well. I only want to use fancybox to keep the appearance and usage the same as other image galleries on the same page. I'd even use an old style <map>, where I would change the coords using jquery to have it responsive. I tried that, attaching the map manually in developer tools as well as programmatically in afterLoad event handler, but apparently this doesn't work in fancybox 3 either.



The areas are polygons, so using positioned div's as overlays is no solution.



Edit: I just discovered that I can replace <img> with a <canvas> in fancybox without loosing the zoom and drag functionality. So in theory it would be possible to use canvas paths and isPointInPath() methode. Unfortunately I need more than one path, which requires the Path2D object, which is not available in IE...







svg imagemap fancybox-3






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 at 20:32

























asked Nov 22 at 9:38









Erik Krause

11




11












  • Currently, zoom functionality is available for images only, therefore you either use some 3rd party script (like in this example - codepen.io/anon/pen/bvjeLZ?editors=1010) or wait for v4, where zoom api will be much more powerful
    – Janis
    Nov 22 at 12:02


















  • Currently, zoom functionality is available for images only, therefore you either use some 3rd party script (like in this example - codepen.io/anon/pen/bvjeLZ?editors=1010) or wait for v4, where zoom api will be much more powerful
    – Janis
    Nov 22 at 12:02
















Currently, zoom functionality is available for images only, therefore you either use some 3rd party script (like in this example - codepen.io/anon/pen/bvjeLZ?editors=1010) or wait for v4, where zoom api will be much more powerful
– Janis
Nov 22 at 12:02




Currently, zoom functionality is available for images only, therefore you either use some 3rd party script (like in this example - codepen.io/anon/pen/bvjeLZ?editors=1010) or wait for v4, where zoom api will be much more powerful
– Janis
Nov 22 at 12:02












1 Answer
1






active

oldest

votes

















up vote
0
down vote













Since all options discussed in the question turned out to be not feasible and I found the pnpoly point in polygon algorithm, I did the whole thing on my own. I put the coordinates as percentages (in order to be size-independent) in an array of javascript objects like so:



    var maps = {
alpen : [
{type:'poly',name:'Finsteraarhorn (4274m)',vertx:[56.48,56.08,56.06,56.46], verty:[28.5,28.75,40.25,40.25]},
{type:'rect',name:'Fiescherhörner (4049m)',coords:[58.08,29.5,59.26,43.5]},
{type:'poly',name:'Eiger (3970m)',vertx:[61.95,61.31,61.31,60.5,60.5], verty:[43,35.25,30.25,30.25,45.5]}
]
}; // maps


Since the pnpoly function requires the vertices for x and y separately I provide the coordinates this way already.



The Id of the map is stored in a data attribute in the source link:



  <a href="/img/bilder/Alpen.jpg" data-type='image' data-Id='alpen' data-fancybox="img" data-caption="<h5>panorama of the alps from the black forest Belchen at sunset</h5>">
<img src="/_pano/bilder/Alpen.jpg">
</a>


CSS for the tooltip:



.my-tooltip {
color: #ccc;
background: rgba(30,30,30,.6);
position: absolute;
padding: 5px;
text-align: left;
border-radius: 5px;
font-size: 12px;
}


pnpoly and pnrect are provided as simple functions, the handling of that all is done in the afterShow event handler:



// PNPoly algorithm checkes whether point in polygon
function pnpoly(vertx, verty, testx, testy) {
var i, j, c = false;
var nvert = vertx.length;
for(i=0, j=nvert-1; i<nvert; j=i++) {
if (((verty[i] > testy) != (verty[j] > testy)) &&
(testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i])) {
c = !c;
}
}
return c;
}

// checks whether point in rectangle
function pnrect(coords,testx,testy) {
return ((testx >= coords[0]) && (testx <= coords[2]) && (testy >= coords[1]) && (testy <= coords[3]));
}

$("[data-fancybox]").fancybox({
afterShow: function( instance, slide ) {
var map = maps[$(slide.opts.$orig).data('id')]; // Get map name from source link data-ID
if (map && map.length) { // if map present
$(".fancybox-image")
.after("<span class='my-tooltip' style='display: none'></span>") // append tooltip after image
.mousemove(function(event) { // create mousemove event handler
var offset = $(this).offset(); // get image offset, since mouse coords are global
var perX = ((event.pageX - offset.left)*100)/$(this).width(); // calculate mouse coords in image as percentages
var perY = ((event.pageY - offset.top)*100)/$(this).height();
var found = false;
var i;
for (i = 0; i < map.length; i++) { // loop over map entries
if (found = (map[i].type == 'poly') // depending on area type
?pnpoly(map[i].vertx, map[i].verty, perX, perY) // look whether coords are in polygon
:pnrect(map[i].coords, perX, perY)) // or coords are in rectangle
break; // if found stop looping
} // for (i = 0; i < map.length; i++)
if (found) {
$(".my-tooltip")
.css({bottom: 'calc(15px + '+ (100 - perY) + '%'}) // tooltip 15px above mouse coursor
.css((perX < 50) // depending on which side we are
?{right:'', left: perX + '%'} // tooltip left of mouse cursor
:{right: (100 - perX) + '%', left:''}) // or tooltip right of mouse cursor
.text(map[i].name) // set tooltip text
.show(); // show tooltip
} else {
$(".my-tooltip").hide(); // if nothing found: hide.
}
});
} else { // if (map && map.length) // if no map present
$(".fancybox-image").off('mousemove'); // remove event mousemove handler
$(".my-tooltip").remove(); // remove tooltip
} // else if (map && map.length)
} // function( instance, slide )
});


Things left to do: Find a solution for touch devices, f.e. provide a button to show all tooltips (probably rotated 90°).



As soon as the page is online I'll provide a link here to see it working...






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53427853%2fjquery-fancybox-3-responsive-image-maps-and-zoomable-content%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote













    Since all options discussed in the question turned out to be not feasible and I found the pnpoly point in polygon algorithm, I did the whole thing on my own. I put the coordinates as percentages (in order to be size-independent) in an array of javascript objects like so:



        var maps = {
    alpen : [
    {type:'poly',name:'Finsteraarhorn (4274m)',vertx:[56.48,56.08,56.06,56.46], verty:[28.5,28.75,40.25,40.25]},
    {type:'rect',name:'Fiescherhörner (4049m)',coords:[58.08,29.5,59.26,43.5]},
    {type:'poly',name:'Eiger (3970m)',vertx:[61.95,61.31,61.31,60.5,60.5], verty:[43,35.25,30.25,30.25,45.5]}
    ]
    }; // maps


    Since the pnpoly function requires the vertices for x and y separately I provide the coordinates this way already.



    The Id of the map is stored in a data attribute in the source link:



      <a href="/img/bilder/Alpen.jpg" data-type='image' data-Id='alpen' data-fancybox="img" data-caption="<h5>panorama of the alps from the black forest Belchen at sunset</h5>">
    <img src="/_pano/bilder/Alpen.jpg">
    </a>


    CSS for the tooltip:



    .my-tooltip {
    color: #ccc;
    background: rgba(30,30,30,.6);
    position: absolute;
    padding: 5px;
    text-align: left;
    border-radius: 5px;
    font-size: 12px;
    }


    pnpoly and pnrect are provided as simple functions, the handling of that all is done in the afterShow event handler:



    // PNPoly algorithm checkes whether point in polygon
    function pnpoly(vertx, verty, testx, testy) {
    var i, j, c = false;
    var nvert = vertx.length;
    for(i=0, j=nvert-1; i<nvert; j=i++) {
    if (((verty[i] > testy) != (verty[j] > testy)) &&
    (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i])) {
    c = !c;
    }
    }
    return c;
    }

    // checks whether point in rectangle
    function pnrect(coords,testx,testy) {
    return ((testx >= coords[0]) && (testx <= coords[2]) && (testy >= coords[1]) && (testy <= coords[3]));
    }

    $("[data-fancybox]").fancybox({
    afterShow: function( instance, slide ) {
    var map = maps[$(slide.opts.$orig).data('id')]; // Get map name from source link data-ID
    if (map && map.length) { // if map present
    $(".fancybox-image")
    .after("<span class='my-tooltip' style='display: none'></span>") // append tooltip after image
    .mousemove(function(event) { // create mousemove event handler
    var offset = $(this).offset(); // get image offset, since mouse coords are global
    var perX = ((event.pageX - offset.left)*100)/$(this).width(); // calculate mouse coords in image as percentages
    var perY = ((event.pageY - offset.top)*100)/$(this).height();
    var found = false;
    var i;
    for (i = 0; i < map.length; i++) { // loop over map entries
    if (found = (map[i].type == 'poly') // depending on area type
    ?pnpoly(map[i].vertx, map[i].verty, perX, perY) // look whether coords are in polygon
    :pnrect(map[i].coords, perX, perY)) // or coords are in rectangle
    break; // if found stop looping
    } // for (i = 0; i < map.length; i++)
    if (found) {
    $(".my-tooltip")
    .css({bottom: 'calc(15px + '+ (100 - perY) + '%'}) // tooltip 15px above mouse coursor
    .css((perX < 50) // depending on which side we are
    ?{right:'', left: perX + '%'} // tooltip left of mouse cursor
    :{right: (100 - perX) + '%', left:''}) // or tooltip right of mouse cursor
    .text(map[i].name) // set tooltip text
    .show(); // show tooltip
    } else {
    $(".my-tooltip").hide(); // if nothing found: hide.
    }
    });
    } else { // if (map && map.length) // if no map present
    $(".fancybox-image").off('mousemove'); // remove event mousemove handler
    $(".my-tooltip").remove(); // remove tooltip
    } // else if (map && map.length)
    } // function( instance, slide )
    });


    Things left to do: Find a solution for touch devices, f.e. provide a button to show all tooltips (probably rotated 90°).



    As soon as the page is online I'll provide a link here to see it working...






    share|improve this answer

























      up vote
      0
      down vote













      Since all options discussed in the question turned out to be not feasible and I found the pnpoly point in polygon algorithm, I did the whole thing on my own. I put the coordinates as percentages (in order to be size-independent) in an array of javascript objects like so:



          var maps = {
      alpen : [
      {type:'poly',name:'Finsteraarhorn (4274m)',vertx:[56.48,56.08,56.06,56.46], verty:[28.5,28.75,40.25,40.25]},
      {type:'rect',name:'Fiescherhörner (4049m)',coords:[58.08,29.5,59.26,43.5]},
      {type:'poly',name:'Eiger (3970m)',vertx:[61.95,61.31,61.31,60.5,60.5], verty:[43,35.25,30.25,30.25,45.5]}
      ]
      }; // maps


      Since the pnpoly function requires the vertices for x and y separately I provide the coordinates this way already.



      The Id of the map is stored in a data attribute in the source link:



        <a href="/img/bilder/Alpen.jpg" data-type='image' data-Id='alpen' data-fancybox="img" data-caption="<h5>panorama of the alps from the black forest Belchen at sunset</h5>">
      <img src="/_pano/bilder/Alpen.jpg">
      </a>


      CSS for the tooltip:



      .my-tooltip {
      color: #ccc;
      background: rgba(30,30,30,.6);
      position: absolute;
      padding: 5px;
      text-align: left;
      border-radius: 5px;
      font-size: 12px;
      }


      pnpoly and pnrect are provided as simple functions, the handling of that all is done in the afterShow event handler:



      // PNPoly algorithm checkes whether point in polygon
      function pnpoly(vertx, verty, testx, testy) {
      var i, j, c = false;
      var nvert = vertx.length;
      for(i=0, j=nvert-1; i<nvert; j=i++) {
      if (((verty[i] > testy) != (verty[j] > testy)) &&
      (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i])) {
      c = !c;
      }
      }
      return c;
      }

      // checks whether point in rectangle
      function pnrect(coords,testx,testy) {
      return ((testx >= coords[0]) && (testx <= coords[2]) && (testy >= coords[1]) && (testy <= coords[3]));
      }

      $("[data-fancybox]").fancybox({
      afterShow: function( instance, slide ) {
      var map = maps[$(slide.opts.$orig).data('id')]; // Get map name from source link data-ID
      if (map && map.length) { // if map present
      $(".fancybox-image")
      .after("<span class='my-tooltip' style='display: none'></span>") // append tooltip after image
      .mousemove(function(event) { // create mousemove event handler
      var offset = $(this).offset(); // get image offset, since mouse coords are global
      var perX = ((event.pageX - offset.left)*100)/$(this).width(); // calculate mouse coords in image as percentages
      var perY = ((event.pageY - offset.top)*100)/$(this).height();
      var found = false;
      var i;
      for (i = 0; i < map.length; i++) { // loop over map entries
      if (found = (map[i].type == 'poly') // depending on area type
      ?pnpoly(map[i].vertx, map[i].verty, perX, perY) // look whether coords are in polygon
      :pnrect(map[i].coords, perX, perY)) // or coords are in rectangle
      break; // if found stop looping
      } // for (i = 0; i < map.length; i++)
      if (found) {
      $(".my-tooltip")
      .css({bottom: 'calc(15px + '+ (100 - perY) + '%'}) // tooltip 15px above mouse coursor
      .css((perX < 50) // depending on which side we are
      ?{right:'', left: perX + '%'} // tooltip left of mouse cursor
      :{right: (100 - perX) + '%', left:''}) // or tooltip right of mouse cursor
      .text(map[i].name) // set tooltip text
      .show(); // show tooltip
      } else {
      $(".my-tooltip").hide(); // if nothing found: hide.
      }
      });
      } else { // if (map && map.length) // if no map present
      $(".fancybox-image").off('mousemove'); // remove event mousemove handler
      $(".my-tooltip").remove(); // remove tooltip
      } // else if (map && map.length)
      } // function( instance, slide )
      });


      Things left to do: Find a solution for touch devices, f.e. provide a button to show all tooltips (probably rotated 90°).



      As soon as the page is online I'll provide a link here to see it working...






      share|improve this answer























        up vote
        0
        down vote










        up vote
        0
        down vote









        Since all options discussed in the question turned out to be not feasible and I found the pnpoly point in polygon algorithm, I did the whole thing on my own. I put the coordinates as percentages (in order to be size-independent) in an array of javascript objects like so:



            var maps = {
        alpen : [
        {type:'poly',name:'Finsteraarhorn (4274m)',vertx:[56.48,56.08,56.06,56.46], verty:[28.5,28.75,40.25,40.25]},
        {type:'rect',name:'Fiescherhörner (4049m)',coords:[58.08,29.5,59.26,43.5]},
        {type:'poly',name:'Eiger (3970m)',vertx:[61.95,61.31,61.31,60.5,60.5], verty:[43,35.25,30.25,30.25,45.5]}
        ]
        }; // maps


        Since the pnpoly function requires the vertices for x and y separately I provide the coordinates this way already.



        The Id of the map is stored in a data attribute in the source link:



          <a href="/img/bilder/Alpen.jpg" data-type='image' data-Id='alpen' data-fancybox="img" data-caption="<h5>panorama of the alps from the black forest Belchen at sunset</h5>">
        <img src="/_pano/bilder/Alpen.jpg">
        </a>


        CSS for the tooltip:



        .my-tooltip {
        color: #ccc;
        background: rgba(30,30,30,.6);
        position: absolute;
        padding: 5px;
        text-align: left;
        border-radius: 5px;
        font-size: 12px;
        }


        pnpoly and pnrect are provided as simple functions, the handling of that all is done in the afterShow event handler:



        // PNPoly algorithm checkes whether point in polygon
        function pnpoly(vertx, verty, testx, testy) {
        var i, j, c = false;
        var nvert = vertx.length;
        for(i=0, j=nvert-1; i<nvert; j=i++) {
        if (((verty[i] > testy) != (verty[j] > testy)) &&
        (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i])) {
        c = !c;
        }
        }
        return c;
        }

        // checks whether point in rectangle
        function pnrect(coords,testx,testy) {
        return ((testx >= coords[0]) && (testx <= coords[2]) && (testy >= coords[1]) && (testy <= coords[3]));
        }

        $("[data-fancybox]").fancybox({
        afterShow: function( instance, slide ) {
        var map = maps[$(slide.opts.$orig).data('id')]; // Get map name from source link data-ID
        if (map && map.length) { // if map present
        $(".fancybox-image")
        .after("<span class='my-tooltip' style='display: none'></span>") // append tooltip after image
        .mousemove(function(event) { // create mousemove event handler
        var offset = $(this).offset(); // get image offset, since mouse coords are global
        var perX = ((event.pageX - offset.left)*100)/$(this).width(); // calculate mouse coords in image as percentages
        var perY = ((event.pageY - offset.top)*100)/$(this).height();
        var found = false;
        var i;
        for (i = 0; i < map.length; i++) { // loop over map entries
        if (found = (map[i].type == 'poly') // depending on area type
        ?pnpoly(map[i].vertx, map[i].verty, perX, perY) // look whether coords are in polygon
        :pnrect(map[i].coords, perX, perY)) // or coords are in rectangle
        break; // if found stop looping
        } // for (i = 0; i < map.length; i++)
        if (found) {
        $(".my-tooltip")
        .css({bottom: 'calc(15px + '+ (100 - perY) + '%'}) // tooltip 15px above mouse coursor
        .css((perX < 50) // depending on which side we are
        ?{right:'', left: perX + '%'} // tooltip left of mouse cursor
        :{right: (100 - perX) + '%', left:''}) // or tooltip right of mouse cursor
        .text(map[i].name) // set tooltip text
        .show(); // show tooltip
        } else {
        $(".my-tooltip").hide(); // if nothing found: hide.
        }
        });
        } else { // if (map && map.length) // if no map present
        $(".fancybox-image").off('mousemove'); // remove event mousemove handler
        $(".my-tooltip").remove(); // remove tooltip
        } // else if (map && map.length)
        } // function( instance, slide )
        });


        Things left to do: Find a solution for touch devices, f.e. provide a button to show all tooltips (probably rotated 90°).



        As soon as the page is online I'll provide a link here to see it working...






        share|improve this answer












        Since all options discussed in the question turned out to be not feasible and I found the pnpoly point in polygon algorithm, I did the whole thing on my own. I put the coordinates as percentages (in order to be size-independent) in an array of javascript objects like so:



            var maps = {
        alpen : [
        {type:'poly',name:'Finsteraarhorn (4274m)',vertx:[56.48,56.08,56.06,56.46], verty:[28.5,28.75,40.25,40.25]},
        {type:'rect',name:'Fiescherhörner (4049m)',coords:[58.08,29.5,59.26,43.5]},
        {type:'poly',name:'Eiger (3970m)',vertx:[61.95,61.31,61.31,60.5,60.5], verty:[43,35.25,30.25,30.25,45.5]}
        ]
        }; // maps


        Since the pnpoly function requires the vertices for x and y separately I provide the coordinates this way already.



        The Id of the map is stored in a data attribute in the source link:



          <a href="/img/bilder/Alpen.jpg" data-type='image' data-Id='alpen' data-fancybox="img" data-caption="<h5>panorama of the alps from the black forest Belchen at sunset</h5>">
        <img src="/_pano/bilder/Alpen.jpg">
        </a>


        CSS for the tooltip:



        .my-tooltip {
        color: #ccc;
        background: rgba(30,30,30,.6);
        position: absolute;
        padding: 5px;
        text-align: left;
        border-radius: 5px;
        font-size: 12px;
        }


        pnpoly and pnrect are provided as simple functions, the handling of that all is done in the afterShow event handler:



        // PNPoly algorithm checkes whether point in polygon
        function pnpoly(vertx, verty, testx, testy) {
        var i, j, c = false;
        var nvert = vertx.length;
        for(i=0, j=nvert-1; i<nvert; j=i++) {
        if (((verty[i] > testy) != (verty[j] > testy)) &&
        (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i])) {
        c = !c;
        }
        }
        return c;
        }

        // checks whether point in rectangle
        function pnrect(coords,testx,testy) {
        return ((testx >= coords[0]) && (testx <= coords[2]) && (testy >= coords[1]) && (testy <= coords[3]));
        }

        $("[data-fancybox]").fancybox({
        afterShow: function( instance, slide ) {
        var map = maps[$(slide.opts.$orig).data('id')]; // Get map name from source link data-ID
        if (map && map.length) { // if map present
        $(".fancybox-image")
        .after("<span class='my-tooltip' style='display: none'></span>") // append tooltip after image
        .mousemove(function(event) { // create mousemove event handler
        var offset = $(this).offset(); // get image offset, since mouse coords are global
        var perX = ((event.pageX - offset.left)*100)/$(this).width(); // calculate mouse coords in image as percentages
        var perY = ((event.pageY - offset.top)*100)/$(this).height();
        var found = false;
        var i;
        for (i = 0; i < map.length; i++) { // loop over map entries
        if (found = (map[i].type == 'poly') // depending on area type
        ?pnpoly(map[i].vertx, map[i].verty, perX, perY) // look whether coords are in polygon
        :pnrect(map[i].coords, perX, perY)) // or coords are in rectangle
        break; // if found stop looping
        } // for (i = 0; i < map.length; i++)
        if (found) {
        $(".my-tooltip")
        .css({bottom: 'calc(15px + '+ (100 - perY) + '%'}) // tooltip 15px above mouse coursor
        .css((perX < 50) // depending on which side we are
        ?{right:'', left: perX + '%'} // tooltip left of mouse cursor
        :{right: (100 - perX) + '%', left:''}) // or tooltip right of mouse cursor
        .text(map[i].name) // set tooltip text
        .show(); // show tooltip
        } else {
        $(".my-tooltip").hide(); // if nothing found: hide.
        }
        });
        } else { // if (map && map.length) // if no map present
        $(".fancybox-image").off('mousemove'); // remove event mousemove handler
        $(".my-tooltip").remove(); // remove tooltip
        } // else if (map && map.length)
        } // function( instance, slide )
        });


        Things left to do: Find a solution for touch devices, f.e. provide a button to show all tooltips (probably rotated 90°).



        As soon as the page is online I'll provide a link here to see it working...







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 24 at 21:36









        Erik Krause

        11




        11






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53427853%2fjquery-fancybox-3-responsive-image-maps-and-zoomable-content%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

            Calculate evaluation metrics using cross_val_predict sklearn

            Insert data from modal to MySQL (multiple modal on website)