/ Scripts & jquery / Посты — метки на карте

Посты — метки на карте

HIT

11.08.2018

1151

Пытаясь реализовать удобный функционал по созданию меток на интерактивной карте я пришел к следующей системе. Заводим произвольный тип записи и таксономии чтобы структурировать и удобно манипулировать городами и точками.

Основа

В основе решения находиться плагин Oi Yandex.Maps for WordPress (хотя я использую его только частично), который в свою очередь основан на Яндекс Api. т.е. плагин необходимо установить.

Создаем пользовательский тип записи city (название не вполне соответствует, т.к. это будут точки. конкретное место в городе):

// Добавляем произвольный тип записей
add_action( 'init', 'register_post_type_city' ); // Использовать функцию только внутри хука init
function register_post_type_city() {
 $labels = array(
     'name' => 'Где купить',
     'singular_name' => 'City', // админ панель Добавить->Функцию
 'add_new' => 'Добавить точку',
 'add_new_item' => 'Добавить новую точку', // заголовок тега <title>
 'edit_item' => 'Редактировать точку',
 'new_item' => 'Новая точка',
 'all_items' => 'Все точки',
 'view_item' => 'Просмотр страницы точки на сайте',
 'search_items' => 'Искать точку',
 'not_found' =>  'Точка не найдена.',
 'not_found_in_trash' => 'В корзине нет точки.',
 'menu_name' => 'Где купить' // ссылка в меню в админке
 );
 $args = array(
 'labels' => $labels,
 'public' => true,
 'show_ui' => true, // показывать интерфейс в админке
 'has_archive' => true, // показывать страницу архива данного типа записей
 'menu_icon' => 'dashicons-location-alt', // иконка dashicons в меню
 'menu_position' => 20, // порядок в меню
 'supports' => array( 'title', 'editor', 'comments', 'author', 'thumbnail'),
     //'taxonomies' => array('cities') // добавляем поддержку стандартных таксономий 'post_tag', 'category', либо пользовательскую 'album' (через запятую)
 );
 register_post_type('city', $args);
}


// Тексты уведомлений для типа постов
add_filter( 'post_updated_messages', 'true_post_type_messages_city' );
function true_post_type_messages_city( $messages ) {
 global $post, $post_ID;
 $messages['city'] = array( // city - название созданного нами типа записей
 0 => '', // Данный индекс не используется.
 1 => sprintf( 'Точка обновлена. Просмотр', esc_url( get_permalink($post_ID) ) ),
 2 => 'Точка обновлёна.',
 3 => 'Точка удалёна.',
 4 => 'Точка обновлена.',
 5 => isset($_GET['revision']) ? sprintf( 'Точка восстановлена из редакции: %s', wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
 6 => sprintf( 'Точка опубликована на сайте. Просмотр', esc_url( get_permalink($post_ID) ) ),
 7 => 'Точка сохранена.',
 8 => sprintf( 'Отправлена на проверку. Просмотр', esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
 9 => sprintf( 'Запланирована на публикацию: %1$s. Просмотр', date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post_ID) ) ),
 10 => sprintf( 'Черновик обновлён. Просмотр', esc_url( add_query_arg( 'preview', 'true', get_permalink($post_ID) ) ) ),
 );
 return $messages;
}


// Произвольные поля для пользовательского типа записей
function true_custom_fields_city() {
add_post_type_support( 'city', 'custom-fields'); // в качестве первого параметра укажите название типа поста
}
add_action('init', 'true_custom_fields_city');

Создаем пользовательскую таксономию (элементами этой таксономии будут города)

// Пользовательская таксономия Город
function add_new_taxonomies() {
 register_taxonomy('cities', // создаем функцию с произвольным именем и вставляем в неё register_taxonomy()
 array('city'),
 array(
 'hierarchical' => false, // true - по типу рубрик, false - по типу меток, по умолчанию - false 
 'labels' => array(
 /* ярлыки, нужные при создании UI, можете не писать ничего, тогда будут использованы ярлыки по умолчанию */
 'name' => 'Город',
 'singular_name' => 'City',
 'search_items' => 'Найти город',
 'popular_items' => 'Популярные города',
 'all_items' => 'Все города',
 'parent_item' => null,
 'parent_item_colon' => null,
 'edit_item' => 'Редактировать город',
 'update_item' => 'Обновить город',
 'add_new_item' => 'Добавить новый город',
 'new_item_name' => 'Название нового города',
 'separate_items_with_commas' => 'Разделяйте города запятыми',
 'add_or_remove_items' => 'Добавить или удалить город',
 'choose_from_most_used' => 'Выбрать из наиболее часто используемых городов',
 'menu_name' => 'Города'
 ),
 'public' => true, // каждый может использовать таксономию, либо только администраторы, по умолчанию - true
 'show_in_nav_menus' => true, // добавить на страницу создания меню
 'show_ui' => true, // добавить интерфейс создания и редактирования
 'show_tagcloud' => true, // нужно ли разрешить облако тегов для этой таксономии
 'update_count_callback' => '_update_post_term_count', // callback-функция для обновления счетчика $object_type
 'query_var' => true, // разрешено ли использование query_var, также можно указать строку, которая будет использоваться в качестве него, по умолчанию - имя таксономии
 'rewrite' => array( // настройки URL пермалинков
 'slug' => 'cities', // ярлык
 'hierarchical' => false // разрешить вложенность
 ),
 )
 );
}
add_action( 'init', 'add_new_taxonomies', 0 );

Города точкам назначать будем как метки.

Произвольные поля

Задаем для записей типа city поля Координаты точки, Название точки, Контакты точки:

// Поле Координаты точки
add_action('add_meta_boxes', 'coordinati_tochka_box');
function coordinati_tochka_box() { add_meta_box('material_box', 'Координаты', 'coordinati_tochka_box_func', 'city', 'normal'); }
function coordinati_tochka_box_func($post){
 $coordinati_tochka = get_post_meta($post->ID, 'coordinati_tochka', 1);
 ?>
 <label><input style="width:100%;" type="text" name="extra[coordinati_tochka]" value="<?php if($coordinati_tochka){echo $coordinati_tochka;}?>" /></label>
 <input type="hidden" name="atb_nonce" value="<?php echo wp_create_nonce(__FILE__); ?>" />
 <?php
}

add_action('save_post', 'coordinati_tochka_box_update');
function coordinati_tochka_box_update($post_id){
 if (!wp_verify_nonce($_POST['atb_nonce'], __FILE__)) return false; // Проверка, что сохраняется именно нужная нам страница.
 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return false; // Проверка, что это не автосохранение
 if (!current_user_can('edit_post', $post_id)) return false; // Проверка, что пользователь может изменять этот пост
 if(!isset($_POST['extra']) ) return false;    // Проверка, что нам пришли все поля
 foreach($_POST['extra'] as $key=>$value){ // Циклом добавляем поля. Можно и в ручную это делать... Но так проще добавить новое поле
 if(empty($value) AND $value != 0){ // Если значение пустое и не равно 0
 delete_post_meta($post_id, $key); // Удаляем это поле из мета-данных
 continue; // Продолжаем
 }
 update_post_meta($post_id, $key, $value); // Обновляем или добавляем мета-данные
 }
 return $post_id;
}



// Поле Название точки
add_action('add_meta_boxes', 'name_tochka_box');
function name_tochka_box() { add_meta_box('material_box_2', 'Название точки', 'name_tochka_box_func', 'city', 'normal'); }
function name_tochka_box_func($post){
 $name_tochka = get_post_meta($post->ID, 'name_tochka', 1);
 ?>
 <label><input style="width:100%;" type="text" name="extra[name_tochka]" value="<?php if($name_tochka){echo $name_tochka;}?>" /></label>
 <input type="hidden" name="atb_nonce" value="<?php echo wp_create_nonce(__FILE__); ?>" />
 <?php
}

add_action('save_post', 'name_tochka_box_update');
function name_tochka_box_update($post_id){
 if (!wp_verify_nonce($_POST['atb_nonce'], __FILE__)) return false; // Проверка, что сохраняется именно нужная нам страница.
 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return false; // Проверка, что это не автосохранение
 if (!current_user_can('edit_post', $post_id)) return false; // Проверка, что пользователь может изменять этот пост
 if(!isset($_POST['extra']) ) return false;    // Проверка, что нам пришли все поля
 foreach($_POST['extra'] as $key=>$value){ // Циклом добавляем поля. Можно и в ручную это делать... Но так проще добавить новое поле
 if(empty($value) AND $value != 0){ // Если значение пустое и не равно 0
 delete_post_meta($post_id, $key); // Удаляем это поле из мета-данных
 continue; // Продолжаем
 }
 update_post_meta($post_id, $key, $value); // Обновляем или добавляем мета-данные
 }
 return $post_id;
}



// Поле Контакты точки
add_action('add_meta_boxes', 'contacts_tochka_box');
function contacts_tochka_box() { add_meta_box('material_box_3', 'Контакты точки', 'contacts_tochka_box_func', 'city', 'normal'); }
function contacts_tochka_box_func($post){
 $contacts_tochka = get_post_meta($post->ID, 'contacts_tochka', 1);
 ?>
 <label><input style="width:100%;" type="text" name="extra[contacts_tochka]" value="<?php if($contacts_tochka){echo $contacts_tochka;}?>" /></label>
 <input type="hidden" name="atb_nonce" value="<?php echo wp_create_nonce(__FILE__); ?>" />
 <?php
}

add_action('save_post', 'contacts_tochka_box_update');
function contacts_tochka_box_update($post_id){
 if (!wp_verify_nonce($_POST['atb_nonce'], __FILE__)) return false; // Проверка, что сохраняется именно нужная нам страница.
 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return false; // Проверка, что это не автосохранение
 if (!current_user_can('edit_post', $post_id)) return false; // Проверка, что пользователь может изменять этот пост
 if(!isset($_POST['extra']) ) return false;    // Проверка, что нам пришли все поля
 foreach($_POST['extra'] as $key=>$value){ // Циклом добавляем поля. Можно и в ручную это делать... Но так проще добавить новое поле
 if(empty($value) AND $value != 0){ // Если значение пустое и не равно 0
 delete_post_meta($post_id, $key); // Удаляем это поле из мета-данных
 continue; // Продолжаем
 }
 update_post_meta($post_id, $key, $value); // Обновляем или добавляем мета-данные
 }
 return $post_id;
}

В последствии в поле Координаты точки мы будем прописывать реальные координаты точки, беря их из карт Яндекс. Поля Название точки и Контакты точки нужны для сопроводительного текста при нажатии на точку, или если точки выводить в виде списка.

Зададим произвольное поле и для таксономии с городами:

// Создание метаполя Координаты для города
function pippin_taxonomy_add_new_meta_field() { // this will add the custom meta field to the add new term page
 ?>
 <div class="form-field">
 <label for="term_meta[custom_term_meta]"><?php _e( 'Example meta field', 'pippin' ); ?></label>
 <input type="text" name="term_meta[custom_term_meta]" id="term_meta[custom_term_meta]" value="">
 <p class="description"><?php _e( 'Enter a value for this field','pippin' ); ?></p>
 </div>
 <?php
}
add_action( 'cities_add_form_fields', 'pippin_taxonomy_add_new_meta_field', 10, 2 );


// Редактирование мета поля
function pippin_taxonomy_edit_meta_field($term) {
 $t_id = $term->term_id;  // put the term ID into a variable
 $term_meta = get_option( "taxonomy_$t_id" ); // retrieve the existing value(s) for this meta field. This returns an array
 ?> 
 <tr class="form-field">
 <th scope="row" valign="top"><label for="term_meta[custom_term_meta]"><?php _e( 'Example meta field', 'pippin' ); ?></label></th>
 <td>
 <input type="text" name="term_meta[custom_term_meta]" id="term_meta[custom_term_meta]" value="<?php echo esc_attr( $term_meta['custom_term_meta'] ) ? esc_attr( $term_meta['custom_term_meta'] ) : ''; ?>">
 <p class="description"><?php _e( 'Enter a value for this field','pippin' ); ?></p>
 </td>
 </tr>
 <?php
}
add_action( 'cities_edit_form_fields', 'pippin_taxonomy_edit_meta_field', 10, 2 );


// Сохранение метаполя
function save_taxonomy_custom_meta( $term_id ) {
 if ( isset( $_POST['term_meta'] ) ) {
 $t_id = $term_id;
 $term_meta = get_option( "taxonomy_$t_id" );
 $cat_keys = array_keys( $_POST['term_meta'] );
 foreach ( $cat_keys as $key ) {
 if ( isset ( $_POST['term_meta'][$key] ) ) { $term_meta[$key] = $_POST['term_meta'][$key]; }
 }
 update_option( "taxonomy_$t_id", $term_meta ); // Save the option array.
 }
}
add_action( 'edited_cities', 'save_taxonomy_custom_meta', 10, 2 );
add_action( 'create_cities', 'save_taxonomy_custom_meta', 10, 2 );

Это поле нужно чтобы вписывать координаты городов, которые придется предварительно уточнять в Яндекс картах.

Найти способ генерации координатов налету по адресу точки или города

Шаблоны вывода

Шаблон archive-city.php — здесь будем выводить список всех городов, причем размечая их по алфавиту. Для меню шаблон доступен по ссылке /city/

<?php $terms = get_terms( 'cities'); ?>

<script type="text/javascript" src="https://api-maps.yandex.ru/2.1/?lang=ru_RU"></script>
<style>.YMaps {position: relative;} .YMaps .oi_yamaps_author_link {position: absolute;bottom: 9px; right:330px; z-index: 999;padding:0;display: table!important;line-height:12px;text-decoration:underline!important;white-space: nowrap!important;font-family: Verdana,serif!important;font-size: 10px!important;padding-left: 2px!important;color: #000!important;background-color: rgba(255, 255, 255, 0.7)!important;border:none;}</style>
<div id="YMaps_0" class="YMaps" style="width:100%;height:720px;"><a class="oi_yamaps_author_link" target="_blank" href="https://oiplug.com/">OiYM</a></div>
<script type="text/javascript">
 ymaps.ready(init);
 function init () {
 var myMap = new ymaps.Map("YMaps_0", {
 center: [47.413167,40.532044],
 zoom: 7
 });
 myMap.controls.add("routeEditor");
 
 <?php foreach( $terms as $term ): ?>
 <?php $term_meta = get_option( "taxonomy_$term->term_id" ); 
 $term_link = get_term_link($term->term_id, 'cities'); ?>
 myPlacemark_1 = new ymaps.Placemark([<?php echo esc_attr( $term_meta['custom_term_meta'] ) ? esc_attr( $term_meta['custom_term_meta'] ) : ''; ?>], 
 {balloonContentHeader: "<a href='<?php echo $term_link; ?>'><?php echo $term->name; ?></a>",},
 {preset: "islands#redDotIcon"}
 );
 myMap.geoObjects.add(myPlacemark_1);
 <?php endforeach; ?>
 }
</script>

<h1 id="title"><i class="fa fa-map-marker" aria-hidden="true"></i> Где купить</h1> 

<div id="all-city">
 <?php global $query_string;
 parse_str($query_string, $args);  // добавляем базовые параметры в массив $args
 $args['posts_per_page'] = -1;  // добавляем/заменяем параметр в массиве
 query_posts( $args ); ?>  

 <?php echo '<div class="city-letter">'; 
 foreach( $terms as $k => $term ){
 $fl = get_first_letter( $term->name );  // первая буква
 $prev_fl = isset( $terms[ ($k-1) ] ) ? get_first_letter( $terms[ ($k-1) ]->name ) : '';
 if( $prev_fl !== $fl ) 
 echo '</div><div class="city-letter"><h3>'.$fl.'</h3>'; // Буква
 printf ( '<a href="%s">%s</a><br>' , get_term_link($term->term_id, 'cities'), $term->name ); // Выводим название записи в виде ссылки на неё
 }
 echo '</div>';
 wp_reset_postdata(); ?>

 <?php // Функция возвращает первую букву переданного в неё слова
 function get_first_letter( $str ){ return mb_substr($str, 0, 1, 'utf-8'); } ?>  
</div>

Выглядеть это должно примерно так:

Шаблон taxonomy-cities.php будет выводить элементы пользовательской таксономии (отдельный город с точками)

<?php $term_slug = get_query_var( 'cities' ); 
$term = get_term_by('slug', $term_slug, 'cities'); 
$term_meta = get_option( "taxonomy_$term->term_id" ); ?>

<script type="text/javascript" src="https://api-maps.yandex.ru/2.1/?lang=ru_RU"></script>
<style>.YMaps {position: relative;} .YMaps .oi_yamaps_author_link {position: absolute;bottom: 9px; right:330px; z-index: 999;padding:0;display: table!important;line-height:12px;text-decoration:underline!important;white-space: nowrap!important;font-family: Verdana,serif!important;font-size: 10px!important;padding-left: 2px!important;color: #000!important;background-color: rgba(255, 255, 255, 0.7)!important;border:none;}</style>
<div id="YMaps_0" class="YMaps" style="width:100%;height:650px;"><a class="oi_yamaps_author_link" target="_blank" href="https://oiplug.com/">OiYM</a></div>
<script type="text/javascript">
 ymaps.ready(init);
 function init () {
 var myMap = new ymaps.Map("YMaps_0", {
 center: [<?php echo esc_attr( $term_meta['custom_term_meta'] ) ? esc_attr( $term_meta['custom_term_meta'] ) : ''; ?>], //найти какая функция отвечает за определение центра, а пока сделать полем
 zoom: 11
 });
 myMap.controls.add("routeEditor");
 
 <?php if ( have_posts() ) : ?>
 <?php while ( have_posts() ) : the_post(); ?> 
 myPlacemark_1 = new ymaps.Placemark([<?php echo get_post_meta($post->ID, 'coordinati_tochka', 1); ?>], //научиться налету конвертировать координаты
 {balloonContentHeader: "<?php echo get_post_meta($post->ID, 'name_tochka', 1); ?>",
 balloonContentBody: "<?php echo get_post_meta($post->ID, 'contacts_tochka', 1); ?>"},
 {preset: "islands#redDotIcon"}
 );
 myMap.geoObjects.add(myPlacemark_1);
 <?php endwhile; ?>
 <?php endif; ?>
 }
</script>

<h1 id="title"><?php echo $term->name; ?></h1>


<?php if ( have_posts() ) : ?><ul> 
<?php while ( have_posts() ) : the_post(); ?>
 
 <li><strong><?php echo get_post_meta($post->ID, 'name_tochka', 1); ?></strong> <?php the_title(); ?> <?php echo get_post_meta($post->ID, 'contacts_tochka', 1); ?></li>
  
<?php endwhile; ?></ul>
<?php endif; ?>

В этом шаблоне мне пришлось оказаться от хлебных крошек от Kama (получалась несуразица) и прописать свои:

<div id="path"><div class="kama_breadcrumbs" itemscope="" itemtype="http://schema.org/BreadcrumbList">
<span itemprop="itemListElement" itemscope="" itemtype="http://schema.org/ListItem"><a href="https://site.ru" itemprop="item"><span itemprop="name">Главная</span></a></span> / 
<a href="/city/" itemprop="item"><span itemprop="name">Где купить</span></a> / <span class="current"><?php echo $term->name; ?></span></div>
</div>

В итоге должно получиться примерно так:

Информация в balloonContentBody

В всплывающий блок balloonContentBody можно вставлять любую верстку html и контент. Пример:

balloonContentBody: "<img src='/wp-content/uploads/2019/09/image.jpg'><br><p>г. Ростов-на-Дону, пр. Космонавтов, 39</p>"

Поделиться в соц. сетях:

  • Похожие записи
  • Комментарии
  • Вложения
API Яндекс.Карт

API Яндекс.Карт

Если нам нужно кастомизировать карту Яндекс, то будет не достаточно подключить ее через iframe, т.к. в нем не будет никаких настроек. Необходимо подключить API Яндекс.Карт Подключаем API Яндекс.Карт На данный Читать далее »

Карта на сайт

Карта на сайт

Для добавления интерактивной карты в раздел контакты, нужно поместить в страницу или шаблон сгенерированный код Yandex карты, Google Map, или 2GIS. На данной странице я собрал популярные решения по добавлению Читать далее »

Записи-метки на картах

Записи-метки на картах

Сделаем функционал привязки записи (любого типа) к картам Google или Yandex. Это может быть востребовано для контактов дилерских центров, филиалов и т.п. Это статья является как бы вступительной теоретической. Более Читать далее »

Добавить комментарий

Пока нет комментариев. Будь первым!

Посты — метки на карте Посты — метки на карте Посты — метки на карте
Интересные фишки для Woocommerce
Рекомендации для васИнтересные фишки для WoocommerceOpttour.ru
Спасибо! Наш менеджер свяжется с Вами в течении 5 минут.