jQuery:fancybox 3,响应式图像地图和可缩放内容

时间:2018-11-22 09:38:06

标签: svg imagemap fancybox-3

我想在fancybox 3中使用图像地图。目标是显示山峰全景图,用户可以在其中指向山顶并获取名称和数据。通常的建议是为此使用基于SVG的图像映射,例如in this pen。由于图像的大小,fancybox缩放功能非常重要。

尽管fancybox将SVG显示为in this pen之类的图像,但无法将<image>标签与SVG文件中的外部源一起使用。更糟糕的是:用作<img>标签来源的SVG文件不会显示地图功能(see this question)。

我尝试使用SVG文件作为数据属性,将fancybox中的<img>标签替换为<object>标签。这样可以正确显示具有地图功能的图像,但fancybox不再对其进行缩放。

因此最终,问题归结为我如何使<object>(或嵌入式SVG或iframe)可缩放,就像fancybox 3中的图像一样。

我也欢迎其他解决方案。我只想使用fancybox来使外观和用法与同一页面上的其他图像画廊相同。我什至会使用旧样式<map>,在该样式中我将使用jquery更改坐标以使其具有响应性。我尝试过,在开发人员工具中手动添加了地图,并在afterLoad事件处理程序中以编程方式附加了地图,但显然这在fancybox 3中也不起作用。

这些区域是多边形,因此使用定位的div作为叠加层是不可行的。

编辑:我刚刚发现,我可以在花式框中使用<img>替换<canvas>,而无需失去缩放功能。因此,从理论上讲,可以使用画布路径和isPointInPath()方法。不幸的是,我需要多个路径,这需要Path2D对象,而该对象在IE中不可用...

1 个答案:

答案 0 :(得分:0)

由于问题中讨论的所有选项均不可行,并且我发现了pnpoly point in polygon algorithm,所以我自己完成了全部操作。我将坐标作为百分比(为了不受大小限制)放在如下所示的javascript对象数组中:

    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

由于pnpoly函数分别需要x和y的顶点,因此我已经以这种方式提供了坐标。

地图的ID存储在源链接的data属性中:

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

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

pnpolypnrect是作为简单函数提供的,所有这些操作的处理都是在afterShow事件处理程序中完成的:

// 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 )
});

要做的事情:找到触摸设备的解决方案,例如提供一个按钮以显示所有工具提示(可能已旋转90°)。

该页面在线后,我将在此处提供一个链接以使其正常运行...