jquery: fancybox 3, адаптивные карты изображений и масштабируемый контент - PullRequest
0 голосов
/ 22 ноября 2018

Я хочу использовать image-maps внутри fancybox 3. Цель - показать горные панорамы, где пользователь мог бы указать на вершину и получить имя и данные.Обычная рекомендация - использовать для этого карту изображений на основе SVG, например в этой ручке .Из-за размера изображений важна функция масштабирования fancybox.

Хотя fancybox будет отображать SVG в виде изображения, подобного , в этом пере использование тега <image> невозможно свнешний источник внутри файла SVG.Еще хуже: файлы SVG, используемые в качестве источника тега <img>, не будут отображать функциональность карты ( см. Этот вопрос ).

Я попытался заменить тег <img> в fancybox натег <object>, использующий файл SVG в качестве атрибута данных.Это показывает изображение с функциональностью карты правильно, но fancybox больше не будет увеличивать его.

Так что в конечном итоге вопрос сводится к тому, как я могу сделать <object> (или встроенный SVG или iframe) масштабируемым, как изображение в fancybox 3.

Я открыт дляи другие решения.Я хочу использовать fancybox только для того, чтобы внешний вид и использование были такими же, как и у других галерей изображений на той же странице.Я бы даже использовал старый стиль <map>, где я бы изменил координаты, используя jquery, чтобы он был адаптивным.Я попробовал это, прикрепив карту вручную в инструментах разработчика, а также программно в обработчике событий afterLoad, но, очевидно, это не работает и в fancybox 3.

Области являются полигонами, поэтому использование позиционированных div в качестве оверлеев не является решением.

Редактировать: Я только что обнаружил, что могу заменить <img> на <canvas> в fancybox без потери масштабаи перетащите функциональность.Так что теоретически можно было бы использовать пути холста и метод isPointInPath().К сожалению, мне нужно более одного пути, для которого требуется объект Path2D, который недоступен в IE ...

1 Ответ

0 голосов
/ 25 ноября 2018

Поскольку все варианты, обсуждаемые в этом вопросе, оказались неосуществимыми, и я обнаружил точку pnpoly в алгоритме многоугольника , я все сделал сам.Я помещаю координаты в процентах (чтобы быть независимыми от размера) в массиве объектов 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 отдельно, я предоставляюкоординирует этот путь уже.

Идентификатор карты хранится в атрибуте данных в исходной ссылке:

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

pnpoly и pnrect предоставляются в виде простых функций, обработка которых выполняется в обработчике событий 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 °).

Как только страница появится в сети, я предоставлю ссылку, чтобы увидеть, как она работает ...

...