Я.Карта с кластерами и карточками объектов

Модификатор подходит для проектов, в которых нужно показать галерею из фотографий

jQuery
Код скопирован!
Скопировать код
Код скопирован!
Скопировать код
Для корректной работы блоков подключите библиотеку jQuery:
Инструкция с подключением кода
Настройки сайта -> Еще -> Подключить jQuery на страницах сайта
  1. Создаем html-элемент
  2. Задаем ему ширину и высоту по 100%
  3. Задаем html-элементу позиционирование CONTAINER: WINDOW (X: LEFT, Y: TOP)
  4. Копируем в него код
  1. По комментариям в коде заменяем цвет необходимых элементов
  2. Для изменения цвета метки, скачиваем svg файл
  3. В Figma заменяем черный цвет элементов на необходимый
  4. Загружаем получившийся svg файл на Тильду (в любой блок для изображений, и копируем ссылку на изображение)
  5. Заменяем ссылку на файл в строках 252, 257, 262
В коде блока T123 добавлены массив-образец {в таких скобках}, который необходимо продублировать необходимое количество раз и настроить:
  1. Заменить координаты метки
  2. Заменить изображения объектов
  3. Заменить описание и адрес
  4. Заменить цену и кол-во спальных мест
  5. Заменить ссылку для кнопки "Подробнее"
  6. При необходимости, можно удалить строку с лишним параметром
Шаг 1
Добавляем Zero блок
Шаг 2
Настраиваем стили для карточек
Шаг 3
Добавляем блок T123 и копируем в него код
Шаг 4
Настраиваем информацию для карточек
<style>
:root {
--green:#141414; /* Основной цвет: используется для фона кластера и кнопок */
--green-hovered:#000; /* Цвет при наведении на элементы */
--text-color:#fff; /* Основной цвет текста (белый) */
--border:5px; /* Радиус скругления углов */
}

#karta {
width: 100%; /* Карта растягивается на всю ширину */
height: 100%; /* Карта растягивается на всю высоту родительского блока */
padding: 0; /* Убираем внутренние отступы */
margin: 0; /* Убираем внешние отступы */
}

.ymaps-2-1-79-balloon__content ymaps {
height: 100% !important; /* Высота контента на всю доступную */
display: flex; /* Используем флексбокс для вертикального расположения */
flex-direction: column; /* Располагаем элементы по вертикали */
width: 250px; /* Ширина всплывающего окна */
}

.ymaps-2-1-79-balloon__content ymaps img {
width: 100%!important; /* Картинка во всплывающем окне занимает всю ширину */
}

.ymaps-2-1-79-balloon {
width:300px; /* Ширина самого балуна */
}

.cluster-item {
display: flex; /* Располагаем элементы кластера с помощью флексбокса */
flex-direction: column; /* Располагаем их вертикально */
}

.ymaps-2-1-79-default-cluster {
line-height: normal!important; /* Убираем лишние расстояния между строками */
height:auto !important; /* Высота подстраивается под контент */
width:fit-content!important; /* Ширина автоматически подстраивается под контент */
}

.custom-cluster-icon {
width:fit-content; /* Ширина по содержимому */
height: fit-content; /* Высота по содержимому */
border-radius: var(--border); /* Скругление углов, заданное в переменной */
text-align: center; /* Текст по центру */
font-weight: 400; /* Толщина шрифта */
color: #fff; /* Цвет текста — белый */
background-color: var(--green); /* Цвет фона иконки кластера */
line-height: normal; /* Обычный межстрочный интервал */
display: flex; /* Используем флексбокс */
justify-content: center; /* Центруем по горизонтали */
align-items: center; /* Центруем по вертикали */
padding: 3px; /* Внутренние отступы */
gap: 5px /* Расстояние между элементами внутри */
}

.custom-cluster-icon .count {
background-color: white; /* Белый фон для счётчика */
color: var(--green); /* Цвет текста — основной */
border-radius: 50px; /* Скругление — делает круг */
width:15px; /* Ширина кружка */
height: 15px; /* Высота кружка */
display: flex; /* Центруем число внутри */
align-items: center;
justify-content: center;
font-size: 9px; /* Размер цифры */
font-weight: 600; /* Жирность цифры */
}

.custom-cluster-icon .info {
white-space: nowrap; /* Запрещает перенос текста */
padding-right: 3px; /* Отступ справа */
}

.baloon_info {
background: #fff; /* Белый фон балуна */
border-radius: 20px; /* Скругление углов */
padding: 15px; /* Внутренние отступы */
max-width: 320px; /* Максимальная ширина */
max-height: 400px; /* Максимальная высота */
overflow-y: scroll; /* Прокрутка по вертикали */
}

.baloon_info img {
max-width: 100%; /* Картинки не выходят за границы */
}

.custom-content {
margin-bottom: 20px; /* Отступ снизу */
}

.ymaps-2-1-79-balloon {
box-shadow: none; /* Убираем тень */
}

.ymaps-2-1-79-balloon__layout {
background: transparent; /* Прозрачный фон */
}

.ymaps-2-1-79-balloon__close + .ymaps-2-1-79-balloon__content {
padding: 15px; /* Отступ внутри */
border-radius: var(--border); /* Скругление углов */
background: #fff; /* Белый фон */
margin-right: 0; /* Убираем отступ справа */
}

.ymaps-2-1-79-balloon__content ymaps {
height: 100%!important; /* Контент растягивается по высоте */
}

.ymaps-2-1-79-balloon__content .costum-title {
display: none; /* Скрываем заголовок по умолчанию */
}

.ymaps-2-1-79-b-cluster-tabs__menu-item-text .costum-title {
display: block; /* Показываем заголовок в табах */
}

.costum-content {
height: 100%; /* Высота на 100% родителя */
display: flex; /* Располагаем содержимое с помощью флексбокса */
flex-direction: column; /* Элементы идут вертикально */
font-size: 13px; /* Размер текста */
line-height: 20px; /* Межстрочный интервал */
}

.costum-content h2 {
color: var(--text-color); /* Цвет заголовка */
padding: 20px 0; /* Отступы сверху и снизу */
}

.costum-content p {
color: var(--text-color); /* Цвет параграфа */
}

.costum-content img {
width: 220px; /* Ширина изображения */
height: 180px; /* Высота изображения */
object-fit: cover; /* Картинка заполняет область без искажений */
border-radius: var(--border); /* Скруглённые углы */
margin-bottom: 20px; /* Отступ снизу */
}

.costum-btn {
color: #fff!important; /* Цвет текста кнопки */
background: #141414; /* Фон кнопки */
border-radius: 5px; /* Скругление кнопки */
padding: 10px 10px; /* Внутренние отступы */
margin-top: 10px; /* Отступ сверху */
max-width: fit-content; /* Ширина подстраивается под контент */
}

.ymaps-2-1-79-b-cluster-tabs__item-header .accordion-header,
.ymaps-2-1-79-balloon-content__header .accordion-header {
background: #fff; /* Белый фон заголовка аккордеона */
color: var(--text-color); /* Цвет текста */
font-size: 15px; /* Размер текста */
pointer-events: none; /* Отключаем клики */
}

.costum-content .costum-btn:hover {
color: var(--green)!important; /* Цвет текста при наведении */
background: var(--green-hovered); /* Фон при наведении */
}

.accordion-header {
font-size: 12px; /* Размер текста */
font-weight: 500; /* Жирность */
background-color: var(--green-hovered); /* Цвет фона */
color: var(--green); /* Цвет текста */
padding: 10px; /* Внутренний отступ */
border-radius: var(--border); /* Скругление */
width: 100%; /* Полная ширина */
}

.accordion-header:hover {
background-color: var(--green); /* Цвет при наведении */
color: #fff; /* Цвет текста при наведении */
}

.ymaps-2-1-79-b-cluster-tabs__menu-item_current_yes {
border-radius: 10px 0 0 10px; /* Скругление активного таба */
}

.ymaps-2-1-79-b-cluster-tabs__menu-item_current_yes .accordion-header {
background-color: var(--green); /* Фон активного заголовка */
color: #fff; /* Цвет текста активного заголовка */
}

.accordion-content {
padding: 5px; /* Внутренние отступы */
border: 1px solid #141414; /* Рамка */
background-color: #fff; /* Фон */
border-radius: var(--border); /* Скругление */
}

.ymaps-2-1-79-b-cluster-tabs__menu-item {
padding: 0; /* Убираем отступы */
}

.ymaps-2-1-79-b-cluster-content {
display: flex; /* Флекс-контейнер */
max-width: 320px; /* Максимальная ширина */
}

.ymaps-2-1-79-b-cluster-tabs__section_type_nav {
max-width: 90px; /* Ширина панели навигации в табах */
}

.ymaps-2-1-79-b-cluster-tabs__item-body {
padding-right: 0; /* Убираем правый отступ */
}

@media screen and (max-width:640px) {
#karta {
width: 100%;
height: 100%;
}

.ymaps-2-1-79-balloon__close + .ymaps-2-1-79-balloon__content {
max-width: 300px; /* Уменьшаем ширину балуна на мобилке */
}

.costum-content img {
width: 155px; /* Уменьшаем размер картинки */
height: 105px;
}

.ymaps-2-1-79-b-cluster-content {
display: flex;
max-width: 320px;
}

.custom-content {
max-width: 200px!important; /* Ограничиваем ширину */
}

.ymaps-2-1-79-b-cluster-tabs__section_type_nav {
min-width: 80px!important;
}

.ymaps-2-1-79-balloon__content ymaps {
max-width: 250px!important;
width: 100%;
}
}

.ymaps-2-1-79-placemark_theme_darkgreen {
background: url(https://static.tildacdn.com/tild6566-3036-4333-b366-306334373362/svgexport-1_70_1.svg); /* Кастомный маркер */
background-position: 0 40px;
}

.ymaps-2-1-79-placemark__l {
background: url(https://static.tildacdn.com/tild6566-3036-4333-b366-306334373362/svgexport-1_70_1.svg)!important; /* Левая часть */
background-position: 0 0;
}

.ymaps-2-1-79-placemark__r {
background: url(https://static.tildacdn.com/tild6566-3036-4333-b366-306334373362/svgexport-1_70_1.svg)!important; /* Правая часть */
background-position: 80px 0!important;
}
</style>
<script>
var objects = [
{
coordinates: [55.545105, 37.55964], // здесь задаем координаты для метки
image: "https://static.tildacdn.com/tild3266-3739-4135-b933-623964303461/thumbnail_00c55482-d.jpg", // фото объекта
description: "1-к квартира, 37м²", // заголовок (над фото)
address: "ул. Изюмская, д.46к2", // адрес (под фото)
price: 2200, // цена
sleepingPlaces: 2, // спальных мест
link: "#1" //ссылка для кнопки "Подробнее"
},
{
coordinates: [55.548375, 37.534469],
image: "https://static.tildacdn.com/tild6433-6665-4436-b665-353430336633/thumbnail_b8166acc-e.jpg",
description: "1-к квартира, 37м²",
address: "Плавский проезд, д.5",
price: 2700,
sleepingPlaces: 3,
link: "#2"
},
{
coordinates: [55.545722, 37.534325],
image: "https://static.tildacdn.com/tild6132-3930-4338-b261-666630376232/thumbnail_3c73912f-1.jpg",
description: "2-к квартира, 54м²",
address: "ул. Адмирала Лазарева, д.19",
price: 2700,
sleepingPlaces: 4,
link: "#3"
}
];
</script>

<script>
$(function(){

ymaps.ready(function () {
var karta = new ymaps.Map("karta", {
center: [55.755864, 37.617698],
zoom: 10
});

var geoObjects = [];
var clusterer = new ymaps.Clusterer({
groupByCoordinates: false,
clusterDisableClickZoom: true,
clusterIcons: [{
href: '', // Путь к картинке (если нужна)
size: [80, 80],
offset: [-40, -40]
}],
clusterIconContentLayout: ymaps.templateLayoutFactory.createClass(
'<div class="custom-cluster-icon"><span class="count">{{ properties.geoObjects.length }}</span> <span class="info"> от {{ properties.minPrice }} ₽</span></div>'
),
// Кастомный макет для балуна кластера
clusterBalloonContentLayout: ymaps.templateLayoutFactory.createClass(
'<div style="max-height: 320px; overflow-y: auto; width: 100%;overflow-x: hidden;">' +
'{% for geoObject in properties.geoObjects %}' +
'<div class="cluster-item" style="margin-bottom: 10px;">' +
'<strong>{{ geoObject.properties.description }}</strong>' +
'<img src="{{ geoObject.properties.image }}" alt="{{ geoObject.properties.name }}" style="width: 100%; height: auto; max-height: 150px; margin: 5px 0;">' +
'<p>Адрес: {{ geoObject.properties.address }}</p>' +
'<p>Спальных мест: {{ geoObject.properties.sleepingPlaces }}</p>' +
'<p>Цена: от {{ geoObject.properties.price }} ₽</p>' +
'<a class="costum-btn" href="{{ geoObject.properties.link }}" target="_blank">Подробнее</a>' +
'</div>' +
'<hr>' +
'{% endfor %}' +
'</div>'
),
clusterBalloonPanelMaxMapArea: 0 // Отключает автоматическое увеличение балуна кластера
});

objects.forEach(function (obj) {
var placemark = new ymaps.Placemark(obj.coordinates, {
description: obj.description,
image: obj.image,
address: obj.address,
sleepingPlaces:obj.sleepingPlaces,
price: obj.price,
link: obj.link,
balloonContentHeader: '<strong>' + obj.description + '</strong>',
balloonContentBody: '<img src="' + obj.image + '" alt="' + obj.name + '" style="width: 100px; height: auto;">' +
'<p>Адрес: ' + obj.address + '</p>' +
'<p>Спальных мест: ' + obj.sleepingPlaces + '</p>' +
'<p>Цена: от ' + obj.price + ' ₽</p>' +
'<a class="costum-btn" href="' + obj.link + '">Подробнее</a>',
iconContent: obj.price + ' ₽'
}, {
preset: 'islands#darkGreenStretchyIcon'
});

geoObjects.push(placemark);
});

clusterer.add(geoObjects);
karta.geoObjects.add(clusterer);

// Вычисляем минимальную цену сразу после добавления объектов в кластер
function updateClusterMinPrices() {
clusterer.getClusters().forEach(function(cluster) {
var clusterGeoObjects = cluster.getGeoObjects();
var minPrice = Math.min.apply(null, clusterGeoObjects.map(function(geoObject) {
return parseInt(geoObject.properties.get('iconContent').replace(' ₽', ''));
}));
cluster.properties.set('minPrice', minPrice);
});
}

updateClusterMinPrices();

clusterer.events.add('objectsadd', updateClusterMinPrices);
karta.events.add('boundschange', function(e) {
if (e.get('newZoom') !== e.get('oldZoom')) {
updateClusterMinPrices();
}
});
});

});
</script>
Шаблон страницы
Код скопирован!
67969989
Нажми, чтобы скопировать номер
Текст скопирован в буфер обмена!
Текст скопирован в буфер обмена!
Текст скопирован в буфер обмена!
Вам также может быть интересно:
Pro подписка
Pro подписка
Модификации
Модификации
Модификации
Pro подписка
Подпишитесь на наши обновления в телеграм