Пользовательская карта изображений с несколькими полигонами — Добавлен значок карты

#javascript #html #css #svg

#javascript #HTML #css #svg

Вопрос:

У меня есть карта изображений — с 20 интерактивными точками-маркерами, созданными с использованием полигонов.

Я хочу добавить значок маркера в центре каждого полигона, который, если возможно, меняет цвет при активации (щелчке), может использовать SVG или .png для закрепления.

При нажатии они добавляют # 1, # 2 и т.д. К URL — используется для заполнения ТЕКСТОВОЙ области на странице контактной информацией.

Каждая область добавляется на карту с помощью инструкции foreach.

пробовал использовать «символ», но он не может попасть в центр внутри каждого полигона.

 <svg id="svgmap<?= $bID; ?>" version="1.1" xmlns="http://www.w3.org/2000/svg"       xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;top:0;left:0;" viewBox="0 0 <?= $width; ?> <?= $height; ?>"  >
<defs>
<symbol id="pin" viewBox='0 0 24 24'><title>location on</title>
    <path d='M12 2c-3.87 0-7 3.13-7 7 0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z'></path>
    <path d='M0 0h24v24h-24z' fill='none'></path>
</symbol>
</defs>

 <?php  
foreach($areas as $area) {
        $points = trim($area['mapdata']);
$url = $sec->sanitizeURL($area['linked_url']);
 ?>
<a class="arrow" id="pin" xlink:href="<?= $url; ?>" xlink:title="<?=  $title; ?>" <?= ($area['newWindow'] amp;amp; !($area['forceDownload'] amp;amp; $area['type'] == 'file') ? 'target="_blank"' : '')?>>
<g id="my-group">
<use xlink:href="#pin" x="" y="" width="30px" height="30px" />
<polygon points="<?= $points; ?>" fill="url(#img1)" filter="url(#sparklin)" opacity="1" />  
</g>
 </a> 

}
  

Отображает все значки в верхнем левом углу карты.. Не по центру каждого раздела.

Обновления


Хорошо, используя приведенное ниже решение: я создал следующую функцию над своим циклом, но я столкнулся с ошибкой «Uncaught TypeError: poly.getBBox не является функцией в myfunction (контакты: 508) в contacts: 566»

[код]

 <script>
                        function myfunction(){
                        // the bounding box of the polygon
                            var BB = null;
                            var BB = poly.getBBox();
                            // the center of the polygon
                            var center = {x:BB.x   BB.width/2,
                                          y:BB.y   BB.height/2}
                            //the size of the symbol
                            var symbol = {w:30,h:30}
            // set the values for the x and y attributes of the symbol
        theUse.setAttributeNS(null, "x",center.x - symbol.w/2)
        theUse.setAttributeNS(null, "y",center.y - symbol.h)
                        };
                    </script>
//Code inside foreach

    <a class="arrow" xlink:href="<?= $url; ?>" xlink:title="<?=  $title; ?>">


                        <polygon id="poly" points="<?= $points; ?>" fill="none" opacity="1" />  
                        <use id="theUse" xlink:href="#pin" x="20" y="20" width="40" height="40" />

                        </a> 

                        <script>
                        myfunction();
                        </script>
[/code]
  

Я полагаю, что это проблема с poly.getBBox(); Возможно, это связано с повторным использованием идентификатора poly? Нужно ли добавлять количество в цикл с шагом для каждого цикла.

Ответ №1:

Одним из способов сделать это было бы использовать ограничивающую рамку многоугольника, чтобы найти центр, а затем расположить символ относительно этого центра.

Далее идет пример, в котором я использую упрощенную версию вашего кода. В этом случае кончик булавки находится в центре полигона-

Наблюдение: в вашем коде id="pin" дважды.

 // the bounding box of the polygon
let BB = poly.getBBox();
// the center of the polygon
let center = {x:BB.x   BB.width/2,
              y:BB.y   BB.height/2}
//the size of the symbol
let symbol = {w:30,h:30}
// set the values for the x and y attributes of the symbol
theUse.setAttributeNS(null, "x",center.x - symbol.w/2)
theUse.setAttributeNS(null, "y",center.y - symbol.h)  
 svg{position:absolute;top:0;left:0; width:90vh}  
 <svg id="svgmap" viewBox="0 0 100 100"  >
<defs>
<symbol id="pin" viewBox='0 0 24 24'>
    <path id="thePath" d='M12 2c-3.87 0-7 3.13-7 7 0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z'></path>
    <path d='M0 0h24v24h-24z' fill='none'></path>
</symbol>
</defs>


<a class="arrow" id="a_pin" xlink:href="kk" xlink:title="title">
<g id="my-group">
  
<polygon id="poly" points="10,10 90,30 70,70 24,80" fill="gold"  opacity="1" />
<use id="theUse" xlink:href="#pin" x="20" y="20" width="30" height="30" />
  
</g>
</a> 
</svg>  

Обновить

В случае, если у вас есть несколько полигонов, вам нужно выполнить цикл по <a class=arrow элементам следующим образом:

 let aPins = svgmap.querySelectorAll(".arrow");

aPins.forEach(a => {
  let poly = a.querySelector("polygon");
  let pin = a.querySelector("use");
  centerPin(poly, pin);
});

function centerPin(poly, pin) {
  // the bounding box of the polygon
  let BB = poly.getBBox();
  // the center of the polygon
  let center = {
    x: BB.x   BB.width / 2,
    y: BB.y   BB.height / 2
  };
  //the size of the symbol
  let symbol = { w: 30, h: 30 };
  // set the values for the x and y attributes of the symbol
  pin.setAttributeNS(null, "x", center.x - symbol.w / 2);
  pin.setAttributeNS(null, "y", center.y - symbol.h);
}  
 svg {
  position: absolute;
  top: 0;
  left: 0;
  width: 90vh;
  border: 1px solid;
}  
 <svg id="svgmap" viewBox="0 0 200 100"  >
<defs>
<symbol id="pin" viewBox='0 0 24 24'>
    <path id="thePath" d='M12 2c-3.87 0-7 3.13-7 7 0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z'></path>
    <path d='M0 0h24v24h-24z' fill='none'></path>
</symbol>
</defs>


<a class="arrow" id="a_pin1" xlink:href="kk" xlink:title="title">
<g id="my-group">  
<polygon points="10,10 90,30 70,70 24,80" fill="gold"  opacity="1" />
<use  xlink:href="#pin" x="20" y="20" width="30" height="30" />  
</g>
</a> 
  
<a class="arrow" id="a_pin2" xlink:href="kk" xlink:title="title">
<g id="my-group">  
<polygon points="90,30 70,70 133,90 180,25" fill="skyBlue"   opacity="1" />
<use  xlink:href="#pin" x="20" y="20" width="30" height="30" />  
</g>
</a>  
  
</svg>  

Комментарии:

1. Хорошо, спасибо, это вроде как работает. Он запускает скрипт и выполняет 1-е действие в цикле. Но имеет ошибки из-за неперехваченной ошибки типа: poly.getBBox не является функцией в myfunction (контакты: 508) в контактах: 566 Смотрите мои обновления выше

2. Я полагаю, это происходит в вашем коде. В моем коде poly указан идентификатор полигона. Если в вашем коде есть несколько полигонов, вам может потребоваться получить ссылку на каждый полигон с помощью чего-то вроде let poly = document.querySelector(whatever

3. Я видел ваше обновление. Поскольку у вас есть несколько <a class="arrow" с полигоном внутри, у вас также есть несколько полигонов с одинаковыми id="poly"