Добавление вращения иконки в mapbox
Проблема с transform: rotate
Привет друзья. Сегодня решил с вами поделиться небольшим мануалом по изменению вращения иконки в mapbox на определенный угол. Как мы знаем за это отвечает свойство в стилях transform: rotate(Ndeg), где N угол вращения.
Однако, я не нашел внятного объяснения решения данной задачи, поскольку в mapbox идет разъяснение как добавить обычное изображение : Add marker to the map
// add markers to map geojson.features.forEach(function(marker) { // create a HTML element for each feature var el = document.createElement('div'); el.className = 'marker'; // make a marker for each feature and add to the map new mapboxgl.Marker(el) .setLngLat(marker.geometry.coordinates) .addTo(map); });
Но как показала практика, проблема возникает на этапе обновления перерисовки карты при масштабировании или перетаскивании карты, так как в созданном HTML элементе <div> с классом marker уже присутствует стиль transform с некими свойствами и они меняются в зависимости от масштабирования или перетаскивания.
В попытках решения
Я попытался самостоятельно добавить в элемент el стиль transform со свойством rotate.
//Here code create marker var el = document.createElement('div'); el.className = 'marker'; el.style.transform += ' rotate(50deg)'; // Here I added 50 deg for example
Но этого хватило только до первой отрисовки карты и маркеров. После каких либо манипуляций свойство rotate удалялось, так как переписывался полностью стиль.
Даже добавив код после добавления карты
//Here code create marker var el = document.createElement('div'); el.className = 'marker'; // make a marker for each feature and add to the map new mapboxgl.Marker(el) .setLngLat(marker.geometry.coordinates) .addTo(map); el.style.transform += ' rotate(50deg)'; // Here I added 50 deg for example
Этого хватило до первого масштабирования.
Я находил несколько статей про попытки решения проблемы, вот одна из них на StackoverFlow: Mapbox Custom Marker Rotation
В ней описывается подобная проблема и попытка решить ее в комментариях разработчиками:
Note that panto or any other form of map update will reset the rotation, make sure to update the rotation after those events.
// В общем здесь описывается, что после любых обновлениях или событиях, нужно обновлять свойство rotate
Т.е. по сути нужно отслеживать событий, каждый раз меняя значения. Однако на мой взгляд это накладывает некие проблемы в будущем, например когда иконок будет больше. Код соответственно становится больше от различных обработчиков.
Решение моей проблемы
Решение проблемы пришло спонтанно. Я решил создать создавать родительский div с изменяющимся свойством transform. В него вкладываем некий элемент и добавляем к нему стили классы. При этом, он не будет меняться при масштабировании или перетаскивании карты.
Вот как я решил эту задачу:
response.source.data.features.forEach(function(marker) { // create a HTML element for each feature var rotate = marker.properties.rotation; // Get property rotation var div = document.createElement('div'); var el = div.appendChild(document.createElement('el')); el.className = 'marker mapboxgl-marker mapboxgl-marker-anchor-center'; el.style.transform = "rotate(" + rotate + "deg)"; el.style.margin = '-15px 0 0 -12px'; var popup = new mapboxgl.Popup({ offset: 10 }) .setHTML(marker.properties.description); new mapboxgl.Marker(div) .setLngLat(marker.geometry.coordinates) .setPopup(popup) .addTo(map); });
Т.е. по сути я создаю родителя и потомка. Потомку добавляю классы имеющиеся у родителя + класс marker в котором описывается картинка. И вдобавок к потомку добавляю стиль transform:rotate(Ndeg) с необходимым мне углом поворота.
Вот как то так я решил данную задачу, буду рад комментариям и более изящному решению со стороны коллег.
Всем удачи!