Skip to content

Instantly share code, notes, and snippets.

@newbornfrontender
Created May 23, 2019 07:43
Show Gist options
  • Save newbornfrontender/0d13a2c903e0f642e03e5a05a1addad4 to your computer and use it in GitHub Desktop.
Save newbornfrontender/0d13a2c903e0f642e03e5a05a1addad4 to your computer and use it in GitHub Desktop.
new map
<template id="search-result-card">
<div class="clinic-card-preview">
<a class="clinic-card-preview__title-link" href="">
<h3 class="clinic-card-preview__title"></h3>
</a>
<ul class="clinic-card-preview__location">
<li class="clinic-card-preview__location-item clinic-card-preview__location-item_metro"></li>
<li class="clinic-card-preview__location-item clinic-card-preview__location-item_geo"></li>
</ul>
<p class="clinic-card-preview__time"></p>
<div class="clinic-card-preview__feedback">
<!-- rating -->
<p class="clinic-card-preview__score"></p>
<a class="clinic-card-preview__comments" href=""></a>
</div>
</div>
</template>
<div class="results-list"></div>
<div id="map" class="map"></div>
import $ from 'jquery';
// =============================================================================
// $(document).ready(() => {
// // Создание кластеризатора с произвольным HTML-макетом иконки кластера
// class CustomCluster {
// // Зададаем макет метки кластера
// createCluster() {
// return ymaps.templateLayoutFactory.createClass(
// '<div class="ymap-cluster-icon">{{ properties.geoObjects.length }}</div>',
// );
// }
// // Зададаем активную область иконки кластера
// createIconShape() {
// return {
// type: 'Circle',
// coordinates: [0, 0],
// radius: 25,
// };
// }
// }
// const init = () => {
// const clusterer = new CustomCluster;
// const map = new ymaps.Map(
// 'map',
// {
// center: [55.76, 37.64],
// zoom: 10,
// },
// {
// searchControlProvider: 'yandex#search',
// },
// );
// const objectManager = new ymaps.ObjectManager({
// // Включает кластеризацию
// clusterize: true,
// // Устанавливает размер ячейки кластеризации в пикселях
// gridSize: 32,
// });
// objectManager.objects.options.set({
// // Указываем тип макета
// iconLayout: 'default#imageWithContent',
// // Добавляем своё изображение иконки метки
// iconImageHref: 'img/marker.svg',
// // Указываем размеры метки
// iconImageSize: [50, 50],
// // Изменяем положение левого верхнего угла иконки относительно её точки привязки
// iconImageOffset: [-25, -25],
// // Не скрывать метку при открытии балуна
// hideIconOnBalloonOpen: false,
// });
// objectManager.clusters.options.set({
// clusterIconLayout: clusterer.createCluster(),
// clusterIconShape: clusterer.createIconShape(),
// });
// map.geoObjects.add(objectManager);
// $.ajax({
// url: 'data.json',
// }).done((data) => {
// objectManager.add(data);
// });
// };
// ymaps.ready(init);
// });
// =============================================================================
$(document).ready(() => {
// Создание кластеризатора с произвольным HTML-макетом иконки кластера
class CustomCluster {
// Зададаем макет метки кластера
createCluster() {
return ymaps.templateLayoutFactory.createClass(
'<div class="ymap-cluster-icon">{{ properties.geoObjects.length }}</div>',
);
}
// Зададаем активную область иконки кластера
createIconShape() {
return {
type: 'Circle',
coordinates: [0, 0],
radius: 25,
};
}
}
const init = () => {
const coords = [
[56.023, 36.988],
[56.025, 36.981],
[56.02, 36.981],
[56.021, 36.983],
[56.027, 36.987],
];
const geoObjects = [];
const map = new ymaps.Map(
'map',
{
center: [55.76, 37.64],
zoom: 10,
controls: [],
},
{
searchControlProvider: 'yandex#search',
},
);
const cluster = new CustomCluster();
const CustomBalloonLayout = ymaps.templateLayoutFactory.createClass(
`
<div class="ymap-popover">
<a class="ymap-popover-close" href="/">
<span></span>
</a>
<div class="ymap-popover-arrow"></div>
<div class="ymap-popover-inner clinic-card-preview">
$[[options.contentLayout observeSize minWidth=268 maxWidth=268]]
</div>
</div>
`,
{
// Строим экземпляр макета на основе шаблона и добавляем его в родительский HTML-элемент
build() {
this.constructor.superclass.build.call(this);
this._$element = $('.ymap-popover', this.getParentElement());
this.applyElementOffset();
this._$element.find('.ymap-popover-close').on('click', $.proxy(this.onCloseClick, this));
},
// Удаляем содержимое макета из DOM
clear() {
this._$element.find('.ymap-popover-close').off('click');
this.constructor.superclass.clear.call(this);
},
// Метод будет вызван системой шаблонов API при изменении размеров вложенного макета
onSublayoutSizeChange() {
CustomBalloonLayout.superclass.onSublayoutSizeChange.apply(this, arguments);
if (!this._isElement(this._$element)) {
return;
}
this.applyElementOffset();
this.events.fire('shapechange');
},
// Сдвигаем балун, чтобы "хвостик" указывал на точку привязки
applyElementOffset() {
this._$element.css({
left: -(this._$element[0].offsetWidth / 2),
// По какой-то причине prettier и stylelint считают строку ниже за CSS
// stylelint-disable
top: this._$element.find('.ymap-popover-arrow')[0].offsetHeight + 13,
});
},
// Закрываем балун при клике на крестик, кидая событие "userclose" на макете
onCloseClick(e) {
e.preventDefault();
this.events.fire('userclose');
},
// Используется для автопозиционирования (balloonAutoPan)
getShape() {
if (!this._isElement(this._$element)) {
return CustomBalloonLayout.superclass.getShape.call(this);
}
var position = this._$element.position();
return new ymaps.shape.Rectangle(
new ymaps.geometry.pixel.Rectangle([
[position.left, position.top],
[
position.left + this._$element[0].offsetWidth,
position.top +
this._$element[0].offsetHeight +
this._$element.find('.ymap-popover-arrow')[0].offsetHeight,
],
]),
);
},
_isElement(element) {
return element && element[0] && element.find('.ymap-popover-arrow')[0];
},
},
);
const CustomBalloonContentLayout = ymaps.templateLayoutFactory.createClass(
`
<a class="clinic-card-preview__title-link" href="$[properties.balloonTitleLink]">
<h3 class="clinic-card-preview__title">$[properties.balloonTitleText]</h3>
</a>
<ul class="clinic-card-preview__location">
<li class="clinic-card-preview__location-item">$[properties.balloonMetro]</li>
<li class="clinic-card-preview__location-item">$[properties.balloonGeo]</li>
</ul>
<p class="clinic-card-preview__time">$[properties.balloonTime]</p>
<div class="clinic-card-preview__feedback">
$[properties.balloonRating]
<p class="clinic-card-preview__score">$[properties.balloonScore]</p>
<a class="clinic-card-preview__comments" href="$[properties.balloonCommentsLink]">$[properties.balloonCommentsText]</a>
</div>
`,
);
$.ajax({
url: 'data.json',
}).done((data) => {
data.forEach((item) => {
const {
id,
geometry: { coordinates },
properties,
} = item;
// ---------------------------------------------------------------------
const resultsList = document.querySelector('.results-list');
const resultTemplate = document.querySelector('#search-result-card');
// Получаем элемент из template тэга
const getNodeFromTemplate = (template, node) => {
return template.content.querySelector(node);
};
// Добавляем текст
const setTextForTemplateNode = (node, text) => {
return getNodeFromTemplate(resultTemplate, node).textContent = text;
};
// Добавляем путь ссылки
const setHrefForTemplateLink = (node, href) => {
return getNodeFromTemplate(resultTemplate, node).href = href;
};
const templateFeedback = getNodeFromTemplate(resultTemplate, '.clinic-card-preview__feedback');
getNodeFromTemplate(resultTemplate, '.clinic-card-preview').dataset.coordinates = coordinates;
setTextForTemplateNode('.clinic-card-preview__title', properties.balloonTitleText);
setHrefForTemplateLink('.clinic-card-preview__title-link', properties.balloonTitleLink);
setTextForTemplateNode('.clinic-card-preview__location-item_metro', properties.balloonMetro);
setTextForTemplateNode('.clinic-card-preview__location-item_geo', properties.balloonGeo);
setTextForTemplateNode('.clinic-card-preview__time', properties.balloonTime);
function htmlToElement(html) {
var template = document.createElement('template');
html = html.trim(); // Never return a text node of whitespace as the result
template.innerHTML = html;
return template.content.firstChild;
}
templateFeedback.insertBefore(htmlToElement(properties.balloonRating), getNodeFromTemplate(resultTemplate, '.clinic-card-preview__score'))
setTextForTemplateNode('.clinic-card-preview__score', properties.balloonScore);
setTextForTemplateNode('.clinic-card-preview__comments', properties.balloonCommentsText);
setHrefForTemplateLink('.clinic-card-preview__comments', properties.balloonCommentsLink);
resultsList.appendChild(resultTemplate.content.cloneNode(true));
// ---------------------------------------------------------------------
geoObjects[id] = new ymaps.GeoObject(
{
geometry: {
type: 'Point',
coordinates,
},
properties,
},
{
// Указываем тип макета
iconLayout: 'default#imageWithContent',
// Добавляем своё изображение иконки метки
iconImageHref: 'img/marker.svg',
// Указываем размеры метки
iconImageSize: [50, 50],
// Изменяем положение левого верхнего угла иконки относительно её точки привязки
iconImageOffset: [-25, -25],
// Не скрывать метку при открытии балуна
hideIconOnBalloonOpen: false,
balloonShadow: false,
balloonLayout: CustomBalloonLayout,
balloonContentLayout: CustomBalloonContentLayout,
balloonPanelMaxMapArea: 0,
},
);
});
const clusterer = new ymaps.Clusterer({
gridSize: 32,
clusterIconLayout: cluster.createCluster(),
clusterIconShape: cluster.createIconShape(),
});
clusterer.add(geoObjects);
map.geoObjects.add(clusterer);
});
};
ymaps.ready(init);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment